From: erik Date: Sun, 2 May 2010 10:07:35 +0000 (+0000) Subject: [maven-release-plugin] copy for tag wamblee-utils-0.2.2 X-Git-Tag: wamblee-utils-0.2.2 X-Git-Url: http://wamblee.org/gitweb/?a=commitdiff_plain;h=96c8961955a306314dfe0cf9ca192252de39fc1c;hp=680cb4c2d0b10909a2cdd3e7f73d8998a74441c1;p=utils [maven-release-plugin] copy for tag wamblee-utils-0.2.2 --- diff --git a/TODO.txt b/TODO.txt index 6efaa913..9e607d14 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,12 +1,22 @@ +* separate security into product and test where test depends on JPA 2.0 implementations + and test is not deployed to the central maven repo. +* move codestyle to separate svn project. +* add cdi subproject * refactor: Create jpa subproject with separate subprojects for api, hibernate, toplink-essentials and eclipselink Each subproject contains the required repo settings -* Maven profile for nonrelease which is dactivated when release is active. -* Have toplink, eclipselink, hibernate profiles that are deactivated by - release and active by default. - -* add cdi subproject to the utils + +* update mythtv project for java ee 6 * add schemagen for user management part. +* reimplement photos application using wicket * JPA 2.0 implementation for security. +* change tracking for all projects with changes plugin + +* complete presentation of all wamblee stuff on wamblee.org. +* maven sites for each subproject accessible through wamblee.org +* overview pages for separate areas + +* create passwords application + diff --git a/hibernate-jpa/src/main/java/org/wamblee/hibernatejpa/JavadocDummyForSonatype.java b/hibernate-jpa/src/main/java/org/wamblee/hibernatejpa/JavadocDummyForSonatype.java new file mode 100644 index 00000000..8d1112e8 --- /dev/null +++ b/hibernate-jpa/src/main/java/org/wamblee/hibernatejpa/JavadocDummyForSonatype.java @@ -0,0 +1,11 @@ +package org.wamblee.hibernatejpa; + +/** + * Dummy class to force generation of javadoc. + * This is required for deploy to oss.sonatype.org to work. + * + * @author Erik Brakkee + */ +public class JavadocDummyForSonatype { + // Empty +} diff --git a/pom.xml b/pom.xml index b57de987..84d049cc 100644 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ - + support system hibernate-jpa @@ -329,8 +329,6 @@ compile - - @@ -345,6 +343,19 @@ javadoc:jar deploy + + org.apache.maven.plugins + maven-checkstyle-plugin + 2.5 + + + org.wamblee + wamblee-code-style + 1.0 + + + + maven-clean-plugin 2.4 @@ -374,6 +385,13 @@ UNIX org.wamblee.jalopy.xml + + + org.wamblee + wamblee-code-style + 1.1-SNAPSHOT + + org.apache.maven.plugins @@ -416,6 +434,7 @@ org.codehaus.mojo cobertura-maven-plugin + 2.3 @@ -455,6 +474,21 @@ + + org.codehaus.mojo + findbugs-maven-plugin + 2.3.1 + + true + + target/site + true + + target/site + + + + org.codehaus.mojo changes-maven-plugin @@ -479,6 +513,7 @@ org.codehaus.mojo cobertura-maven-plugin + 2.3 xml @@ -491,8 +526,9 @@ org.apache.maven.plugins maven-checkstyle-plugin + 2.5 - config/sun_checks.xml + org.wamblee.checkstyle.xml @@ -545,7 +581,7 @@ http://oss.sonatype.org/service/local/staging/deploy/maven2/ - + all diff --git a/security/README.txt b/security/README.txt new file mode 100644 index 00000000..bad8e3ac --- /dev/null +++ b/security/README.txt @@ -0,0 +1,5 @@ + +Security is separated into impl and jpatest because current JPA 2.0 implementations +(hibernate, eclipse-link) are not available on central maven repo. Therefore, the +tests that depend on them must be put into a separate jpatest project. + diff --git a/security/impl/pom.xml b/security/impl/pom.xml new file mode 100644 index 00000000..91d604ec --- /dev/null +++ b/security/impl/pom.xml @@ -0,0 +1,35 @@ + + + + org.wamblee + wamblee-utils + 0.2.2 + + + 4.0.0 + org.wamblee + wamblee-security-impl + jar + /security/impl + http://wamblee.org + + + + org.wamblee + wamblee-system-general + 0.2.2 + + + + javax + javaee-api + + + + commons-codec + commons-codec + + + + + diff --git a/support/general/src/main/java/org/wamblee/persistence/AbstractPersistent.java b/security/impl/src/main/java/org/wamblee/security/AbstractPersistent.java similarity index 54% rename from support/general/src/main/java/org/wamblee/persistence/AbstractPersistent.java rename to security/impl/src/main/java/org/wamblee/security/AbstractPersistent.java index 4eee3a02..cd2837dd 100644 --- a/support/general/src/main/java/org/wamblee/persistence/AbstractPersistent.java +++ b/security/impl/src/main/java/org/wamblee/security/AbstractPersistent.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,71 +13,75 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.wamblee.persistence; +package org.wamblee.security; import java.io.Serializable; +import org.wamblee.persistence.Persistent; + /** - * Default implementation of Persistent. - * + * Default implementation of Persistent. + * * @author Erik Brakkee */ public abstract class AbstractPersistent implements Persistent { - - /** - * Primary key. - */ - private Serializable _primaryKey; - - /** - * Version. - */ - private int _version; - - /** - * Constructs the object. - * - */ - protected AbstractPersistent() { - _primaryKey = null; - _version = -1; + + private Serializable primaryKey; + + private Number version; + + protected AbstractPersistent() { + primaryKey = null; + version = -1; } - + /** - * Copy constructor. - * @param aPersistent Object to copy. + * Copy constructor. + * + * @param aPersistent + * Object to copy. */ protected AbstractPersistent(AbstractPersistent aPersistent) { - _primaryKey = aPersistent._primaryKey; - _version = aPersistent._version; + primaryKey = aPersistent.primaryKey; + version = aPersistent.version; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.persistence.Persistent#getPrimaryKey() */ + @Override public Serializable getPrimaryKey() { - return _primaryKey; + return primaryKey; } - - /* (non-Javadoc) - * @see org.wamblee.persistence.Persistent#setPrimaryKey(java.io.Serializable) + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.persistence.Persistent#setPrimaryKey(java.io.Serializable) */ + @Override public void setPrimaryKey(Serializable aKey) { - _primaryKey = aKey; + primaryKey = aKey; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.persistence.Persistent#getPersistedVersion() */ - public int getPersistedVersion() { - return _version; + public Number getPersistedVersion() { + return version; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.persistence.Persistent#setPersistedVersion(int) */ - public void setPersistedVersion(int aVersion) { - _version = aVersion; + public void setPersistedVersion(Number aVersion) { + version = aVersion; } } diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationRule.java b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationRule.java new file mode 100644 index 00000000..b2baacce --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationRule.java @@ -0,0 +1,57 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; +import javax.persistence.Version; + +import org.wamblee.usermgt.User; + +/** + * Represents an authorization rule to determine whether an operation is allowed + * on a resource. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_AUTH_RULE") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "TYPE") +public abstract class AbstractAuthorizationRule implements AuthorizationRule { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + public AbstractAuthorizationRule() { + // Empty + } + + public AbstractAuthorizationRule(AbstractAuthorizationRule aRule) { + primaryKey = aRule.primaryKey; + version = aRule.version; + } +} diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationService.java b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationService.java new file mode 100644 index 00000000..d8c1e527 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractAuthorizationService.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Version; + +import org.wamblee.usermgt.UserAccessor; + +/** + * Service to determine if access to a certain resource is allowed. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_AUTH_SVC") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "TYPE") +@NamedQueries( + @NamedQuery(name = AbstractAuthorizationService.QUERY_FIND_BY_NAME, + query = "select s from AbstractAuthorizationService s where s.name = :" + + AbstractAuthorizationService.NAME_PARAM) + ) +public abstract class AbstractAuthorizationService implements AuthorizationService { + + public static final String QUERY_FIND_BY_NAME = "AuthorizationService.findByName"; + public static final String NAME_PARAM = "name"; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + public AbstractAuthorizationService() { + // Empty. + } + + public AbstractAuthorizationService(AbstractAuthorizationService aSvc) { + primaryKey = aSvc.primaryKey; + version = aSvc.version; + } +} diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AbstractOperationCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractOperationCondition.java new file mode 100644 index 00000000..69048ebd --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractOperationCondition.java @@ -0,0 +1,54 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; +import javax.persistence.Version; + +/** + * Checks if an operation matches a condition. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_OPERATION_CONDITION") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "TYPE") +public abstract class AbstractOperationCondition implements OperationCondition { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + public AbstractOperationCondition() { + // Empty + } + + public AbstractOperationCondition(AbstractOperationCondition aCondition) { + primaryKey = aCondition.primaryKey; + version = aCondition.version; + } +} diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AbstractPathCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractPathCondition.java new file mode 100644 index 00000000..6ec48017 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractPathCondition.java @@ -0,0 +1,54 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; +import javax.persistence.Version; + +/** + * Checks if a path satisfies a condition. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_PATH_CONDITION") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "TYPE") +public abstract class AbstractPathCondition implements PathCondition { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + public AbstractPathCondition() { + // Empty + } + + public AbstractPathCondition(AbstractPathCondition aCondition) { + primaryKey = aCondition.primaryKey; + version = aCondition.version; + } +} diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AbstractUserCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractUserCondition.java new file mode 100644 index 00000000..30e174f7 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AbstractUserCondition.java @@ -0,0 +1,56 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorColumn; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.Table; +import javax.persistence.Version; + +import org.wamblee.usermgt.User; + +/** + * Condition used to match a user against a specified set of users. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_USER_CONDITION") +@Inheritance(strategy = InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name = "TYPE") +public abstract class AbstractUserCondition implements UserCondition { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + public AbstractUserCondition() { + // Empty. + } + + public AbstractUserCondition(AbstractUserCondition aCondition) { + primaryKey = aCondition.primaryKey; + version = aCondition.version; + } +} diff --git a/security/src/main/java/org/wamblee/security/authorization/AllOperation.java b/security/impl/src/main/java/org/wamblee/security/authorization/AllOperation.java similarity index 65% rename from security/src/main/java/org/wamblee/security/authorization/AllOperation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AllOperation.java index c76d00ca..83b7a4e0 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AllOperation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AllOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,43 +13,45 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * An superclass of all other operations. + * An superclass of all other operations. */ public class AllOperation implements Operation { - private static final String OPERATION = "all"; - + /** - * Operation name. + * Operation name. */ - private String _name; - + private String name; + /** - * Constructs an all operation. - * + * Constructs an all operation. + * */ - public AllOperation() { - _name = OPERATION; + public AllOperation() { + name = OPERATION; } - + /** * Constructs the operation, this constructor is the one that must be used - * by subclasses. - * @param aName Name of the operation. This name must be unique among all operations. + * by subclasses. + * + * @param aName + * Name of the operation. This name must be unique among all + * operations. */ - protected AllOperation(String aName) { - _name = aName; + protected AllOperation(String aName) { + name = aName; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.security.authorization.Operation#getName() */ public String getName() { - return _name; + return name; } - } diff --git a/security/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java similarity index 59% rename from security/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java index fdee026e..c33eced3 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AnyUserCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,40 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; -import org.wamblee.persistence.AbstractPersistent; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + import org.wamblee.usermgt.User; /** - * Matches any user. - * + * Matches any user. + * * @author Erik Brakkee */ -public class AnyUserCondition extends AbstractPersistent implements UserCondition { - +@Entity +@DiscriminatorValue("ANYUSER") +public class AnyUserCondition extends AbstractUserCondition { /** - * Constructs the condition. - * + * Constructs the condition. + * */ - public AnyUserCondition() { - // Empty. + public AnyUserCondition() { + // Empty. } - /* (non-Javadoc) - * @see org.wamblee.security.authorization.UserCondition#matches(org.wamblee.usermgt.User) + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.UserCondition#matches(org.wamblee. + * usermgt.User) */ public boolean matches(User aUser) { - return true; + return true; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see java.lang.Object#toString() */ @Override public String toString() { - return "AnyUserCondition()"; + return "AnyUserCondition()"; } - } diff --git a/security/src/main/java/org/wamblee/security/authorization/AuthorizationException.java b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationException.java similarity index 63% rename from security/src/main/java/org/wamblee/security/authorization/AuthorizationException.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationException.java index d7a81fd5..e06a9144 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AuthorizationException.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,32 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Authorization exception to be thrown when - * a resouce may not be accessed. - * + * Authorization exception to be thrown when a resouce may not be accessed. + * * @author Erik Brakkee */ public class AuthorizationException extends RuntimeException { - - private Object _resource; - private Operation _operation; + private Object resource; + + private Operation operation; + /** + * Creates a new AuthorizationException object. + * + */ public AuthorizationException(Object aResource, Operation aOperation) { - super("Operation '" + aOperation + "' not allowed on '" + aResource + "'"); - _resource = aResource; - _operation = aOperation; + super("Operation '" + aOperation + "' not allowed on '" + aResource + + "'"); + resource = aResource; + operation = aOperation; } - - public Object getResource() { - return _resource; + + public Object getResource() { + return resource; } - - public Operation getOperation() { - return _operation; + + public Operation getOperation() { + return operation; } - } diff --git a/security/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java similarity index 58% rename from security/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java index 7423eab9..4ec00cdd 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,31 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; import org.apache.log4j.Logger; - /** - * Inititializer class for authorization rules. This class initializes the - * authorization rules in case none are present. + * Inititializer class for authorization rules. This class initializes the + * authorization rules in case none are present. */ public class AuthorizationInitializer { - - private static final Logger LOGGER = Logger.getLogger(AuthorizationInitializer.class); + private static final Logger LOGGER = Logger + .getLogger(AuthorizationInitializer.class); /** - * Initializes authorization rules in case none are present. - * @param aService Authorization service. - * @param aRules Default rules for initialization. + * Initializes authorization rules in case none are present. + * + * @param aService + * Authorization service. + * @param aRules + * Default rules for initialization. */ - public AuthorizationInitializer(AuthorizationService aService, AuthorizationRule[] aRules) { - if ( aService.getRules().length == 0 ) { - for (AuthorizationRule rule: aRules) { - LOGGER.info("Appending authorization rule " + rule); - aService.appendRule(rule); - } - } + public AuthorizationInitializer(AuthorizationService aService, + AbstractAuthorizationRule[] aRules) { + if (aService.getRules().length == 0) { + for (AbstractAuthorizationRule rule : aRules) { + LOGGER.info("Appending authorization rule " + rule); + aService.appendRule(rule); + } + } } } diff --git a/security/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java similarity index 91% rename from security/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java index a394910f..e187caaa 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,13 +12,12 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.security.authorization; /** * Represents the result of an authorization decision. - * + * * @author Erik Brakkee */ public enum AuthorizationResult { @@ -26,19 +25,16 @@ public enum AuthorizationResult { * Access is granted. */ GRANTED, - /** * Access is denied. */ DENIED, - /** * Access is undecided. */ UNDECIDED, - /** * Unsupported resource. */ - UNSUPPORTED_RESOURCE + UNSUPPORTED_RESOURCE; } diff --git a/security/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java similarity index 51% rename from security/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java rename to security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java index 575f4f21..812021b1 100644 --- a/security/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationRule.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,35 +12,43 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.security.authorization; -import org.wamblee.persistence.Persistent; import org.wamblee.usermgt.User; /** - * Represents an authorization rule to determine whether an operation is allowed on a resource. - * + * Represents an authorization rule to determine whether an operation is allowed + * on a resource. + * * @author Erik Brakkee */ -public interface AuthorizationRule extends Persistent { - +public interface AuthorizationRule { + /** - * Returns the supported object types for which this authorization rule applies. - * This can be used by the authorization service for optimization. - * @return Array of supported types. + * Returns the supported object types for which this authorization rule + * applies. This can be used by the authorization service for optimization. + * + * @return Array of supported types. */ - Class[] getSupportedTypes(); + public abstract Class[] getSupportedTypes(); /** - * Determines whether an operation is allowed on a certain resource. - * The rule implementation must be prepared to deal with resources for which it does - * not apply. In those cases it should return {@link AuthorizationResult#UNSUPPORTED_RESOURCE}. - * @param aResource Resource. - * @param anOperation Operation. - * @param aUser Current user. - * @return Authorization result. + * Determines whether an operation is allowed on a certain resource. The + * rule implementation must be prepared to deal with resources for which it + * does not apply. In those cases it should return + * {@link AuthorizationResult#UNSUPPORTED_RESOURCE}. + * + * @param aResource + * Resource. + * @param aOperation + * Operation. + * @param aUser + * Current user. + * + * @return Authorization result. */ - AuthorizationResult isAllowed(Object aResource, Operation anOperation, User aUser); -} + public abstract AuthorizationResult isAllowed(Object aResource, + Operation aOperation, User aUser); + +} \ No newline at end of file diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationService.java b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationService.java new file mode 100644 index 00000000..349ef757 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/AuthorizationService.java @@ -0,0 +1,96 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import org.wamblee.usermgt.UserAccessor; + +/** + * Service to determine if access to a certain resource is allowed. + * + * @author Erik Brakkee + */ +public interface AuthorizationService { + + /** + * Checks whether an operation is allowed on a resource. + * + * @param aResource + * Resource. + * @param aOperation + * Operation. + * + * @return Checks whether the operation is allowed on a resource. + */ + boolean isAllowed(Object aResource, Operation aOperation); + + /** + * Checks if the given operation is allowed on the resource. + * + * @param + * Type of resource + * @param aResource + * Resource. + * @param aOperation + * Operation. + * @return Resource passed in in case access is allowed + * @throws AuthorizationException + * In case access is denied. + */ + T check(T aResource, Operation aOperation); + + /** + * Gets the authorization rules. + * + * @return Rules. + */ + AuthorizationRule[] getRules(); + + /** + * Appends a new authorization rule to the end. + * + * @param aRule + * Rule to append. + */ + void appendRule(AuthorizationRule aRule); + + /** + * Removes a rule. + * + * @param aIndex + * Index of the rule to remove. + */ + void removeRule(int aIndex); + + /** + * Inserts a rule. + * + * @param aIndex + * Index of the position of the rule after insertion. + * @param aRule + * Rule to insert. + */ + void insertRuleAfter(int aIndex, AuthorizationRule aRule); + + /** + * Sets the user accessor so that the authorization service can get access + * to the logged in user. + * + * @param aUserAccessor + * User accessor. + */ + void setUserAccessor(UserAccessor aUserAccessor); + +} \ No newline at end of file diff --git a/security/src/main/java/org/wamblee/security/authorization/CreateOperation.java b/security/impl/src/main/java/org/wamblee/security/authorization/CreateOperation.java similarity index 81% rename from security/src/main/java/org/wamblee/security/authorization/CreateOperation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/CreateOperation.java index b9a96d8e..7a6214df 100644 --- a/security/src/main/java/org/wamblee/security/authorization/CreateOperation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/CreateOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Represents an operation to create something. - * + * Represents an operation to create something. + * * @author Erik Brakkee */ public class CreateOperation extends AllOperation { - private static final String OPERATION = "create"; - + /** - * Constructs the operation. - * + * Constructs the operation. + * */ - public CreateOperation() { + public CreateOperation() { super(OPERATION); } - } diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java b/security/impl/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java new file mode 100644 index 00000000..8ee41178 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java @@ -0,0 +1,203 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.CascadeType; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; +import javax.persistence.Transient; + +import org.wamblee.usermgt.User; +import org.wamblee.usermgt.UserAccessor; + +/** + * Default implementation of an authorization service. To determine whether + * access to a resource is allowed, the service consults a number of + * authorization rules in a fixed order. The first rule that gives a result + * GRANTED or DENIED determines the result of the evaluation. Rules that return + * any other result are ignoed. If none of the rules match, than access is + * denied. + * + * @author Erik Brakkee + */ +@Entity +@DiscriminatorValue("DEFAULT") +public class DefaultAuthorizationService extends AbstractAuthorizationService { + + + /** + * List of ordered authorization rules. + */ + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, targetEntity = AbstractAuthorizationRule.class) + @OrderColumn(name = "RULE_INDEX") + private List rules; + + /** + * User accessor used to obtain the current user. + */ + @Transient + private UserAccessor userAccessor; + + /** + * Name for this instance of the authorization service. + */ + private String name; + + /** + * Constructs the service. + * + * @param aAccessor + * User accessor. + * @param aName + * Name of this instance of the service. + */ + public DefaultAuthorizationService(UserAccessor aAccessor, String aName) { + rules = new ArrayList(); + userAccessor = aAccessor; + name = aName; + } + + /** + * Constructs the authorization service. + */ + public DefaultAuthorizationService() { + rules = new ArrayList(); + userAccessor = null; + name = null; + } + + /** + * Sets the user accessor. + * + * @param aUserAccessor + * User accessor. + */ + @Override + public void setUserAccessor(UserAccessor aUserAccessor) { + userAccessor = aUserAccessor; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#isAllowed(java + * .lang.Object, org.wamblee.security.authorization.Operation) + */ + public boolean isAllowed(Object aResource, Operation aOperation) { + User user = userAccessor.getCurrentUser(); + + for (AuthorizationRule rule : rules) { + switch (rule.isAllowed(aResource, aOperation, user)) { + case DENIED: + return false; + + case GRANTED: + return true; + } + } + + return false; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.security.authorization.AuthorizationService#check(T, + * org.wamblee.security.authorization.Operation) + */ + public T check(T aResource, Operation aOperation) { + if (!isAllowed(aResource, aOperation)) { + throw new AuthorizationException(aResource, aOperation); + } + + return aResource; + } + + protected String getName() { + return name; + } + + public void setName(String aName) { + name = aName; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.security.authorization.AuthorizationService#getRules() + */ + public AuthorizationRule[] getRules() { + return rules.toArray(new AbstractAuthorizationRule[0]); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#appendRule(org + * .wamblee.security.authorization.AuthorizationRule) + */ + public void appendRule(AuthorizationRule aRule) { + rules.add(aRule); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter + * (int, org.wamblee.security.authorization.AuthorizationRule) + */ + public void insertRuleAfter(int aIndex, AuthorizationRule aRule) { + rules.add(aIndex, aRule); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#removeRule(int) + */ + public void removeRule(int aIndex) { + rules.remove(aIndex); + } + + /** + * For OR mapping. + * + * @return The rules. + */ + protected List getMappedRules() { + return rules; + } + + /** + * For OR mapping. + * + * @param aRules + * The rules. + */ + protected void setMappedRules(List aRules) { + rules = aRules; + } +} diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java b/security/impl/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java new file mode 100644 index 00000000..2ebce1c7 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java @@ -0,0 +1,115 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import java.util.ArrayList; +import java.util.Map; +import java.util.TreeMap; + +/** + * Operation registry implementation. This implementation ignores the + * distinction between different types of resources and simply assumes that + * every operation is applicable to every type of resource. + * + * @author Erik Brakkee + */ +public class DefaultOperationRegistry implements OperationRegistry { + private Map operations; + + /** + * Creates a new DefaultOperationRegistry object. + * + */ + public DefaultOperationRegistry(Operation[] aOperations) { + operations = new TreeMap(); + + for (Operation operation : aOperations) { + operations.put(operation.getName(), operation); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.OperationRegistry#getOperations(java + * .lang.Class) + */ + public Operation[] getOperations(Class aResourceClass) { + return operations.values().toArray(new Operation[0]); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.OperationRegistry#encode(org.wamblee + * .security.authorization.Operation[]) + */ + public String encode(Operation[] aOperations) { + StringBuffer buffer = new StringBuffer(); + + for (Operation operation : aOperations) { + if (buffer.length() > 0) { + buffer.append(','); + } + + buffer.append(operation.getName()); + } + + return buffer.toString(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.OperationRegistry#decode(java.lang + * .Class, java.lang.String) + */ + public Operation[] decode(Class aResourceClass, String aOperationsString) { + return decode(aOperationsString); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.OperationRegistry#decode(java.lang + * .String) + */ + public Operation[] decode(String aOperationsString) { + if (aOperationsString.length() == 0) { + return new Operation[0]; + } + + String[] names = aOperationsString.split(","); + ArrayList result = new ArrayList(); + + for (String name : names) { + Operation operation = operations.get(name); + + if (operation == null) { + throw new IllegalArgumentException("Unknown operation '" + + name + "'"); + } + + result.add(operation); + } + + return result.toArray(new Operation[0]); + } +} diff --git a/security/src/main/java/org/wamblee/security/authorization/DeleteOperation.java b/security/impl/src/main/java/org/wamblee/security/authorization/DeleteOperation.java similarity index 83% rename from security/src/main/java/org/wamblee/security/authorization/DeleteOperation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/DeleteOperation.java index 7bdaac51..14901149 100644 --- a/security/src/main/java/org/wamblee/security/authorization/DeleteOperation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/DeleteOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Deletes the operation. - * + * Deletes the operation. + * * @author Erik Brakkee */ public class DeleteOperation extends AllOperation { - private static final String OPERATION = "delete"; - + /** - * Constructs the operation. - * + * Constructs the operation. + * */ - public DeleteOperation() { + public DeleteOperation() { super(OPERATION); } } diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java new file mode 100644 index 00000000..5c3315b3 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java @@ -0,0 +1,95 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + + +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +import org.wamblee.usermgt.User; + + +/** + * Checks if a user against a specific group. + * + * @author Erik Brakkee + */ +@Entity +@DiscriminatorValue("GROUP") +public class GroupUserCondition extends AbstractUserCondition { + /** + * Group the user must be in. + */ + @Column(name = "GRP") + private String group; + + /** + * Constructs the condition. + * + * @param aGroup + * Group the user must be in. + */ + public GroupUserCondition(String aGroup) { + group = aGroup; + } + + /** + * For OR mapping. + * + */ + protected GroupUserCondition() { + group = null; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.UserCondition#matches(org.wamblee. + * usermgt.UserAccessor) + */ + public boolean matches(User aUser) { + return aUser.isInGroup(group); + } + + /** + * + * @return Returns the group. + */ + protected String getGroup() { + return group; + } + + /** + * + * @param aGroup + * The group to set. + */ + protected void setGroup(String aGroup) { + group = aGroup; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "GroupUserCondition(group=" + group + ")"; + } +} diff --git a/security/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java similarity index 63% rename from security/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java index e5a4d686..b42f5d0e 100644 --- a/security/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/IsaOperationCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,22 +12,26 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.security.authorization; -import org.wamblee.persistence.AbstractPersistent; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; /** * Determiens if an operation is a subclass of a specified operation. */ -public class IsaOperationCondition extends AbstractPersistent implements - OperationCondition { - +@Entity +@DiscriminatorValue("ISA") +@Access(AccessType.PROPERTY) +public class IsaOperationCondition extends AbstractOperationCondition { /** * Operation that the other operation must be a subclass of. */ - private Class _operation; + private Class operation; /** * Constructs the condition. @@ -36,7 +40,7 @@ public class IsaOperationCondition extends AbstractPersistent implements * Operation that an operation must be an instance of. */ public IsaOperationCondition(Class aOperation) { - _operation = aOperation; + operation = aOperation; } /** @@ -44,16 +48,18 @@ public class IsaOperationCondition extends AbstractPersistent implements * */ public IsaOperationCondition() { - _operation = null; + operation = null; } /* * (non-Javadoc) * - * @see org.wamblee.security.authorization.OperationCondition#matches(org.wamblee.security.authorization.Operation) + * @see + * org.wamblee.security.authorization.OperationCondition#matches(org.wamblee + * .security.authorization.Operation) */ public boolean matches(Operation aOperation) { - return _operation.isInstance(aOperation); + return operation.isInstance(aOperation); } /** @@ -61,11 +67,13 @@ public class IsaOperationCondition extends AbstractPersistent implements * * @return Operation string. */ + @Column(name = "CLASSNAME") protected String getOperationString() { - if (_operation == null) { - return null; + if (operation == null) { + return null; } - return _operation.getName(); + + return operation.getName(); } /** @@ -73,15 +81,18 @@ public class IsaOperationCondition extends AbstractPersistent implements * * @param aOperation * Operation string. + * */ protected void setOperationString(String aOperation) { - if (aOperation == null ) { + if (aOperation == null) { return; } - try { - _operation = (Class)Class.forName(aOperation); - } catch (Exception e) { - throw new IllegalArgumentException("Unknown class '" + aOperation + "'"); + + try { + operation = (Class) Class.forName(aOperation); + } catch (Exception e) { + throw new IllegalArgumentException("Unknown class '" + aOperation + + "'"); } } @@ -92,7 +103,6 @@ public class IsaOperationCondition extends AbstractPersistent implements */ @Override public String toString() { - return "IsaOperationCondition(operation=" + _operation.getName() + ")"; + return "IsaOperationCondition(operation=" + operation.getName() + ")"; } - } diff --git a/security/src/main/java/org/wamblee/security/authorization/Operation.java b/security/impl/src/main/java/org/wamblee/security/authorization/Operation.java similarity index 69% rename from security/src/main/java/org/wamblee/security/authorization/Operation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/Operation.java index 24205065..54a959e4 100644 --- a/security/src/main/java/org/wamblee/security/authorization/Operation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/Operation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Represents an operation on a resource. - * An operation should contain no state to be persisted since only the name of the - * operation is persisted. - * + * Represents an operation on a resource. An operation should contain no state + * to be persisted since only the name of the operation is persisted. + * * @author Erik Brakkee */ public interface Operation { - /** - * Gets the name of the operation. - * @return Operation. + * Gets the name of the operation. + * + * @return Operation. */ - String getName(); + String getName(); } diff --git a/security/src/main/java/org/wamblee/security/authorization/OperationCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/OperationCondition.java similarity index 63% rename from security/src/main/java/org/wamblee/security/authorization/OperationCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/OperationCondition.java index db6e0d0a..06ef988b 100644 --- a/security/src/main/java/org/wamblee/security/authorization/OperationCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/OperationCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; -import org.wamblee.persistence.Persistent; - /** - * Checks if an operation matches a condition. - * + * Checks if an operation matches a condition. + * * @author Erik Brakkee */ -public interface OperationCondition extends Persistent { +public interface OperationCondition { - /** - * Determines if the operation matches. - * @param aOperation Operation. - * @return True iff the operation matches. + * Determines if the operation matches. + * + * @param aOperation + * Operation. + * + * @return True iff the operation matches. */ - boolean matches(Operation aOperation); -} + public abstract boolean matches(Operation aOperation); + +} \ No newline at end of file diff --git a/security/src/main/java/org/wamblee/security/authorization/OperationRegistry.java b/security/impl/src/main/java/org/wamblee/security/authorization/OperationRegistry.java similarity index 60% rename from security/src/main/java/org/wamblee/security/authorization/OperationRegistry.java rename to security/impl/src/main/java/org/wamblee/security/authorization/OperationRegistry.java index bcce7c96..0986148d 100644 --- a/security/src/main/java/org/wamblee/security/authorization/OperationRegistry.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/OperationRegistry.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,45 +13,54 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; - /** - * Utility to map between a list of operations and a string based - * on the names of the operations. - * + * Utility to map between a list of operations and a string based on the names + * of the operations. + * * @author Erik Brakkee */ public interface OperationRegistry { - /** - * Gets the supported operations for a given resource class. - * @param aResourceClass Resource class. - * @return Supported operations for that class. + * Gets the supported operations for a given resource class. + * + * @param aResourceClass + * Resource class. + * + * @return Supported operations for that class. */ Operation[] getOperations(Class aResourceClass); - + /** - * Converts a number of operations to a string. - * @param aOperations Operations to convert. - * @return String representation of the allowed operations. + * Converts a number of operations to a string. + * + * @param aOperations + * Operations to convert. + * + * @return String representation of the allowed operations. */ String encode(Operation[] aOperations); - + /** * Converts an operations string to an array of operations. - * @param aResourceClass Resource class. - * @param aOperationsString Operations string as returned by {@link #encode(Operation[])}. - * @return Operations array. + * + * @param aResourceClass + * Resource class. + * @param aOperationsString + * Operations string as returned by {@link #encode(Operation[])}. + * + * @return Operations array. */ Operation[] decode(Class aResourceClass, String aOperationsString); - + /** * Converts an operations string to an array of operations. - * @param aOperationsString Operations string as returned by {@link #encode(Operation[])}. - * @return Operations array. + * + * @param aOperationsString + * Operations string as returned by {@link #encode(Operation[])}. + * + * @return Operations array. */ Operation[] decode(String aOperationsString); - } diff --git a/security/src/main/java/org/wamblee/security/authorization/PathCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/PathCondition.java similarity index 64% rename from security/src/main/java/org/wamblee/security/authorization/PathCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/PathCondition.java index 8c970177..0fd91916 100644 --- a/security/src/main/java/org/wamblee/security/authorization/PathCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/PathCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,22 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; -import org.wamblee.persistence.Persistent; - /** - * Checks if a path satisfies a condition. - * + * Checks if a path satisfies a condition. + * * @author Erik Brakkee */ -public interface PathCondition extends Persistent { +public interface PathCondition { /** - * Checks if the path matches the condition. - * @param aPath Path to match. - * @return True iff the path matches. + * Checks if the path matches the condition. + * + * @param aPath + * Path to match. + * + * @return True iff the path matches. */ - boolean matches(String aPath); -} + public abstract boolean matches(String aPath); + +} \ No newline at end of file diff --git a/security/src/main/java/org/wamblee/security/authorization/ReadOperation.java b/security/impl/src/main/java/org/wamblee/security/authorization/ReadOperation.java similarity index 78% rename from security/src/main/java/org/wamblee/security/authorization/ReadOperation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/ReadOperation.java index 839fdb18..2ff67b53 100644 --- a/security/src/main/java/org/wamblee/security/authorization/ReadOperation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/ReadOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Represents a read operation on a resource. - * + * Represents a read operation on a resource. + * * @author Erik Brakkee */ public class ReadOperation extends AllOperation { - private static final String OPERATION = "read"; - + /** - * Constructs the operation. - * + * Constructs the operation. + * */ - public ReadOperation() { - super(OPERATION); + public ReadOperation() { + super(OPERATION); } } diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java new file mode 100644 index 00000000..e40d4aca --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java @@ -0,0 +1,89 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +/** + * Condition to check whether a path matches a given regula expression. + * + * @author Erik Brakkee + */ +@Entity +@DiscriminatorValue("REGEXP") +public class RegexpPathCondition extends AbstractPathCondition { + /** + * String the path must start with. + */ + private String pattern; + + /** + * Constructs the condition. + * + * @param aPattern + * String the path must start with. + */ + public RegexpPathCondition(String aPattern) { + pattern = aPattern; + } + + /** + * For OR mapping. + * + */ + protected RegexpPathCondition() { + pattern = null; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.PathCondition#matches(java.lang.String + * ) + */ + public boolean matches(String aPath) { + return aPath.matches(pattern); + } + + /** + * + * @return Returns the _path. + */ + protected String getPattern() { + return pattern; + } + + /** + * + * @param aPattern + * The _path to set. + */ + protected void setPattern(String aPattern) { + pattern = aPattern; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "RegexpCondition(pattern = '" + pattern + "')"; + } +} diff --git a/security/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java similarity index 66% rename from security/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java index 59f8627c..9233d800 100644 --- a/security/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/StartsWithPathCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,34 +13,40 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; /** - * Condition to check whether a path starts with a given string. - * + * Condition to check whether a path starts with a given string. + * * @author Erik Brakkee */ +@Entity +@DiscriminatorValue("STARTSWITH") public class StartsWithPathCondition extends RegexpPathCondition { - /** - * Constructs the condition. - * @param aPath String the path must start with. + * Constructs the condition. + * + * @param aPath + * String the path must start with. */ - public StartsWithPathCondition(String aPath) { - super( aPath + ".*"); + public StartsWithPathCondition(String aPath) { + super(aPath + ".*"); } - + /** - * For OR mapping. - * + * For OR mapping. + * */ - protected StartsWithPathCondition() { - super(); + protected StartsWithPathCondition() { + super(); } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see java.lang.Object#toString() */ @Override diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java b/security/impl/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java new file mode 100644 index 00000000..17bdc348 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java @@ -0,0 +1,319 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import static org.wamblee.security.authorization.AuthorizationResult.*; + +import javax.enterprise.inject.Typed; +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Transient; + +import org.apache.log4j.Logger; +import org.wamblee.usermgt.User; + +/** + * Utility base class for implementation of authentication rules based on the + *
    + *
  • The path of the resource. To obtain the path of a resource, subclasses + * must implement {@link #getResourcePath(Object)}. Whether a path is + * appropriate is determined by a + * {@link org.wamblee.security.authorization.AbstractPathCondition}.
  • + *
  • The user identity with which the resource is accessed. Whether a user is + * appropriate is determined by a + * {@link org.wamblee.security.authorization.AbstractUserCondition}.
  • + *
  • The operation that is requested. Whether the operation is appropriate is + * determined by a {@link org.wamblee.security.authorization.AbstractOperationCondition} + * .
  • + *
+ * In case all three conditions match, the condition returns the configured + * result passed at construction (GRANTED or DENIED). If the resource is not of + * the specified type, the result is UNSUPPORTED_RESOURCE, otherwise, the result + * is UNDECIDED. + */ +@Entity +@Access(AccessType.PROPERTY) +public abstract class UrlAuthorizationRule extends AbstractAuthorizationRule { + private static final Logger LOGGER = Logger + .getLogger(UrlAuthorizationRule.class); + + /** + * Result that the rule will return in case there is a match. + */ + private AuthorizationResult result; + + /** + * A condition which specifies which users the rule is for. + */ + private UserCondition userCondition; + + /** + * Path the rule applies for. + */ + private PathCondition pathCondition; + + /** + * Resource class that the rule applies for. + */ + private Class resourceClass; + + /** + * Operation that this rule is for. + */ + + private OperationCondition operationCondition; + + /** + * Constructs an authorization rule. IF the group and path match, then the + * provided result will be returned. + * + * @param aResult + * Result of the authorization when the path and group match. + * @param aUserCondition + * Condition to match users. + * @param aPathCondition + * Condition to match paths with. + * @param aResourceClass + * Supported resource class this is for. + * @param aOperationCondition + * Condition to match the operation with. + */ + protected UrlAuthorizationRule(AuthorizationResult aResult, + UserCondition aUserCondition, PathCondition aPathCondition, + Class aResourceClass, OperationCondition aOperationCondition) { + if (!aResult.equals(GRANTED) && !aResult.equals(DENIED)) { + throw new IllegalArgumentException( + "Only GRANTED or DENIED may be used: " + aResult); + } + + result = aResult; + userCondition = aUserCondition; + pathCondition = aPathCondition; + resourceClass = aResourceClass; + operationCondition = aOperationCondition; + } + + /** + * For OR mapping. + * + */ + protected UrlAuthorizationRule(Class aResourceClass) { + result = null; + userCondition = null; + pathCondition = null; + resourceClass = aResourceClass; + operationCondition = null; + } + + /** + * For OR mapping. + * + */ + protected UrlAuthorizationRule() { + result = null; + userCondition = null; + pathCondition = null; + resourceClass = null; + operationCondition = null; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationRule#getSupportedTypes() + */ + @Transient + public Class[] getSupportedTypes() { + return new Class[] { resourceClass }; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationRule#isAllowed(java.lang + * .Object, org.wamblee.security.authorization.Operation) + */ + public AuthorizationResult isAllowed(Object aResource, + Operation aOperation, User aUser) { + if (!resourceClass.isInstance(aResource)) { + return UNSUPPORTED_RESOURCE; + } + + String path = getResourcePath(aResource); + + return isAllowed(path, aOperation, aUser); + } + + /** + * Determines if the operation is allowed on the resource. + * + * @param aPath + * Path of the resource. + * @param aOperation + * Operation to be done. + * @param aUser + * Currently logged in user or null if no user is logged in. + * + * @return Authorization result, + */ + protected AuthorizationResult isAllowed(String aPath, Operation aOperation, + User aUser) { + if (!pathCondition.matches(aPath)) { + return UNDECIDED; + } + + if (!operationCondition.matches(aOperation)) { + return UNDECIDED; + } + + if (!userCondition.matches(aUser)) { + return UNDECIDED; + } + + return result; + } + + /** + * Gets the path of the resource. + * + * @param aResource + * Resource, guaranteed to be an instance of + * {@link #resourceClass}. + * + * @return Path of the resource. + */ + protected abstract String getResourcePath(Object aResource); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "UrlAUthorizationRule(result = " + result + + ", pathCondition = " + pathCondition + ", userCondition = " + + userCondition + ", resourceClass = " + resourceClass + ")"; + } + + /** + * Gets the authorization result for OR mapping. + * + * @return Result. + */ + @Column(name = "AUTH_RESULT", nullable = false) + protected String getAuthorizationResultString() { + if (result == null) { + return null; + } + + return result.toString(); + } + + /** + * Sets the authorization result, for OR mapping. + * + * @param aResult + * Result. + */ + protected void setAuthorizationResultString(String aResult) { + result = AuthorizationResult.valueOf(aResult); + } + + @Column(name = "RES_CLASSNAME", nullable = false) + protected String getResourceClassName() { + if (resourceClass == null) { + return ""; + } + + return resourceClass.getName(); + } + + protected void setResourceClassName(String aResourceClass) { + try { + resourceClass = Class.forName(aResourceClass); + } catch (ClassNotFoundException e) { + LOGGER.error("Cannot find resource class '" + aResourceClass + "'", + e); + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /** + * + * @return Returns the operationCondition. + */ + @ManyToOne(cascade = CascadeType.ALL, targetEntity = AbstractOperationCondition.class) + @JoinColumn(name = "OPER_COND_PK") + public OperationCondition getOperationCondition() { + return operationCondition; + } + + /** + * + * @param aOperationCondition + * The operationCondition to set. + */ + protected void setOperationCondition(OperationCondition aOperationCondition) { + operationCondition = aOperationCondition; + } + + /** + * + * @return Returns the pathCondition. + */ + @ManyToOne(cascade = CascadeType.ALL, targetEntity = AbstractPathCondition.class) + @JoinColumn(name = "PATH_COND_PK") + public PathCondition getPathCondition() { + return pathCondition; + } + + /** + * + * @param aPathCondition + * The pathCondition to set. + */ + protected void setPathCondition(PathCondition aPathCondition) { + pathCondition = aPathCondition; + } + + /** + * + * @return Returns the userCondition. + */ + @ManyToOne(cascade = CascadeType.ALL, targetEntity = AbstractUserCondition.class) + @JoinColumn(name = "USER_COND_PK") + public UserCondition getUserCondition() { + return userCondition; + } + + /** + * + * @param aUserCondition + * The userCondition to set. + */ + protected void setUserCondition(UserCondition aUserCondition) { + userCondition = aUserCondition; + } +} diff --git a/security/src/main/java/org/wamblee/security/authorization/UserCondition.java b/security/impl/src/main/java/org/wamblee/security/authorization/UserCondition.java similarity index 69% rename from security/src/main/java/org/wamblee/security/authorization/UserCondition.java rename to security/impl/src/main/java/org/wamblee/security/authorization/UserCondition.java index ad398770..7ce55cf9 100644 --- a/security/src/main/java/org/wamblee/security/authorization/UserCondition.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/UserCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; -import org.wamblee.persistence.Persistent; import org.wamblee.usermgt.User; /** - * Condition used to match a user against a specified set of users. - * + * Condition used to match a user against a specified set of users. + * * @author Erik Brakkee */ -public interface UserCondition extends Persistent { +public interface UserCondition { /** - * Determines if the condition matches. - * @param aUser user to check. - * @return True if the condition matches, false otherwise. + * Determines if the condition matches. + * + * @param aUser + * user to check. + * + * @return True if the condition matches, false otherwise. */ - boolean matches(User aUser); -} + public abstract boolean matches(User aUser); + +} \ No newline at end of file diff --git a/security/src/main/java/org/wamblee/security/authorization/WriteOperation.java b/security/impl/src/main/java/org/wamblee/security/authorization/WriteOperation.java similarity index 78% rename from security/src/main/java/org/wamblee/security/authorization/WriteOperation.java rename to security/impl/src/main/java/org/wamblee/security/authorization/WriteOperation.java index 212ce316..5819f422 100644 --- a/security/src/main/java/org/wamblee/security/authorization/WriteOperation.java +++ b/security/impl/src/main/java/org/wamblee/security/authorization/WriteOperation.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,24 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * Represents a write operation on a resource. - * + * Represents a write operation on a resource. + * * @author Erik Brakkee */ public class WriteOperation extends AllOperation { - private static final String OPERATION = "write"; - + /** - * Constructs the operation. - * + * Constructs the operation. + * */ - public WriteOperation() { - super(OPERATION); + public WriteOperation() { + super(OPERATION); } - } diff --git a/security/impl/src/main/java/org/wamblee/security/authorization/jpa/JpaAuthorizationService.java b/security/impl/src/main/java/org/wamblee/security/authorization/jpa/JpaAuthorizationService.java new file mode 100644 index 00000000..e1b71d7d --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/security/authorization/jpa/JpaAuthorizationService.java @@ -0,0 +1,223 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization.jpa; + +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.NonUniqueResultException; + +import org.wamblee.persistence.JpaMergeSupport; +import org.wamblee.security.authorization.AbstractAuthorizationService; +import org.wamblee.security.authorization.AbstractAuthorizationRule; +import org.wamblee.security.authorization.AuthorizationRule; +import org.wamblee.security.authorization.AuthorizationService; +import org.wamblee.security.authorization.DefaultAuthorizationService; +import org.wamblee.security.authorization.Operation; +import org.wamblee.usermgt.UserAccessor; + +/** + * Authorization service with persistent storage. This is a wrapper for + * {@link org.wamblee.security.authorization.DefaultAuthorizationService} which + * refreshes the state of the service at certain time intervals. + * + * @author Erik Brakkee + */ +public class JpaAuthorizationService implements AuthorizationService { + + /** + * Authorization service to use. + */ + private AuthorizationService service; + + /** + * Hibernate template to use. + */ + private EntityManager entityManager; + + /** + * User accessor. + */ + private UserAccessor userAccessor; + + /** + * Name of the service. + */ + private String name; + + /** + * Refresh interval in milliseconds. + */ + private final long refreshInterval; + + /** + * Last refresh time. + */ + private long lastRefreshTime; + + /** + * Constructs the persistent service. + * + * @param aName + * Name of the service. + * @param aEntityManager + * Entity manager. + * @param aAccessor + * User accessor. + * @param aRefresh + * Whether or not to refresh the state of the service at the + * start of every operation. + */ + public JpaAuthorizationService(String aName, EntityManager aEntityManager, + UserAccessor aAccessor, long aRefreshInterval) { + entityManager = aEntityManager; + refreshInterval = aRefreshInterval; + lastRefreshTime = System.currentTimeMillis(); + userAccessor = aAccessor; + name = aName; + } + + @Override + public void setUserAccessor(UserAccessor aUserAccessor) { + userAccessor = aUserAccessor; + } + + /** + * Initialize service if needed. + * + */ + private void initialize() { + if (service == null) { + refreshByReload(); + } + } + + private void refreshByReload() { + try { + service = entityManager.createNamedQuery( + AbstractAuthorizationService.QUERY_FIND_BY_NAME, + AbstractAuthorizationService.class).setParameter( + AbstractAuthorizationService.NAME_PARAM, name).getSingleResult(); + service.setUserAccessor(userAccessor); + } catch (NonUniqueResultException e) { + throw new IllegalArgumentException( + "Returned more than one service for name '" + name + "'"); + } catch (NoResultException e) { + service = new DefaultAuthorizationService(userAccessor, name); + entityManager.persist(service); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#isAllowed(java + * .lang.Object, org.wamblee.security.authorization.Operation) + */ + public boolean isAllowed(Object aResource, Operation aOperation) { + initialize(); + refresh(); + + return service.isAllowed(aResource, aOperation); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.security.authorization.AuthorizationService#check(T, + * org.wamblee.security.authorization.Operation) + */ + public T check(T aResource, Operation aOperation) { + initialize(); + refresh(); + + return service.check(aResource, aOperation); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.security.authorization.AuthorizationService#getRules() + */ + public AuthorizationRule[] getRules() { + initialize(); + refresh(); + + return service.getRules(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#appendRule(org + * .wamblee.security.authorization.AuthorizationRule) + */ + public void appendRule(AuthorizationRule aRule) { + initialize(); + refresh(); + service.appendRule(aRule); + save(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#removeRule(int) + */ + public void removeRule(int aIndex) { + initialize(); + refresh(); + service.removeRule(aIndex); + save(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter + * (int, org.wamblee.security.authorization.AuthorizationRule) + */ + public void insertRuleAfter(int aIndex, AuthorizationRule aRule) { + initialize(); + refresh(); + service.insertRuleAfter(aIndex, aRule); + save(); + } + + /** + * Refreshes the state of the service through hibernate. + */ + private synchronized void refresh() { + long time = System.currentTimeMillis(); + + if ((time - lastRefreshTime) > refreshInterval) { + refreshByReload(); + lastRefreshTime = time; + } + } + + /** + * Saves any changes to the service state if necessary. + */ + private void save() { + AuthorizationService merged = entityManager.merge(service); + entityManager.flush(); + JpaMergeSupport.merge(merged, service); + } +} diff --git a/security/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java b/security/impl/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java similarity index 91% rename from security/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java rename to security/impl/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java index 161b652e..e509c281 100644 --- a/security/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java +++ b/security/impl/src/main/java/org/wamblee/security/encryption/Md5HexMessageDigester.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,25 +12,23 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.security.encryption; +import org.apache.commons.codec.binary.Hex; + import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import org.apache.commons.codec.binary.Hex; - /** - * MD5 Hex encoder. - * + * MD5 Hex encoder. + * * @author Erik Brakkee */ public class Md5HexMessageDigester implements MessageDigester { - /** - * Constructs the message digester. - * + * Constructs the message digester. + * */ public Md5HexMessageDigester() { // Empty @@ -46,10 +44,10 @@ public class Md5HexMessageDigester implements MessageDigester { MessageDigest digest = MessageDigest.getInstance("MD5"); byte[] result = digest.digest(aValue.getBytes()); char[] charResult = Hex.encodeHex(result); + return new String(charResult); } catch (NoSuchAlgorithmException e) { throw new IllegalArgumentException("MD5 not supported????"); } } - } diff --git a/security/src/main/java/org/wamblee/security/encryption/MessageDigester.java b/security/impl/src/main/java/org/wamblee/security/encryption/MessageDigester.java similarity index 73% rename from security/src/main/java/org/wamblee/security/encryption/MessageDigester.java rename to security/impl/src/main/java/org/wamblee/security/encryption/MessageDigester.java index 685a4c79..42be966f 100644 --- a/security/src/main/java/org/wamblee/security/encryption/MessageDigester.java +++ b/security/impl/src/main/java/org/wamblee/security/encryption/MessageDigester.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,19 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.encryption; /** - * Utility class that encapsulates a message digest method. + * Utility class that encapsulates a message digest method. */ public interface MessageDigester { - /** - * Computes a message digest for a value and encodes it in some way. - * @param aValue Value to compute digest for. - * @return Encoded digest. + * Computes a message digest for a value and encodes it in some way. + * + * @param aValue + * Value to compute digest for. + * + * @return Encoded digest. */ - String hash(String aValue); - + String hash(String aValue); } diff --git a/security/src/main/java/org/wamblee/usermgt/AbstractUserSet.java b/security/impl/src/main/java/org/wamblee/usermgt/AbstractUserSet.java similarity index 53% rename from security/src/main/java/org/wamblee/usermgt/AbstractUserSet.java rename to security/impl/src/main/java/org/wamblee/usermgt/AbstractUserSet.java index 1a3096f7..cb9602a4 100644 --- a/security/src/main/java/org/wamblee/usermgt/AbstractUserSet.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/AbstractUserSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,53 +13,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; -import static org.wamblee.usermgt.UserMgtException.Reason.DUPLICATE_USER; - import org.wamblee.security.encryption.MessageDigester; +import static org.wamblee.usermgt.UserMgtException.Reason.DUPLICATE_USER; /** - * User set base class. + * User set base class. */ public abstract class AbstractUserSet implements UserSet { - /** - * Password validator. + * Password validator. */ - private NameValidator _passwordValidator; - + private NameValidator passwordValidator; + /** - * Password encoder. + * Password encoder. */ - private MessageDigester _passwordEncoder; + private MessageDigester passwordEncoder; - - protected AbstractUserSet(NameValidator aPasswordValidator, - MessageDigester aPasswordEncoder) { - _passwordValidator = aPasswordValidator; - _passwordEncoder = aPasswordEncoder; + /** + * Creates a new AbstractUserSet object. + * + */ + protected AbstractUserSet(NameValidator aPasswordValidator, + MessageDigester aPasswordEncoder) { + passwordValidator = aPasswordValidator; + passwordEncoder = aPasswordEncoder; } - + /** - * Sets the password validtor and encoder in the user. - * @param aUser User. + * Sets the password validtor and encoder in the user. + * + * @param aUser + * User. */ - protected void setPasswordInfo(User aUser) { - aUser.setPasswordValidator(_passwordValidator); - aUser.setPasswordEncoder(_passwordEncoder); + protected void setPasswordInfo(User aUser) { + aUser.setPasswordValidator(passwordValidator); + aUser.setPasswordEncoder(passwordEncoder); } - /* (non-Javadoc) - * @see org.wamblee.usermgt.UserSet#createUser(java.lang.String, java.lang.String, org.wamblee.usermgt.Group) + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.UserSet#createUser(java.lang.String, + * java.lang.String, org.wamblee.usermgt.Group) */ - public User createUser(String aUsername, String aPassword, Group aGroup) throws UserMgtException { - User user = new User(aUsername, aPassword, aGroup, _passwordValidator, _passwordEncoder); + public User createUser(String aUsername, String aPassword, Group aGroup) + throws UserMgtException { + User user = new User(aUsername, aPassword, aGroup, passwordValidator, + passwordEncoder); + if (contains(user)) { throw new UserMgtException(DUPLICATE_USER, user); } + add(user); + return user; } } diff --git a/security/impl/src/main/java/org/wamblee/usermgt/Group.java b/security/impl/src/main/java/org/wamblee/usermgt/Group.java new file mode 100644 index 00000000..b203c63d --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/usermgt/Group.java @@ -0,0 +1,162 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Version; + +/** + * Represents a group. + * + * @author Erik Brakkee + */ +@Entity +@Table(name = "SEC_GROUP") +@NamedQueries( { + @NamedQuery(name = Group.QUERY_FIND_BY_NAME, query = "select g from Group g where g.name = :" + + Group.NAME_PARAM), + @NamedQuery(name = Group.QUERY_COUNT_GROUPS, query = "select count(g) from Group g"), + @NamedQuery(name = Group.QUERY_ALL_GROUPS, query = "select g from Group g") }) +public class Group implements Serializable, Comparable { + + public static final String QUERY_FIND_BY_NAME = "Group.findByName"; + public static final String QUERY_COUNT_GROUPS = "Group.count"; + public static final String QUERY_ALL_GROUPS = "Group.all"; + public static final String NAME_PARAM = "name"; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + /** + * Group name. + */ + @Column(nullable = false, unique = true) + private String name; + + /** + * Constructs the group. + * + * @param aName + */ + Group(String aName) { + super(); + name = aName; + } + + /** + * Creates a new Group object. + * + */ + public Group(Group aGroup) { + primaryKey = aGroup.primaryKey; + version = aGroup.version; + name = aGroup.name; + } + + /** + * Creates a new Group object. + */ + protected Group() { + super(); + name = null; + } + + /** + * Gets the name of the group. + * + * @return Group name. + */ + public String getName() { + return name; + } + + /** + * Sets the group name. + * + * @param aName + * Group name. + */ + void setName(String aName) { + name = aName; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object aGroup) { + if (aGroup == null) { + return false; + } + if (!(aGroup instanceof Group)) { + return false; + } + + return name.equals(((Group) aGroup).name); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(T) + */ + public int compareTo(Object aGroup) { + return name.compareTo(((Group) aGroup).name); + } + + public Long getPrimaryKey() { + return primaryKey; + } + + public void setPrimaryKey(Long aKey) { + primaryKey = aKey; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Group(pk = " + getPrimaryKey() + ", name=" + name + ")"; + } +} diff --git a/security/src/main/java/org/wamblee/usermgt/GroupSet.java b/security/impl/src/main/java/org/wamblee/usermgt/GroupSet.java similarity index 55% rename from security/src/main/java/org/wamblee/usermgt/GroupSet.java rename to security/impl/src/main/java/org/wamblee/usermgt/GroupSet.java index 780d60bb..cc187a14 100644 --- a/security/src/main/java/org/wamblee/usermgt/GroupSet.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/GroupSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,61 +13,76 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; import java.util.Set; /** - * Represents a set of groups. A typical implemnetation would be, a readonly implementation - * defined in a configuration file or a list of groups defined in a database. - * + * Represents a set of groups. A typical implemnetation would be, a readonly + * implementation defined in a configuration file or a list of groups defined in + * a database. + * * @author Erik Brakkee */ public interface GroupSet { - /** - * Must be called when the group has been modified to notify the group set. - * @param aGroup Group that was modified. + * Must be called when the group has been modified to notify the group set. + * + * @param aGroup + * Group that was modified. */ - void groupModified(Group aGroup); - + void groupModified(Group aGroup); + /** - * Finds the group by name. - * @param aName Group name. - * @return Group or null if not found. + * Finds the group by name. + * + * @param aName + * Group name. + * + * @return Group or null if not found. */ Group find(String aName); - + /** - * Determines if the group exists. - * @param aGroup Group. - * @return True iff the group exists. + * Determines if the group exists. + * + * @param aGroup + * Group. + * + * @return True iff the group exists. */ boolean contains(Group aGroup); - + /** - * Adds a group. If the group already exists, the existing group set - * is left unchanged. - * @param aGroup Group. + * Adds a group. If the group already exists, the existing group set is left + * unchanged. + * + * @param aGroup + * Group. + * */ boolean add(Group aGroup); - + /** - * Removes a group. If the group does not exist, this method is a no-op. - * @param aGroup Group to remove. - * @return True if the group was removed, false otherwise. + * Removes a group. If the group does not exist, this method is a no-op. + * + * @param aGroup + * Group to remove. + * + * @return True if the group was removed, false otherwise. */ boolean remove(Group aGroup); - + /** - * Returns the current groups. - * @return Groups. + * Returns the current groups. + * + * @return Groups. */ Set list(); /** - * @return The number of groups. + * + * @return The number of groups. */ - int size(); + int size(); } diff --git a/security/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java b/security/impl/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java similarity index 51% rename from security/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java rename to security/impl/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java index 2d2cb85f..ce2d7b8b 100644 --- a/security/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/InMemoryGroupSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,89 +12,119 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; +import java.util.ArrayList; +import java.util.List; import java.util.Set; import java.util.TreeSet; +import java.util.concurrent.atomic.AtomicLong; /** - * In-memory group set implementation. - * + * In-memory group set implementation. + * * @author Erik Brakkee */ public class InMemoryGroupSet implements GroupSet { - + + private AtomicLong pk = new AtomicLong(1l); + /** - * Groups. + * Groups. */ - private Set _groups; - + private List groups; + /** - * Constructs an empty group set. + * Constructs an empty group set. */ - public InMemoryGroupSet() { - _groups = new TreeSet(); + public InMemoryGroupSet() { + groups = new ArrayList(); } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#groupModified(org.wamblee.usermgt.Group) + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.usermgt.GroupSet#groupModified(org.wamblee.usermgt.Group) */ public void groupModified(Group aGroup) { - _groups.remove(aGroup); - _groups.add(aGroup); + for (int i = 0; i < groups.size(); i++) { + if (groups.get(i).getPrimaryKey().equals(aGroup.getPrimaryKey())) { + groups.remove(i); + groups.add(aGroup); + return; + } + } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#find(java.lang.String) */ public Group find(String aName) { - for (Group group: _groups) { - if ( group.getName().equals(aName)) { - return new Group(group); + for (Group group : groups) { + if (group.getName().equals(aName)) { + return group; } } - return null; + + return null; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#contains(org.wamblee.usermgt.Group) */ public boolean contains(Group aGroup) { - return _groups.contains(aGroup); + return groups.contains(aGroup); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#add(org.wamblee.usermgt.Group) */ public boolean add(Group aGroup) { - return _groups.add(aGroup); + aGroup.setPrimaryKey(pk.getAndIncrement()); + if (find(aGroup.getName()) != null) { + return false; + } + return groups.add(aGroup); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#remove(org.wamblee.usermgt.Group) */ public boolean remove(Group aGroup) { - return _groups.remove(aGroup); + return groups.remove(aGroup); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#list() */ public Set list() { - Set list = new TreeSet(); - for (Group group: _groups) { + Set list = new TreeSet(); + + for (Group group : groups) { list.add(new Group(group)); } + return list; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.GroupSet#size() */ public int size() { - return _groups.size(); + return groups.size(); } - } diff --git a/security/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java b/security/impl/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java similarity index 81% rename from security/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java rename to security/impl/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java index 6d25dc11..e048849d 100644 --- a/security/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/InMemoryUserSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,33 +12,33 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; +import org.wamblee.security.encryption.MessageDigester; + import java.util.Set; import java.util.TreeSet; -import org.wamblee.security.encryption.MessageDigester; - /** * In-memory user set. - * + * * @author Erik Brakkee */ public class InMemoryUserSet extends AbstractUserSet { - /** - * Users. All users in this set have their password validator and encoder set. + * Users. All users in this set have their password validator and encoder + * set. */ - private Set _users; + private Set users; /** * Constructs an empty user set. */ - public InMemoryUserSet(NameValidator aPasswordValidator, MessageDigester aPasswordEncoder) { + public InMemoryUserSet(NameValidator aPasswordValidator, + MessageDigester aPasswordEncoder) { super(aPasswordValidator, aPasswordEncoder); - _users = new TreeSet(); + users = new TreeSet(); } /* @@ -47,9 +47,9 @@ public class InMemoryUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#userModified(org.wamblee.usermgt.User) */ public void userModified(User aUser) { - _users.remove(aUser); - setPasswordInfo(aUser); - _users.add(aUser); + users.remove(aUser); + setPasswordInfo(aUser); + users.add(aUser); } /* @@ -58,11 +58,12 @@ public class InMemoryUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#find(java.lang.String) */ public User find(String aName) { - for (User user : _users) { + for (User user : users) { if (user.getName().equals(aName)) { return new User(user); } } + return null; } @@ -73,7 +74,8 @@ public class InMemoryUserSet extends AbstractUserSet { */ public boolean add(User aUser) { setPasswordInfo(aUser); - return _users.add(aUser); + + return users.add(aUser); } /* @@ -82,7 +84,7 @@ public class InMemoryUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#contains(org.wamblee.usermgt.User) */ public boolean contains(User aUser) { - return _users.contains(aUser); + return users.contains(aUser); } /* @@ -91,7 +93,7 @@ public class InMemoryUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#remove(org.wamblee.usermgt.User) */ public boolean remove(User aUser) { - return _users.remove(aUser); + return users.remove(aUser); } /* @@ -101,9 +103,11 @@ public class InMemoryUserSet extends AbstractUserSet { */ public Set list() { Set list = new TreeSet(); - for (User user : _users) { + + for (User user : users) { list.add(new User(user)); } + return list; } @@ -114,19 +118,22 @@ public class InMemoryUserSet extends AbstractUserSet { */ public Set list(Group aGroup) { Set result = new TreeSet(); - for (User user : _users) { + + for (User user : users) { if (user.getGroups().contains(aGroup)) { result.add(new User(user)); } } + return result; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.UserSet#size() */ public int size() { - return _users.size(); + return users.size(); } - } diff --git a/security/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java b/security/impl/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java similarity index 50% rename from security/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java rename to security/impl/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java index f353e3b1..ec7a25af 100644 --- a/security/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/JaasUserAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,46 +12,51 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; import java.security.AccessController; import java.security.Principal; + import java.util.Set; import javax.security.auth.Subject; /** - * Implementation of the user accessor that retrieves user information - * from JAAS. - * + * Implementation of the user accessor that retrieves user information from + * JAAS. + * * @author Erik Brakkee */ public class JaasUserAccessor implements UserAccessor { - /** - * User administration to use. + * User administration to use. */ - private UserAdministration _admin; + private UserAdministration admin; /** - * Class of the JAAS user principal. + * Class of the JAAS user principal. */ - private Class _userPrincipalClass; + private Class userPrincipalClass; /** - * Constructs user accessor. - * @param aAdmin User administration. - * @param aUserClassName Class name of the user principal. + * Constructs user accessor. + * + * @param aAdmin + * User administration. + * @param aUserClassName + * Class name of the user principal. */ public JaasUserAccessor(UserAdministration aAdmin, String aUserClassName) { - _admin = aAdmin; + admin = aAdmin; + try { - _userPrincipalClass = Class.forName(aUserClassName); - if ( !Principal.class.isAssignableFrom(_userPrincipalClass)) { - throw new IllegalArgumentException("Specified class '" + aUserClassName + "' is not a subclass of '" + - Principal.class.getName()); + userPrincipalClass = Class.forName(aUserClassName); + + if (!Principal.class.isAssignableFrom(userPrincipalClass)) { + throw new IllegalArgumentException("Specified class '" + + aUserClassName + "' is not a subclass of '" + + Principal.class.getName()); } } catch (ClassNotFoundException e) { throw new RuntimeException(e); @@ -65,37 +70,50 @@ public class JaasUserAccessor implements UserAccessor { */ public User getCurrentUser() { Subject subject = Subject.getSubject(AccessController.getContext()); + if (subject == null) { return null; } + Principal userPrincipal = getUserPrincipal(subject); - - return _admin.getUser(userPrincipal.getName()); + + return admin.getUser(userPrincipal.getName()); } /** - * Gets the user principal from the subject. - * @param subject Subject. - * @return User principal. - * @throws IllegalArgumentException In case there is a duplicate principal or the principal was not found. + * Gets the user principal from the subject. + * + * @param aSubject + * Subject. + * + * @return User principal. + * + * @throws IllegalArgumentException + * In case there is a duplicate principal or the principal was + * not found. */ - private Principal getUserPrincipal(Subject subject) { - Set principals = subject.getPrincipals(); - Principal userPrincipal = null; - for ( Principal principal: principals) { - if ( principal.getClass().equals(_userPrincipalClass)) { - if ( userPrincipal != null ) { + private Principal getUserPrincipal(Subject aSubject) { + Set principals = aSubject.getPrincipals(); + Principal userPrincipal = null; + + for (Principal principal : principals) { + if (principal.getClass().equals(userPrincipalClass)) { + if (userPrincipal != null) { throw new IllegalArgumentException( - "Multiple principals for class '" + _userPrincipalClass + "', subject: " + subject); + "Multiple principals for class '" + userPrincipalClass + + "', subject: " + aSubject); } - userPrincipal = principal; + + userPrincipal = principal; } } - if ( userPrincipal == null ) { + + if (userPrincipal == null) { throw new IllegalArgumentException( - "No user principal found for class '" + _userPrincipalClass + "', subject: " + subject); + "No user principal found for class '" + userPrincipalClass + + "', subject: " + aSubject); } + return userPrincipal; } - } diff --git a/security/src/main/java/org/wamblee/usermgt/NameValidator.java b/security/impl/src/main/java/org/wamblee/usermgt/NameValidator.java similarity index 71% rename from security/src/main/java/org/wamblee/usermgt/NameValidator.java rename to security/impl/src/main/java/org/wamblee/usermgt/NameValidator.java index f120d24a..d2b189e0 100644 --- a/security/src/main/java/org/wamblee/usermgt/NameValidator.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/NameValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; /** * Validator of names. - * + * * @author Erik Brakkee */ public interface NameValidator { - /** - * Validates a name. - * @param aName Name - * @throws UserMgtException In case the name is invalid. + * Validates a name. + * + * @param aName + * Name + * + * @throws UserMgtException + * In case the name is invalid. */ - void validate(String aName) throws UserMgtException; + void validate(String aName) throws UserMgtException; } diff --git a/security/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java b/security/impl/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java similarity index 58% rename from security/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java rename to security/impl/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java index 8acf1158..8a774eb7 100644 --- a/security/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/RegexpNameValidator.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,73 +13,80 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; import org.wamblee.usermgt.UserMgtException.Reason; /** - * Validation of names based on a regular expression. - * + * Validation of names based on a regular expression. + * * @author Erik Brakkee */ public class RegexpNameValidator implements NameValidator { - /** - * Convenience pattern for an id. + * Convenience pattern for an id. */ public static final String ID_PATTERN = "[a-zA-Z]+[a-zA-Z0-9]*"; - + /** - * Convenience pattern for a password consisting of at least 6 characters. + * Convenience pattern for a password consisting of at least 6 characters. */ public static final String PASSWORD_PATTERN = ".{6}.*"; - + /** - * Pattern to use. + * Pattern to use. */ - private String _pattern; - + private String pattern; + /** - * Reason to use when validation fails. + * Reason to use when validation fails. */ - private Reason _reason; - + private Reason reason; + /** - * Message to report. + * Message to report. */ - private String _message; - + private String message; + /** - * Validates a regular expression. - * @param aPattern Pattern that names must comply to. - * @param aReason Reason to report when validation fails. - * @param aMessage Message to report. + * Validates a regular expression. + * + * @param aPattern + * Pattern that names must comply to. + * @param aReason + * Reason to report when validation fails. + * @param aMessage + * Message to report. */ - public RegexpNameValidator(String aPattern, Reason aReason, String aMessage) { - _pattern = aPattern; - _reason = aReason; - _message = aMessage; + public RegexpNameValidator(String aPattern, Reason aReason, String aMessage) { + pattern = aPattern; + reason = aReason; + message = aMessage; } - + /** - * Convenience constructor with all string parameters. Useful for configuration - * in Spring. - * @param aPattern Pattern to use. - * @param aReason Reason. - * @param aMessage Message. + * Convenience constructor with all string parameters. Useful for + * configuration in Spring. + * + * @param aPattern + * Pattern to use. + * @param aReason + * Reason. + * @param aMessage + * Message. */ - public RegexpNameValidator(String aPattern, String aReason, String aMessage) { + public RegexpNameValidator(String aPattern, String aReason, String aMessage) { this(aPattern, Reason.valueOf(aReason), aMessage); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.NameValidator#validate(java.lang.String) */ public void validate(String aName) throws UserMgtException { - if ( !aName.matches(_pattern)) { - throw new UserMgtException(_reason, _message); + if (!aName.matches(pattern)) { + throw new UserMgtException(reason, message); } } - } diff --git a/security/impl/src/main/java/org/wamblee/usermgt/User.java b/security/impl/src/main/java/org/wamblee/usermgt/User.java new file mode 100644 index 00000000..7462507a --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/usermgt/User.java @@ -0,0 +1,406 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import java.io.Serializable; +import java.util.Set; +import java.util.TreeSet; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.persistence.Version; + +import org.wamblee.security.encryption.MessageDigester; +import org.wamblee.usermgt.UserMgtException.Reason; + +/** + * Represents a user. The methods for managing the groups of the user have + * package scope. Managing the groups of the user should be done through the + * {@link org.wamblee.usermgt.UserAdministration} interface. + */ +@Entity +@Table(name = "SEC_USER") +@NamedQueries( { + @NamedQuery(name = User.QUERY_FIND_BY_NAME, query = "select u from User u where u.name = :" + + User.NAME_PARAM), + @NamedQuery(name = User.QUERY_FIND_BY_GROUP_NAME, query = "select user from User user join user.groups grp where grp.name = :name"), + @NamedQuery(name = User.QUERY_COUNT_USERS, query = "select count(u) from User u"), + @NamedQuery(name = User.QUERY_ALL_USERS, query = "select u from User u")}) +public class User implements Serializable, Comparable { + + public static final String QUERY_FIND_BY_NAME = "User.findByName"; + public static final String QUERY_FIND_BY_GROUP_NAME = "User.findByGroupName"; + public static final String QUERY_COUNT_USERS = "User.count"; + public static final String QUERY_ALL_USERS = "User.all"; + public static final String NAME_PARAM = "name"; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long primaryKey; + + @Version + private int version; + + /** + * User name. + */ + private String name; + + /** + * Password. + */ + private String password; + + /** + * Groups the user belongs to. + */ + @ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER) + private Set groups; + + /** + * Password validator. + */ + @Transient + private NameValidator passwordValidator; + + /** + * Password encoder. + */ + @Transient + private MessageDigester passwordEncoder; + + /** + * Constructs the user. + * + * @param aName + * User name. + * @param aPassword + * Password. + * @param aGroup + * Group the user belongs to. + */ + User(String aName, String aPassword, Group aGroup, + NameValidator aPasswordValidator, MessageDigester aPasswordEncoder) + throws UserMgtException { + super(); + name = aName; + aPasswordValidator.validate(aPassword); + password = aPasswordEncoder.hash(aPassword); + groups = new TreeSet(); + groups.add(aGroup); + passwordValidator = aPasswordValidator; + passwordEncoder = aPasswordEncoder; + } + + /** + * Creates a new User object. + * + */ + public User(User aUser) { + primaryKey = aUser.primaryKey; + version = aUser.version; + name = aUser.name; + password = aUser.password; + groups = new TreeSet(); + + for (Group group : aUser.groups) { + groups.add(new Group(group)); + } + + passwordValidator = aUser.passwordValidator; + passwordEncoder = aUser.passwordEncoder; + } + + /** + * Creates a new User object. + */ + User() { + super(); + name = null; + password = null; + groups = null; + passwordValidator = null; + passwordEncoder = null; + } + + /** + * Sets the password validator. + * + * @param aPasswordValidator + * Validator. + */ + public void setPasswordValidator(NameValidator aPasswordValidator) { + passwordValidator = aPasswordValidator; + } + + /** + * Sets the password encoder. + * + * @param aPasswordEncoder + * Encoder. + */ + public void setPasswordEncoder(MessageDigester aPasswordEncoder) { + passwordEncoder = aPasswordEncoder; + } + + /** + * + * @return Returns the password. + */ + String getPassword() { + return password; + } + + /** + * Checks the password. + * + * @param aPassword + * Password to check. + * + * @throws UserMgtException + * In case the password is incorrect. + */ + public void checkPassword(String aPassword) throws UserMgtException { + String encoded = passwordEncoder.hash(aPassword); + + if (!password.equals(encoded)) { + throw new UserMgtException(Reason.INVALID_PASSWORD, this); + } + } + + /** + * Changes the password. + * + * @param aOldPassword + * Old password. + * @param aNewPassword + * New password. + * + * @throws UserMgtException + * In case the old password is incorrect. + */ + public void changePassword(String aOldPassword, String aNewPassword) + throws UserMgtException { + checkPassword(aOldPassword); + passwordValidator.validate(aNewPassword); + setPassword(aNewPassword); + } + + /** + * + * @param aPassword + * The password to set. + * + */ + public void setPassword(String aPassword) throws UserMgtException { + passwordValidator.validate(aPassword); + password = passwordEncoder.hash(aPassword); + } + + /** + * For OR mapping. + * + * @return Password. + */ + protected String getPasswordString() { + return password; + } + + /** + * For OR mapping. + * + * @param aPassword + * Password. + */ + protected void setPasswordString(String aPassword) { + password = aPassword; + } + + /** + * + * @return Returns the _user. + */ + public String getName() { + return name; + } + + /** + * + * @param aName + * The username to set. + */ + void setName(String aName) { + name = aName; + } + + /** + * Gets the groups the user belongs to. + * + * @return Groups. + */ + public Set getGroups() { + Set result = new TreeSet(); + result.addAll(groups); + + return result; + } + + /** + * Checks whether the user belongs to the given group. + * + * @param aGroup + * Group. + * + * @return True if the user belongs to the group. + */ + public boolean isInGroup(Group aGroup) { + return groups.contains(aGroup); + } + + /** + * Checks whether the user belongs to the given group. + * + * @param aGroup + * Group. + * + * @return True if the user belongs to the group. + */ + public boolean isInGroup(String aGroup) { + return groups.contains(new Group(aGroup)); + } + + /** + * Gets the group set. For OR mapping. + * + * @return set of groups. + */ + Set getGroupSet() { + return groups; + } + + /** + * Sets the groups the user belongs to, for OR mapping. + * + * @param aGroups + * Groups. + */ + void setGroupSet(Set aGroups) { + groups = aGroups; + } + + /** + * Adds the user to a group. + * + * @param aGroup + * Group to add the user to. + * + * @throws UserMgtException + * In case the user already belongs to the group. + */ + void addGroup(Group aGroup) throws UserMgtException { + if (groups.contains(aGroup)) { + throw new UserMgtException(Reason.USER_ALREADY_IN_GROUP, aGroup); + } + + groups.add(aGroup); + } + + /** + * Removes the user from a group. + * + * @param aGroup + * Group. + * + * @throws UserMgtException + * In case the user does not belong to the group. + */ + void removeGroup(Group aGroup) throws UserMgtException { + if (!groups.contains(aGroup)) { + throw new UserMgtException(Reason.USER_NOT_IN_GROUP, this, aGroup); + } + + if (groups.size() == 1) { + throw new UserMgtException(Reason.USER_MUST_BE_IN_A_GROUP, this, + aGroup); + } + + groups.remove(aGroup); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object aUser) { + if (!(aUser instanceof User)) { + return false; + } + + User user = (User) aUser; + + return name.equals(user.name); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + return name.hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + String result = "User(name=" + name + ", password=" + password; + + for (Group group : groups) { + result += (", group=" + group); + } + + return result + ")"; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Comparable#compareTo(T) + */ + public int compareTo(Object aUser) { + return name.compareTo(((User) aUser).name); + } + + public Long getPrimaryKey() { + return primaryKey; + } +} diff --git a/security/src/main/java/org/wamblee/usermgt/UserAccessor.java b/security/impl/src/main/java/org/wamblee/usermgt/UserAccessor.java similarity index 80% rename from security/src/main/java/org/wamblee/usermgt/UserAccessor.java rename to security/impl/src/main/java/org/wamblee/usermgt/UserAccessor.java index d3dd8a9e..74ea55c9 100644 --- a/security/src/main/java/org/wamblee/usermgt/UserAccessor.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; /** - * Interface for accessing the currently logged in user. - * + * Interface for accessing the currently logged in user. + * * @author Erik Brakkee */ public interface UserAccessor { /** - * Gets the current user. - * @return Currently logged in user or null if no user is found. + * Gets the current user. + * + * @return Currently logged in user or null if no user is found. */ - User getCurrentUser(); + User getCurrentUser(); } diff --git a/security/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java b/security/impl/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java similarity index 64% rename from security/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java rename to security/impl/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java index 58263ebc..85f677ef 100644 --- a/security/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserAdminInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,70 +12,78 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; -import java.security.NoSuchAlgorithmException; - import org.apache.log4j.Logger; +import java.security.NoSuchAlgorithmException; + /** * User administration initializer. It populates the user administration with a * number of groups and users but only in case no users exist. - * + * * @author Erik Brakkee */ public class UserAdminInitializer { - - private static final Logger LOGGER = Logger.getLogger(UserAdminInitializer.class); - + private static final Logger LOGGER = Logger + .getLogger(UserAdminInitializer.class); + /** * Initializes the user administration in case no users are present. * */ public UserAdminInitializer(UserAdministration aAdmin, String[] aUsers, - String[] aGroups, String[] aPasswords) throws UserMgtException, NoSuchAlgorithmException { - if (aUsers.length != aGroups.length - || aUsers.length != aPasswords.length) { + String[] aGroups, String[] aPasswords) throws UserMgtException, + NoSuchAlgorithmException { + if ((aUsers.length != aGroups.length) || + (aUsers.length != aPasswords.length)) { throw new IllegalArgumentException( - "Array sizes for users, groups, and passwords differ: " - + aUsers.length + "," + aGroups.length + "," - + aPasswords.length); - + "Array sizes for users, groups, and passwords differ: " + + aUsers.length + "," + aGroups.length + "," + + aPasswords.length); } + if (aAdmin.getUserCount() == 0) { initialize(aAdmin, aUsers, aGroups, aPasswords); } - } /** - * Adds the specified users and groups to the user administration. - * @param aAdmin User administration. - * @param aUsers Users. - * @param aGroups Groups. - * @param aPasswords Passwords. - * @throws UserMgtException In case of a problem creating users or groups. + * Adds the specified users and groups to the user administration. + * + * @param aAdmin + * User administration. + * @param aUsers + * Users. + * @param aGroups + * Groups. + * @param aPasswords + * Passwords. + * + * @throws UserMgtException + * In case of a problem creating users or groups. */ private void initialize(UserAdministration aAdmin, String[] aUsers, - String[] aGroups, String[] aPasswords) throws UserMgtException { + String[] aGroups, String[] aPasswords) throws UserMgtException { for (int i = 0; i < aUsers.length; i++) { String user = aUsers[i]; String group = aGroups[i]; String password = aPasswords[i]; - + if (aAdmin.getUser(user) == null) { // must create user. Group groupObj = aAdmin.getGroup(group); + if (groupObj == null) { // must create group LOGGER.info("Creating group: " + group); groupObj = aAdmin.createGroup(group); } - assert groupObj != null; - - LOGGER.info("Creating user: " + user + " password: " + password); + assert groupObj != null; + + LOGGER + .info("Creating user: " + user + " password: " + password); aAdmin.createUser(user, password, groupObj); } } diff --git a/security/impl/src/main/java/org/wamblee/usermgt/UserAdministration.java b/security/impl/src/main/java/org/wamblee/usermgt/UserAdministration.java new file mode 100644 index 00000000..28e05b9d --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserAdministration.java @@ -0,0 +1,206 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import java.util.Set; + +/** + * Interface for user administration. Manages the users and groups. + * + * @author Erik Brakkee + */ +public interface UserAdministration { + /** + * Creates a new user. + * + * @param aUser + * Username. + * @param aPassword + * Password. + * @param aGroup + * Group. + * + * @return User. + * + * @throws UserMgtException + * In case there is a conflict with an existing user. + */ + User createUser(String aUser, String aPassword, Group aGroup) + throws UserMgtException; + + /** + * Creates a new group. + * + * @param aName + * Group name. + * + * @return Group + * + * @throws UserMgtException + * In case there is a conflict with an existing group. + */ + Group createGroup(String aName) throws UserMgtException; + + /** + * + * @return Number of users. + */ + int getUserCount(); + + /** + * + * @return Number of groups. + */ + int getGroupCount(); + + /** + * Must be called when the user is modified. + * + * @param aUser + * User. + * @return The modified user. The user passed in to this call should be considered invalid. + */ + void userModified(User aUser); + + /** + * Must be called when the group is modified. + * + * @param aGroup + * Group. + */ + void groupModified(Group aGroup); + + /** + * Gets the user for a given name. + * + * @param aName + * User name. + * + * @return User or null if not found. + */ + User getUser(String aName); + + /** + * Gets the group for a given group name. + * + * @param aName + * Group name. + * + * @return Group or null if not found. + */ + Group getGroup(String aName); + + /** + * Get the users. + * + * @return All known users. + */ + Set getUsers(); + + /** + * Gets the users for a given group. + * + * @param aGroup + * Group. + * @return Set of users (always non-null). + */ + Set getUsers(Group aGroup); + + /** + * Gets all known groups. + * + * @return Groups. + */ + Set getGroups(); + + /** + * Renames a user. + * + * @param aUser + * User object for which user name must be changed. + * @param aUserName + * New user name. + * + * @throws UserMgtException + * In case the user is not known or the new user name is already + * in use by another user. + */ + void renameUser(User aUser, String aUserName) throws UserMgtException; + + /** + * Renames a group. + * + * @param aGroup + * Group to rename. + * @param aGroupName + * New name for the group. + * + * @throws UserMgtException + * In case the new group name is already used by another group + * of if the existing group is unknown. + */ + void renameGroup(Group aGroup, String aGroupName) throws UserMgtException; + + /** + * Removes the user. + * + * @param aUser + * User to remove. + * + * @throws UserMgtException + * In case the user does not exist. + */ + void removeUser(User aUser) throws UserMgtException; + + /** + * Removes the group. + * + * @param aGroup + * Group to remove. + * + * @throws UserMgtException + * In case there are still users that are in the given group. + */ + void removeGroup(Group aGroup) throws UserMgtException; + + /** + * Adds a user to a group. + * + * @param aUser + * User. + * @param aGroup + * Group. + * + * @throws UserMgtException + * In case the user or group or not known or if the user is + * already part of the group. + */ + void addUserToGroup(User aUser, Group aGroup) throws UserMgtException; + + /** + * Removes a user from a group. + * + * @param aUser + * User + * @param aGroup + * Group + * + * @throws UserMgtException + * In case the user or group are unknown or if the user is not + * part of the group. + */ + void removeUserFromGroup(User aUser, Group aGroup) throws UserMgtException; +} diff --git a/security/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java b/security/impl/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java similarity index 63% rename from security/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java rename to security/impl/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java index dceca930..6866d454 100644 --- a/security/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserAdministrationImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; import static org.wamblee.usermgt.UserMgtException.Reason.DUPLICATE_GROUP; @@ -27,88 +26,97 @@ import java.util.Set; /** * Administration of users and groups. - * + * * @author Erik Brakkee */ public class UserAdministrationImpl implements UserAdministration { - /** * All known users. */ - private UserSet _users; + private UserSet users; /** * All known groups. */ - private GroupSet _groups; - + private GroupSet groups; + /** - * Validator for user names. + * Validator for user names. */ - private NameValidator _userValidator; - + private NameValidator userValidator; + /** - * Validator for group names. + * Validator for group names. */ - private NameValidator _groupValidator; - + private NameValidator groupValidator; + /** * Constructs empty user administration. * */ - public UserAdministrationImpl(UserSet aUsers, GroupSet aGroups, NameValidator aUserValidator, - NameValidator aGroupValidator) { - _users = aUsers; - _groups = aGroups; - _userValidator = aUserValidator; - _groupValidator = aGroupValidator; + public UserAdministrationImpl(UserSet aUsers, GroupSet aGroups, + NameValidator aUserValidator, NameValidator aGroupValidator) { + users = aUsers; + groups = aGroups; + userValidator = aUserValidator; + groupValidator = aGroupValidator; } /* * (non-Javadoc) * * @see org.wamblee.usermgt.UserAdministration#createUser(java.lang.String, - * java.lang.String) + * java.lang.String) */ public User createUser(String aUser, String aPassword, Group aGroup) - throws UserMgtException { - _userValidator.validate(aUser); + throws UserMgtException { + userValidator.validate(aUser); checkGroup(aGroup); - User user = _users.createUser(aUser, aPassword, aGroup); + + User user = users.createUser(aUser, aPassword, aGroup); + return new User(user); } - + /* * (non-Javadoc) * * @see org.wamblee.usermgt.UserAdministration#createGroup(java.lang.String) */ public Group createGroup(String aName) throws UserMgtException { - _groupValidator.validate(aName); + groupValidator.validate(aName); + Group group = new Group(aName); - if (_groups.contains(group)) { + + if (groups.contains(group)) { throw new UserMgtException(DUPLICATE_GROUP, group); } - _groups.add(group); + + groups.add(group); + return new Group(group); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#userModified(org.wamblee.usermgt.User) + * @see + * org.wamblee.usermgt.UserAdministration#userModified(org.wamblee.usermgt + * .User) */ public void userModified(User aUser) { - _users.userModified(aUser); + users.userModified(aUser); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#groupModified(org.wamblee.usermgt.Group) + * @see + * org.wamblee.usermgt.UserAdministration#groupModified(org.wamblee.usermgt + * .Group) */ public void groupModified(Group aGroup) { - _groups.groupModified(aGroup); + groups.groupModified(aGroup); } /* @@ -117,7 +125,7 @@ public class UserAdministrationImpl implements UserAdministration { * @see org.wamblee.usermgt.UserAdministration#getUser(java.lang.String) */ public User getUser(String aName) { - return _users.find(aName); + return users.find(aName); } /* @@ -126,7 +134,7 @@ public class UserAdministrationImpl implements UserAdministration { * @see org.wamblee.usermgt.UserAdministration#getGroup(java.lang.String) */ public Group getGroup(String aName) { - return _groups.find(aName); + return groups.find(aName); } /* @@ -135,16 +143,18 @@ public class UserAdministrationImpl implements UserAdministration { * @see org.wamblee.usermgt.UserAdministration#getUsers() */ public Set getUsers() { - return _users.list(); + return users.list(); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#getUsers(org.wamblee.usermgt.Group) + * @see + * org.wamblee.usermgt.UserAdministration#getUsers(org.wamblee.usermgt.Group + * ) */ public Set getUsers(Group aGroup) { - return _users.list(aGroup); + return users.list(aGroup); } /* @@ -153,137 +163,157 @@ public class UserAdministrationImpl implements UserAdministration { * @see org.wamblee.usermgt.UserAdministration#getGroups() */ public Set getGroups() { - return _groups.list(); + return groups.list(); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#removeUser(org.wamblee.usermgt.User) + * @see + * org.wamblee.usermgt.UserAdministration#removeUser(org.wamblee.usermgt + * .User) */ public void removeUser(User aUser) throws UserMgtException { checkUser(aUser); - _users.remove(aUser); + users.remove(aUser); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#removeGroup(org.wamblee.usermgt.Group) + * @see + * org.wamblee.usermgt.UserAdministration#removeGroup(org.wamblee.usermgt + * .Group) */ public void removeGroup(Group aGroup) throws UserMgtException { checkGroup(aGroup); + if (getUsers(aGroup).size() > 0) { throw new UserMgtException(GROUP_STILL_OCCUPIED, aGroup); } - _groups.remove(aGroup); + + groups.remove(aGroup); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#renameUser(org.wamblee.usermgt.User, - * java.lang.String) + * @see + * org.wamblee.usermgt.UserAdministration#renameUser(org.wamblee.usermgt + * .User, java.lang.String) */ public void renameUser(User aUser, String aUserName) - throws UserMgtException { + throws UserMgtException { checkUser(aUser); + if (aUser.getName().equals(aUserName)) { throw new UserMgtException(TRIVIAL_RENAME, aUser); } - if (_users.find(aUserName) != null) { + + if (users.find(aUserName) != null) { throw new UserMgtException(DUPLICATE_USER, aUser); } - _userValidator.validate(aUserName); - // we are modifying the user so we should re-insert it into the set - // after renaming it. - _users.remove(aUser); + + userValidator.validate(aUserName); + aUser.setName(aUserName); - _users.add(aUser); + users.userModified(aUser); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#renameGroup(org.wamblee.usermgt.Group, - * java.lang.String) + * @see + * org.wamblee.usermgt.UserAdministration#renameGroup(org.wamblee.usermgt + * .Group, java.lang.String) */ public void renameGroup(Group aGroup, String aGroupName) - throws UserMgtException { + throws UserMgtException { checkGroup(aGroup); + if (aGroup.getName().equals(aGroupName)) { throw new UserMgtException(TRIVIAL_RENAME, aGroup); } - if (_groups.find(aGroupName) != null) { + + if (groups.find(aGroupName) != null) { throw new UserMgtException(DUPLICATE_GROUP, aGroup); } - _groupValidator.validate(aGroupName); - // we are renaming the group so we should re-insert it into the set - // after renaming it. - _groups.remove(aGroup); + + groupValidator.validate(aGroupName); + aGroup.setName(aGroupName); - _groups.add(aGroup); + groups.groupModified(aGroup); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#addUserToGroup(org.wamblee.usermgt.User, - * org.wamblee.usermgt.Group) + * @see + * org.wamblee.usermgt.UserAdministration#addUserToGroup(org.wamblee.usermgt + * .User, org.wamblee.usermgt.Group) */ public void addUserToGroup(User aUser, Group aGroup) - throws UserMgtException { + throws UserMgtException { checkUser(aUser); checkGroup(aGroup); aUser.addGroup(aGroup); - _users.userModified(aUser); + users.userModified(aUser); } /* * (non-Javadoc) * - * @see org.wamblee.usermgt.UserAdministration#removeUserFromGroup(org.wamblee.usermgt.User, - * org.wamblee.usermgt.Group) + * @see + * org.wamblee.usermgt.UserAdministration#removeUserFromGroup(org.wamblee + * .usermgt.User, org.wamblee.usermgt.Group) */ public void removeUserFromGroup(User aUser, Group aGroup) - throws UserMgtException { + throws UserMgtException { checkUser(aUser); checkGroup(aGroup); aUser.removeGroup(aGroup); - _users.userModified(aUser); + users.userModified(aUser); } /** + * * @param aUser + * * @throws UserMgtException */ private void checkUser(User aUser) throws UserMgtException { - if (!_users.contains(aUser)) { + if (!users.contains(aUser)) { throw new UserMgtException(UNKNOWN_USER, aUser); } } /** + * * @param aGroup + * * @throws UserMgtException */ private void checkGroup(Group aGroup) throws UserMgtException { - if (!_groups.contains(aGroup)) { + if (!groups.contains(aGroup)) { throw new UserMgtException(UNKNOWN_GROUP, aGroup); } } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.UserAdministration#getUserCount() */ public int getUserCount() { - return _users.size(); + return users.size(); } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.UserAdministration#getGroupCount() */ public int getGroupCount() { - return _groups.size(); + return groups.size(); } } diff --git a/security/src/main/java/org/wamblee/usermgt/UserMgtException.java b/security/impl/src/main/java/org/wamblee/usermgt/UserMgtException.java similarity index 55% rename from security/src/main/java/org/wamblee/usermgt/UserMgtException.java rename to security/impl/src/main/java/org/wamblee/usermgt/UserMgtException.java index 6a96e618..588018ae 100644 --- a/security/src/main/java/org/wamblee/usermgt/UserMgtException.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserMgtException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,44 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; import java.util.EnumMap; /** - * User management exception. - * + * User management exception. + * * @author Erik Brakkee */ public class UserMgtException extends Exception { - - static final long serialVersionUID = 5585349754997507529L; - - /** - * Possible causes for the exception. - * - */ - public enum Reason { - UNKNOWN_USER, - UNKNOWN_GROUP, - DUPLICATE_USER, - DUPLICATE_GROUP, - USER_ALREADY_IN_GROUP, - USER_NOT_IN_GROUP, - TRIVIAL_RENAME, - INVALID_PASSWORD, - GROUP_STILL_OCCUPIED, - USER_MUST_BE_IN_A_GROUP, - INVALID_USERNAME, - INVALID_GROUPNAME - } - + static final long serialVersionUID = 5585349754997507529L; + /** - * Mapping of enum to exception message text. + * Mapping of enum to exception message text. */ - private static final EnumMap MESSAGES = new EnumMap(Reason.class); - + private static final EnumMap MESSAGES = new EnumMap( + Reason.class); + static { MESSAGES.put(Reason.UNKNOWN_USER, "Unknown user"); MESSAGES.put(Reason.UNKNOWN_GROUP, "Unknown group"); @@ -61,68 +41,97 @@ public class UserMgtException extends Exception { MESSAGES.put(Reason.TRIVIAL_RENAME, "Trivial rename"); MESSAGES.put(Reason.INVALID_PASSWORD, "Invalid password"); MESSAGES.put(Reason.GROUP_STILL_OCCUPIED, "Group still occupied"); - MESSAGES.put(Reason.USER_MUST_BE_IN_A_GROUP, "User must be in at least one group"); + MESSAGES.put(Reason.USER_MUST_BE_IN_A_GROUP, + "User must be in at least one group"); MESSAGES.put(Reason.INVALID_USERNAME, "Invalid user name"); MESSAGES.put(Reason.INVALID_GROUPNAME, "Invalid group name"); } - + /** - * Cause of the exception. + * Cause of the exception. */ - private Reason _cause; - + private Reason cause; + /** - * User or null if no user is relevant for the problem. + * User or null if no user is relevant for the problem. */ - private User _user; - + private User user; + /** - * Group or null if no group is relevant for the problem. + * Group or null if no group is relevant for the problem. */ - private Group _group; + private Group group; + /** + * Creates a new UserMgtException object. + * + */ public UserMgtException(Reason aCause, String aMessage) { super(MESSAGES.get(aCause) + ": " + aMessage); - _cause = aCause; + cause = aCause; } - + + /** + * Creates a new UserMgtException object. + * + */ public UserMgtException(Reason aCause, User aUser) { this(aCause, "for user '" + aUser.getName() + "'"); - _user = aUser; + user = aUser; } - + + /** + * Creates a new UserMgtException object. + * + */ public UserMgtException(Reason aCause, Group aGroup) { this(aCause, "for group '" + aGroup.getName() + "'"); - _group = aGroup; + group = aGroup; } - + + /** + * Creates a new UserMgtException object. + * + */ public UserMgtException(Reason aCause, User aUser, Group aGroup) { - this(aCause, "for user '" + aUser.getName() + "' and group '" + aGroup.getName() + "'"); - _user = aUser; - _group = aGroup; + this(aCause, "for user '" + aUser.getName() + "' and group '" + + aGroup.getName() + "'"); + user = aUser; + group = aGroup; } /** - * Gets the cause of the problem. - * @return Cause. + * Gets the cause of the problem. + * + * @return Cause. */ public Reason getReason() { - return _cause; + return cause; } - + /** - * Gets the user for which the problem occurred. - * @return User or null if not applicable. + * Gets the user for which the problem occurred. + * + * @return User or null if not applicable. */ public User getUser() { - return _user; + return user; } - + /** - * Gets the group for which the problem occured. - * @return Group or null if not applicable. + * Gets the group for which the problem occured. + * + * @return Group or null if not applicable. */ public Group getGroup() { - return _group; - } + return group; + } + + /** + * Possible causes for the exception. + * + */ + public enum Reason { + UNKNOWN_USER, UNKNOWN_GROUP, DUPLICATE_USER, DUPLICATE_GROUP, USER_ALREADY_IN_GROUP, USER_NOT_IN_GROUP, TRIVIAL_RENAME, INVALID_PASSWORD, GROUP_STILL_OCCUPIED, USER_MUST_BE_IN_A_GROUP, INVALID_USERNAME, INVALID_GROUPNAME; + } } diff --git a/security/impl/src/main/java/org/wamblee/usermgt/UserSet.java b/security/impl/src/main/java/org/wamblee/usermgt/UserSet.java new file mode 100644 index 00000000..c8912a83 --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/usermgt/UserSet.java @@ -0,0 +1,114 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import java.util.Set; + +/** + * Represents a set of users. Typical implementations would be an implementation + * based on a static configuration file or an implementation backed by a + * database. + * + * @author Erik Brakkee + */ +public interface UserSet { + /** + * Creates a user. + * + * @param aUsername + * User name. + * @param aPassword + * Password. + * @param aGroup + * Group. + * + * @return New user. + * + * @throws UserMgtException + * In case the user cannot be created. + */ + User createUser(String aUsername, String aPassword, Group aGroup) + throws UserMgtException; + + /** + * Must be called whenever a user object has been modified to notify the + * user set. + * + * @param aUser + * Modified user. + */ + void userModified(User aUser); + + /** + * Finds user. + * + * @param aName + * Username. + * + * @return User or null if not found. + */ + User find(String aName); + + /** + * Checks if a user exists. + * + * @param aUser + * User. + * + * @return True iff the user exists. + */ + boolean contains(User aUser); + + /** + * Adds a user. If the user already exists, the user details are updated + * with that of the specified user object. + * + * @param aUser + * User to add. + * + */ + boolean add(User aUser); + + /** + * Removes a user. If the user does not exist, nothing happens. + * + * @param aUser + * + */ + boolean remove(User aUser); + + /** + * Lists the current users. + * + * @return Users. + */ + Set list(); + + /** + * Lists the users belonging to a particular group. + * + * @param aGroup + * Group. + * @return Groups. + */ + Set list(Group aGroup); + + /** + * + * @return The number of users. + */ + int size(); +} diff --git a/security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaGroupSet.java b/security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaGroupSet.java new file mode 100644 index 00000000..2150b43a --- /dev/null +++ b/security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaGroupSet.java @@ -0,0 +1,111 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt.jpa; + +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; + +import org.wamblee.persistence.JpaMergeSupport; +import org.wamblee.usermgt.Group; +import org.wamblee.usermgt.GroupSet; + +/** + * Group set backed by the database. + * + * @author Erik Brakkee + */ +public class JpaGroupSet implements GroupSet { + + private EntityManager em; + + public JpaGroupSet(EntityManager aEm) { + em = aEm; + } + + @Override + public boolean add(Group aGroup) { + assert aGroup.getPrimaryKey() == null; + if (contains(aGroup)) { + return false; + } + em.persist(aGroup); + return true; + } + + @Override + public boolean contains(Group aGroup) { + return find(aGroup.getName()) != null; + } + + @Override + public Group find(String aName) { + TypedQuery query = em.createNamedQuery(Group.QUERY_FIND_BY_NAME, + Group.class); + query.setParameter(Group.NAME_PARAM, aName); + List groups = query.getResultList(); + if (groups.size() > 1) { + throw new RuntimeException( + "More than one group with the same name '" + aName + "'"); + } + + if (groups.size() == 0) { + return null; + } + return groups.get(0); + } + + @Override + public void groupModified(Group aGroup) { + assert aGroup.getPrimaryKey() != null; + Group merged = em.merge(aGroup); + // Need to flush so that version of the merged instance is updated so we + // can use + // the updated version in the original group passed in. That allows the + // same + // group object to continue to be used as a detached object. + em.flush(); + JpaMergeSupport.merge(merged, aGroup); + } + + @Override + public Set list() { + List groups = em.createNamedQuery(Group.QUERY_ALL_GROUPS, + Group.class).getResultList(); + Set res = new TreeSet(groups); + return res; + } + + @Override + public boolean remove(Group aGroup) { + Group group = find(aGroup.getName()); + if (group == null) { + return false; + } + em.remove(group); + return true; + } + + @Override + public int size() { + Long res = (Long) em.createNamedQuery(Group.QUERY_COUNT_GROUPS) + .getSingleResult(); + return res.intValue(); + } +} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/HibernateUserSet.java b/security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaUserSet.java similarity index 53% rename from security/src/main/java/org/wamblee/usermgt/hibernate/HibernateUserSet.java rename to security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaUserSet.java index 8bc1db58..045eda00 100644 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/HibernateUserSet.java +++ b/security/impl/src/main/java/org/wamblee/usermgt/jpa/JpaUserSet.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,17 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -package org.wamblee.usermgt.hibernate; +package org.wamblee.usermgt.jpa; import java.util.List; import java.util.Set; import java.util.TreeSet; -import org.hibernate.SessionFactory; -import org.springframework.orm.hibernate3.HibernateTemplate; +import javax.persistence.EntityManager; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; + import org.wamblee.cache.Cache; -import org.wamblee.persistence.hibernate.HibernateSupport; +import org.wamblee.persistence.JpaMergeSupport; import org.wamblee.security.encryption.MessageDigester; import org.wamblee.usermgt.AbstractUserSet; import org.wamblee.usermgt.Group; @@ -32,56 +33,33 @@ import org.wamblee.usermgt.User; /** * User set backed by the database. - * + * * @author Erik Brakkee */ -public class HibernateUserSet extends AbstractUserSet { - - private static final String QUERY_FIND_BY_NAME = "findUserByName"; - - private static final String QUERY_FIND_BY_GROUP_NAME = "findUserByGroupName"; - - private static final String PARAM_NAME = "name"; - - private static final String QUERY_COUNT_USERS = "countUsers"; +public class JpaUserSet extends AbstractUserSet { /** - * Cache of users. Every user in the cache has its password validator and encoder set. - */ - private Cache _cache; - - /** - * Spring hibernate support. + * Cache of users. Every user in the cache has its password validator and + * encoder set. */ - private HibernateSupport _hibernateSupport; + private Cache cache; + + private EntityManager entityManager; /** * Constructs a user set backed by the database. - * @param aCache User cache to use. + * + * @param aCache + * User cache to use. */ - public HibernateUserSet(Cache aCache, - NameValidator aPasswordValidator, MessageDigester aPasswordEncoder) { + public JpaUserSet(Cache aCache, + NameValidator aPasswordValidator, MessageDigester aPasswordEncoder, + EntityManager aEntityManager) { super(aPasswordValidator, aPasswordEncoder); - _cache = aCache; - _hibernateSupport = new HibernateSupport(); + cache = aCache; + entityManager = aEntityManager; } - - /** - * Sets the session factory. - * @param aFactory Session factory. - */ - public void setSessionFactory(SessionFactory aFactory) { - _hibernateSupport.setSessionFactory(aFactory); - } - - /** - * Gets the hibernate template. - * @return Hibernate template. - */ - private HibernateTemplate getHibernateTemplate() { - return _hibernateSupport.getHibernateTemplate(); - } - + /* * (non-Javadoc) * @@ -89,10 +67,13 @@ public class HibernateUserSet extends AbstractUserSet { */ public void userModified(User aUser) { assert aUser.getPrimaryKey() != null; - _hibernateSupport.merge(aUser); - _cache.remove(aUser.getName()); + User merged = entityManager.merge(aUser); + // Need to flush the entity manager to make sure the version is updated. + entityManager.flush(); + JpaMergeSupport.merge(merged, aUser); + cache.remove(aUser.getName()); setPasswordInfo(aUser); - _cache.put(aUser.getName(), new User(aUser)); + cache.put(aUser.getName(), new User(aUser)); } /* @@ -101,23 +82,24 @@ public class HibernateUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#find(java.lang.String) */ public User find(String aName) { - User user = _cache.get(aName); + User user = cache.get(aName); + if (user != null) { return user; } - List result = getHibernateTemplate().findByNamedQueryAndNamedParam( - QUERY_FIND_BY_NAME, PARAM_NAME, aName); - if (result.size() > 1) { - throw new RuntimeException( - "Implementation problem, more than one user with the same name!"); - } - if (result.size() == 0) { + + TypedQuery query = entityManager.createNamedQuery( + User.QUERY_FIND_BY_NAME, User.class); + query.setParameter(User.NAME_PARAM, aName); + try { + user = query.getSingleResult(); + user = new User(user); + setPasswordInfo(user); + cache.put(aName, user); + return user; + } catch (NoResultException e) { return null; } - user = (User) result.get(0); - setPasswordInfo(user); - _cache.put(aName, user); - return new User(user); } /* @@ -136,12 +118,15 @@ public class HibernateUserSet extends AbstractUserSet { */ public boolean add(User aUser) { assert aUser.getPrimaryKey() == null; + if (contains(aUser)) { return false; } - getHibernateTemplate().saveOrUpdate(aUser); + + entityManager.persist(aUser); setPasswordInfo(aUser); - _cache.put(aUser.getName(), aUser); + cache.put(aUser.getName(), aUser); + return true; } @@ -151,15 +136,14 @@ public class HibernateUserSet extends AbstractUserSet { * @see org.wamblee.usermgt.UserSet#remove(org.wamblee.usermgt.User) */ public boolean remove(User aUser) { - assert aUser.getPrimaryKey() != null; if (!contains(aUser)) { return false; } - User user = (User) getHibernateTemplate().merge(aUser); - getHibernateTemplate().delete(user); - aUser.setPersistedVersion(-1); - aUser.setPrimaryKey(null); - _cache.remove(aUser.getName()); + + User user = entityManager.merge(aUser); + entityManager.remove(user); + cache.remove(aUser.getName()); + return true; } @@ -170,11 +154,14 @@ public class HibernateUserSet extends AbstractUserSet { */ public Set list() { Set users = new TreeSet(); - List list = getHibernateTemplate().loadAll(User.class); + List list = entityManager.createNamedQuery(User.QUERY_ALL_USERS, + User.class).getResultList(); + for (User user : list) { setPasswordInfo(user); users.add(new User(user)); } + return users; } @@ -185,20 +172,27 @@ public class HibernateUserSet extends AbstractUserSet { */ public Set list(Group aGroup) { Set users = new TreeSet(); - List list = getHibernateTemplate().findByNamedQueryAndNamedParam( - QUERY_FIND_BY_GROUP_NAME, PARAM_NAME, aGroup.getName()); + TypedQuery query = entityManager.createNamedQuery( + User.QUERY_FIND_BY_GROUP_NAME, User.class); + query.setParameter(User.NAME_PARAM, aGroup.getName()); + + List list = query.getResultList(); + for (User user : list) { setPasswordInfo(user); users.add(new User(user)); } + return users; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.usermgt.UserSet#size() */ public int size() { - Long result = (Long)getHibernateTemplate().findByNamedQuery(QUERY_COUNT_USERS).get(0); - return result.intValue(); + Long result = entityManager.createNamedQuery(User.QUERY_COUNT_USERS, Long.class).getSingleResult(); + return result.intValue(); } } diff --git a/security/src/main/resources/hbm/AuthorizationRule.hbm.xml b/security/impl/src/main/resources/hbm/AuthorizationRule.hbm.xml similarity index 83% rename from security/src/main/resources/hbm/AuthorizationRule.hbm.xml rename to security/impl/src/main/resources/hbm/AuthorizationRule.hbm.xml index 33f5d942..006c0a41 100644 --- a/security/src/main/resources/hbm/AuthorizationRule.hbm.xml +++ b/security/impl/src/main/resources/hbm/AuthorizationRule.hbm.xml @@ -5,7 +5,7 @@ - @@ -21,17 +21,17 @@ diff --git a/security/src/main/resources/hbm/AuthorizationService.hbm.xml b/security/impl/src/main/resources/hbm/AuthorizationService.hbm.xml similarity index 82% rename from security/src/main/resources/hbm/AuthorizationService.hbm.xml rename to security/impl/src/main/resources/hbm/AuthorizationService.hbm.xml index f8e036ca..4396b6b7 100644 --- a/security/src/main/resources/hbm/AuthorizationService.hbm.xml +++ b/security/impl/src/main/resources/hbm/AuthorizationService.hbm.xml @@ -5,7 +5,7 @@ - @@ -21,7 +21,7 @@ - @@ -30,7 +30,7 @@ select service - from org.wamblee.security.authorization.AuthorizationService service + from org.wamblee.security.authorization.AbstractAuthorizationService service where service.name = :name diff --git a/security/src/main/resources/hbm/Group.hbm.xml b/security/impl/src/main/resources/hbm/Group.hbm.xml similarity index 100% rename from security/src/main/resources/hbm/Group.hbm.xml rename to security/impl/src/main/resources/hbm/Group.hbm.xml diff --git a/security/src/main/resources/hbm/OperationCondition.hbm.xml b/security/impl/src/main/resources/hbm/OperationCondition.hbm.xml similarity index 85% rename from security/src/main/resources/hbm/OperationCondition.hbm.xml rename to security/impl/src/main/resources/hbm/OperationCondition.hbm.xml index 5ab4b0d8..d5dcbc89 100644 --- a/security/src/main/resources/hbm/OperationCondition.hbm.xml +++ b/security/impl/src/main/resources/hbm/OperationCondition.hbm.xml @@ -5,7 +5,7 @@ - diff --git a/security/src/main/resources/hbm/OperationCondition.hbm.xmlxx b/security/impl/src/main/resources/hbm/OperationCondition.hbm.xmlxx similarity index 86% rename from security/src/main/resources/hbm/OperationCondition.hbm.xmlxx rename to security/impl/src/main/resources/hbm/OperationCondition.hbm.xmlxx index 250030e0..5fd0562b 100644 --- a/security/src/main/resources/hbm/OperationCondition.hbm.xmlxx +++ b/security/impl/src/main/resources/hbm/OperationCondition.hbm.xmlxx @@ -5,7 +5,7 @@ - diff --git a/security/src/main/resources/hbm/PathCondition.hbm.xml b/security/impl/src/main/resources/hbm/PathCondition.hbm.xml similarity index 89% rename from security/src/main/resources/hbm/PathCondition.hbm.xml rename to security/impl/src/main/resources/hbm/PathCondition.hbm.xml index c43c0a83..c401372b 100644 --- a/security/src/main/resources/hbm/PathCondition.hbm.xml +++ b/security/impl/src/main/resources/hbm/PathCondition.hbm.xml @@ -5,7 +5,7 @@ - diff --git a/security/src/main/resources/hbm/TestAuthorizationRule.hbm.xml b/security/impl/src/main/resources/hbm/TestAuthorizationRule.hbm.xml similarity index 100% rename from security/src/main/resources/hbm/TestAuthorizationRule.hbm.xml rename to security/impl/src/main/resources/hbm/TestAuthorizationRule.hbm.xml diff --git a/security/src/main/resources/hbm/User.hbm.xml b/security/impl/src/main/resources/hbm/User.hbm.xml similarity index 98% rename from security/src/main/resources/hbm/User.hbm.xml rename to security/impl/src/main/resources/hbm/User.hbm.xml index eefbfa22..3bd4ef57 100644 --- a/security/src/main/resources/hbm/User.hbm.xml +++ b/security/impl/src/main/resources/hbm/User.hbm.xml @@ -4,6 +4,7 @@ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> + diff --git a/security/src/main/resources/hbm/UserCondition.hbm.xml b/security/impl/src/main/resources/hbm/UserCondition.hbm.xml similarity index 88% rename from security/src/main/resources/hbm/UserCondition.hbm.xml rename to security/impl/src/main/resources/hbm/UserCondition.hbm.xml index fc83423d..8079cf56 100644 --- a/security/src/main/resources/hbm/UserCondition.hbm.xml +++ b/security/impl/src/main/resources/hbm/UserCondition.hbm.xml @@ -5,7 +5,7 @@ - diff --git a/security/src/main/resources/hbm/ehcache.xml b/security/impl/src/main/resources/hbm/ehcache.xml similarity index 100% rename from security/src/main/resources/hbm/ehcache.xml rename to security/impl/src/main/resources/hbm/ehcache.xml diff --git a/security/src/main/resources/hbm/hibernate.properties b/security/impl/src/main/resources/hbm/hibernate.properties similarity index 100% rename from security/src/main/resources/hbm/hibernate.properties rename to security/impl/src/main/resources/hbm/hibernate.properties diff --git a/security/src/main/resources/properties/org.wamblee.security.ehcache.xml b/security/impl/src/main/resources/properties/org.wamblee.security.ehcache.xml similarity index 100% rename from security/src/main/resources/properties/org.wamblee.security.ehcache.xml rename to security/impl/src/main/resources/properties/org.wamblee.security.ehcache.xml diff --git a/security/src/main/resources/spring/org.wamblee.security.authorization.xml b/security/impl/src/main/resources/spring/org.wamblee.security.authorization.xml similarity index 94% rename from security/src/main/resources/spring/org.wamblee.security.authorization.xml rename to security/impl/src/main/resources/spring/org.wamblee.security.authorization.xml index 29f2ff16..b0a79c71 100644 --- a/security/src/main/resources/spring/org.wamblee.security.authorization.xml +++ b/security/impl/src/main/resources/spring/org.wamblee.security.authorization.xml @@ -16,7 +16,7 @@ - DEFAULT diff --git a/security/src/main/resources/spring/org.wamblee.security.usermgt-repositories.xml b/security/impl/src/main/resources/spring/org.wamblee.security.usermgt-repositories.xml similarity index 100% rename from security/src/main/resources/spring/org.wamblee.security.usermgt-repositories.xml rename to security/impl/src/main/resources/spring/org.wamblee.security.usermgt-repositories.xml diff --git a/security/src/main/resources/spring/org.wamblee.security.usermgt.xml b/security/impl/src/main/resources/spring/org.wamblee.security.usermgt.xml similarity index 100% rename from security/src/main/resources/spring/org.wamblee.security.usermgt.xml rename to security/impl/src/main/resources/spring/org.wamblee.security.usermgt.xml diff --git a/security/impl/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java b/security/impl/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java new file mode 100644 index 00000000..8be34f9d --- /dev/null +++ b/security/impl/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java @@ -0,0 +1,191 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import junit.framework.TestCase; +import static org.wamblee.security.authorization.AuthorizationResult.DENIED; +import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; + +import org.wamblee.usermgt.UserAccessor; + +/** + * Tests the authorization service. + * + * @author Erik Brakkee + */ +public class AuthorizationServiceTest extends TestCase { + private AbstractAuthorizationRule rule1; + + private AbstractAuthorizationRule rule2; + + private AbstractAuthorizationRule rule3; + + private AuthorizationService service; + + protected AuthorizationService getService() { + return service; + } + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + + rule1 = createRule(GRANTED, "users", "/oni/", AllOperation.class); + rule2 = createRule(DENIED, "users", "/abc/", ReadOperation.class); + rule3 = createRule(GRANTED, "users", "/abc/", AllOperation.class); + + service = createService(); + service.appendRule(rule1); + service.appendRule(rule2); + service.appendRule(rule3); + } + + protected void resetTestRules() { + ((TestAuthorizationRule) rule1).reset(); + ((TestAuthorizationRule) rule2).reset(); + ((TestAuthorizationRule) rule3).reset(); + } + + protected UserAccessor createUserAccessor() { + return new TestUserAccessor(); + } + + /** + * Creates an authorization service with some rules for testing. . + * + * @return Authorization service. + */ + protected AuthorizationService createService() { + DefaultAuthorizationService service = new DefaultAuthorizationService(); + service.setUserAccessor(createUserAccessor()); + + return service; + } + + protected AbstractAuthorizationRule createRule(AuthorizationResult aResult, + String aGroup, String aPath, Class aOperation) { + return new TestAuthorizationRule(aResult, aGroup, aPath, aOperation); + } + + protected void checkMatchCount(int aCount, AuthorizationRule aRule) { + TestAuthorizationRule testRule = (TestAuthorizationRule) aRule; + assertEquals(aCount, testRule.getMatchCount()); + testRule.reset(); + } + + protected Object createResource(String aPath) { + return new TestResource(aPath); + } + + protected void checkRuleCount(int aCount) { + // Empty + } + + /** + * Several checks to verify the outcome of matching against the first rule. + */ + public void testFirstRuleGrants() { + assertTrue(service.isAllowed(createResource("/oni/xyz.jpg"), + new ReadOperation())); + checkMatchCount(1, service.getRules()[0]); + assertTrue(service.isAllowed(createResource("/oni/xyz.jpg"), + new WriteOperation())); + checkMatchCount(1, service.getRules()[0]); + assertTrue(service.isAllowed(createResource("/oni/xyz.jpg"), + new DeleteOperation())); + checkMatchCount(1, service.getRules()[0]); + assertTrue(service.isAllowed(createResource("/oni/xyz.jpg"), + new CreateOperation())); + checkMatchCount(1, service.getRules()[0]); + checkMatchCount(0, service.getRules()[1]); + checkMatchCount(0, service.getRules()[2]); + } + + /** + * Verify that a match with the second rule leads to a denial of + * authorization. + */ + public void testSecondRuleDenies() { + assertFalse(service.isAllowed(createResource("/abc/xyz.jpg"), + new ReadOperation())); + checkMatchCount(0, service.getRules()[0]); + checkMatchCount(1, service.getRules()[1]); + checkMatchCount(0, service.getRules()[2]); + } + + /** + * Verifies that the third rule is used when appropriate and that it grants + * access. + */ + public void testThirdRuleGrants() { + assertTrue(service.isAllowed(createResource("/abc/xyz.jpg"), + new WriteOperation())); + checkMatchCount(0, service.getRules()[0]); + checkMatchCount(0, service.getRules()[1]); + checkMatchCount(1, service.getRules()[2]); + } + + /** + * Removes a rule and checks it is removed. + */ + public void testRemoveRule() { + checkRuleCount(3); + assertTrue(service.isAllowed(createResource("/abc/xyz.jpg"), + new WriteOperation())); + service.removeRule(2); + assertFalse(service.isAllowed(createResource("/abc/xyz.jpg"), + new WriteOperation())); + checkRuleCount(2); + } + + /** + * Inserts a rule and checks it is inserted. + */ + public void testInsertRule() { + checkRuleCount(3); + assertFalse(service.isAllowed(createResource("/janse/xyz.jpg"), + new WriteOperation())); + service.appendRule(createRule(GRANTED, "users", "/janse/", + WriteOperation.class)); + assertTrue(service.isAllowed(createResource("/janse/xyz.jpg"), + new WriteOperation())); + checkRuleCount(4); + } + + /** + * Gets the rules. Verifies that all rules are obtained. + */ + public void testGetRules() { + AuthorizationRule[] rules = service.getRules(); + assertEquals(3, rules.length); + } + + /** + * Verifies that when no rules match, access is denied. + */ + public void testNoRulesSupportResource() { + assertFalse(service.isAllowed(createResource("/xyxyxyxy"), + new ReadOperation())); + checkMatchCount(0, service.getRules()[0]); + checkMatchCount(0, service.getRules()[1]); + checkMatchCount(0, service.getRules()[2]); + } +} diff --git a/security/impl/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java b/security/impl/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java new file mode 100644 index 00000000..e09f7fa1 --- /dev/null +++ b/security/impl/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java @@ -0,0 +1,77 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import junit.framework.TestCase; + +/** + * Test of the operation registry. + * + * @author Erik Brakkee + */ +public class DefaultOperationRegistryTest extends TestCase { + private OperationRegistry registry; + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + registry = new DefaultOperationRegistry(new Operation[] { + new AllOperation(), new ReadOperation(), new WriteOperation(), + new DeleteOperation(), new CreateOperation() }); + } + + /** + * Tests encoding and decoding of no operations. + */ + public void testEncodeDecodeNooperations() { + assertEquals("", registry.encode(new Operation[0])); + assertEquals(0, registry.decode(Object.class, "").length); + } + + /** + * Verifies that encoding of operations into a string works. + */ + public void testEncode() { + assertEquals("read,write", registry.encode(new Operation[] { + new ReadOperation(), new WriteOperation() })); + } + + /** + * Verifies that decoding of operation from a string works. + */ + public void testDecode() { + Operation[] operations = registry.decode(Object.class, "read,write"); + assertTrue(operations[0] instanceof ReadOperation); + assertTrue(operations[1] instanceof WriteOperation); + } + + /** + * Verifies that an IllegalArgumentException occurs when attempting to + * decode an operation that is not known. + */ + public void testDecodeUnknownOperation() { + try { + registry.decode(Object.class, "bla"); + fail(); + } catch (IllegalArgumentException e) { + // ok + } + } +} diff --git a/security/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java b/security/impl/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java similarity index 65% rename from security/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java rename to security/impl/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java index cf83b289..5876c46f 100644 --- a/security/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java +++ b/security/impl/src/test/java/org/wamblee/security/authorization/RegexpPathConditionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; import junit.framework.TestCase; /** - * Test for regular expression matching. - * + * Test for regular expression matching. + * * @author Erik Brakkee */ public class RegexpPathConditionTest extends TestCase { - /** - * Various tests. - * + * Various tests. */ - public void testMatch() { - PathCondition cond = new RegexpPathCondition("abc"); - assertTrue(cond.matches("abc")); - assertFalse(cond.matches("xabcx")); - cond = new RegexpPathCondition("/[a-z]*/.*"); - assertTrue(cond.matches("/hallo/xyz")); + public void testMatch() { + PathCondition cond = new RegexpPathCondition("abc"); + assertTrue(cond.matches("abc")); + assertFalse(cond.matches("xabcx")); + cond = new RegexpPathCondition("/[a-z]*/.*"); + assertTrue(cond.matches("/hallo/xyz")); } } diff --git a/security/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java b/security/impl/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java similarity index 89% rename from security/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java rename to security/impl/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java index 2e64098d..49666ce0 100644 --- a/security/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java +++ b/security/impl/src/test/java/org/wamblee/security/authorization/StartsWithPathConditionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; import junit.framework.TestCase; /** - * Tests for StartsWithPathCondition. - * + * Tests for StartsWithPathCondition. + * * @author Erik Brakkee */ public class StartsWithPathConditionTest extends TestCase { - /** - * Various tests. + * Various tests. */ public void testMatches() { PathCondition cond = new StartsWithPathCondition("/hallo"); diff --git a/security/impl/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java b/security/impl/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java new file mode 100644 index 00000000..26cb4738 --- /dev/null +++ b/security/impl/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java @@ -0,0 +1,100 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization; + +import static org.wamblee.security.authorization.AuthorizationResult.DENIED; +import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; +import javax.persistence.Transient; + +import org.wamblee.usermgt.User; + +/** + * Test authorization rule that also counts the number of times the rule + * matches. + * + * @author Erik Brakkee + */ +@Entity +@DiscriminatorValue("TEST") +public class TestAuthorizationRule extends UrlAuthorizationRule { + /** + * Counts the number of matches. + */ + @Transient + private int matches = 0; + + /** + * Creates a new TestAuthorizationRule object. + * + */ + public TestAuthorizationRule(AuthorizationResult aResult, String aGroup, + String aPath, Class aOperation) { + super(aResult, new GroupUserCondition(aGroup), + new StartsWithPathCondition(aPath), TestResource.class, + new IsaOperationCondition(aOperation)); + } + + /** + * Creates a new TestAuthorizationRule object. + */ + protected TestAuthorizationRule() { + super(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.UrlAuthorizationRule#getPath(java. + * lang.Object) + */ + @Override + protected String getResourcePath(Object aResource) { + return ((TestResource) aResource).getPath(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.UrlAuthorizationRule#isAllowed(java + * .lang.Object, org.wamblee.security.authorization.Operation, + * org.wamblee.usermgt.UserAccessor) + */ + @Override + public AuthorizationResult isAllowed(Object aResource, + Operation aOperation, User aUser) { + AuthorizationResult result = super.isAllowed(aResource, aOperation, + aUser); + + if (result.equals(GRANTED) || result.equals(DENIED)) { + matches++; + } + + return result; + } + + public int getMatchCount() { + return matches; + } + + public void reset() { + matches = 0; + } +} diff --git a/security/src/test/java/org/wamblee/security/authorization/TestResource.java b/security/impl/src/test/java/org/wamblee/security/authorization/TestResource.java similarity index 69% rename from security/src/test/java/org/wamblee/security/authorization/TestResource.java rename to security/impl/src/test/java/org/wamblee/security/authorization/TestResource.java index a0edd898..cb600d73 100644 --- a/security/src/test/java/org/wamblee/security/authorization/TestResource.java +++ b/security/impl/src/test/java/org/wamblee/security/authorization/TestResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; /** - * A test resource for authorization. - * + * A test resource for authorization. + * * @author Erik Brakkee */ public class TestResource { + private String path; - private String _path; - - public TestResource(String aPath) { - _path = aPath; + /** + * Creates a new TestResource object. + * + */ + public TestResource(String aPath) { + path = aPath; } - - public String getPath() { - return _path; + + public String getPath() { + return path; } } diff --git a/security/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java b/security/impl/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java similarity index 71% rename from security/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java rename to security/impl/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java index 02e09020..c4cadcc8 100644 --- a/security/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java +++ b/security/impl/src/test/java/org/wamblee/security/authorization/TestUserAccessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,13 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.security.authorization; import junit.framework.TestCase; import org.wamblee.security.encryption.Md5HexMessageDigester; + import org.wamblee.usermgt.Group; import org.wamblee.usermgt.InMemoryGroupSet; import org.wamblee.usermgt.InMemoryUserSet; @@ -31,15 +31,15 @@ import org.wamblee.usermgt.UserMgtException; import org.wamblee.usermgt.UserMgtException.Reason; /** - * User access that always returns a user that belongs to - * a fixed group. - * + * User access that always returns a user that belongs to a fixed group. + * * @author Erik Brakkee */ public class TestUserAccessor implements UserAccessor { - - private static final String USER = "erik"; + private static final String USER = "erik"; + private static final String PASSWORD = "abc123"; + private static final String GROUP = "users"; /* @@ -49,18 +49,22 @@ public class TestUserAccessor implements UserAccessor { */ public User getCurrentUser() { UserAdministration admin = new UserAdministrationImpl( - new InMemoryUserSet( new RegexpNameValidator(RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, "Password must contain at least 6 characters"), - new Md5HexMessageDigester()), new InMemoryGroupSet(), - new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, Reason.INVALID_USERNAME, "Invalid user"), - new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, Reason.INVALID_GROUPNAME, "Invalid group") - ); + new InMemoryUserSet(new RegexpNameValidator( + RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, + "Password must contain at least 6 characters"), + new Md5HexMessageDigester()), new InMemoryGroupSet(), + new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, + Reason.INVALID_USERNAME, "Invalid user"), + new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, + Reason.INVALID_GROUPNAME, "Invalid group")); + try { Group group = admin.createGroup(GROUP); + return admin.createUser(USER, PASSWORD, group); } catch (UserMgtException e) { TestCase.fail(e.getMessage()); throw new RuntimeException(e); } } - } diff --git a/security/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java b/security/impl/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java similarity index 62% rename from security/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java rename to security/impl/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java index 4e66ed86..b2353b89 100644 --- a/security/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java +++ b/security/impl/src/test/java/org/wamblee/security/authorization/UrlAuthorizationRuleTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,79 +13,84 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.authorization; +import junit.framework.TestCase; import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; import static org.wamblee.security.authorization.AuthorizationResult.UNDECIDED; import static org.wamblee.security.authorization.AuthorizationResult.UNSUPPORTED_RESOURCE; -import junit.framework.TestCase; import org.wamblee.usermgt.User; - /** - * Tests for the {@link org.wamblee.security.authorization.UrlAuthorizationRule}. - * + * Tests for the {@link org.wamblee.security.authorization.UrlAuthorizationRule} + * . + * * @author Erik Brakkee */ public class UrlAuthorizationRuleTest extends TestCase { - /** - * Constructs the rule with a result of UNDECIDED. Verifies that an IllegalArgumentException - * is thrown. - * + * Constructs the rule with a result of UNDECIDED. Verifies that an + * IllegalArgumentException is thrown. */ - public void testConstructWithUndecidedResult() { - try { - new TestAuthorizationRule(UNDECIDED, "users", "/path", ReadOperation.class); + public void testConstructWithUndecidedResult() { + try { + new TestAuthorizationRule(UNDECIDED, "users", "/path", + ReadOperation.class); fail(); - } catch (IllegalArgumentException e) { - // ok + } catch (IllegalArgumentException e) { + // ok } } - + /** - * Constructs the rule with a result of UNSUPPORTED_RESOURCE. Verifies that an IllegalArgumentException - * is thrown. - * + * Constructs the rule with a result of UNSUPPORTED_RESOURCE. Verifies that + * an IllegalArgumentException is thrown. */ - public void testConstructWithUnsupportedResult() { - try { - new TestAuthorizationRule(UNSUPPORTED_RESOURCE, "users", "/path", ReadOperation.class); + public void testConstructWithUnsupportedResult() { + try { + new TestAuthorizationRule(UNSUPPORTED_RESOURCE, "users", "/path", + ReadOperation.class); fail(); - } catch (IllegalArgumentException e) { - // ok + } catch (IllegalArgumentException e) { + // ok } } - + /** - * Constructs the authorization rule and applies it to an unsupported object type. - * Verifies that the result is UNSUPPORTED_RESOURCE. - * + * Constructs the authorization rule and applies it to an unsupported object + * type. Verifies that the result is UNSUPPORTED_RESOURCE. */ - public void testUnsupportedObject() { - AuthorizationRule rule = new TestAuthorizationRule(GRANTED, "users", "/path", ReadOperation.class); - assertEquals(UNSUPPORTED_RESOURCE, rule.isAllowed("hello", new ReadOperation(), new TestUserAccessor().getCurrentUser())); + public void testUnsupportedObject() { + AuthorizationRule rule = new TestAuthorizationRule(GRANTED, "users", + "/path", ReadOperation.class); + assertEquals(UNSUPPORTED_RESOURCE, rule.isAllowed("hello", + new ReadOperation(), new TestUserAccessor().getCurrentUser())); } - - public void testMatchingScenarios() { - AuthorizationRule rule = new TestAuthorizationRule(GRANTED, "users", "/path/", ReadOperation.class); + + public void testMatchingScenarios() { + AuthorizationRule rule = new TestAuthorizationRule(GRANTED, "users", + "/path/", ReadOperation.class); User user = new TestUserAccessor().getCurrentUser(); - + // everything matches - assertEquals(GRANTED, rule.isAllowed(new TestResource("/path/a"), new ReadOperation(), user)); - assertEquals(GRANTED, rule.isAllowed(new TestResource("/path/"), new ReadOperation(), user)); - - // path does not match. - assertEquals(UNDECIDED, rule.isAllowed(new TestResource("/path"), new ReadOperation(), user)); - - // operation does not match. - assertEquals(UNDECIDED, rule.isAllowed(new TestResource("/path/"), new WriteOperation(), user)); - - // group does not match. - AuthorizationRule rule2 = new TestAuthorizationRule(GRANTED, "users2", "/path/", ReadOperation.class); - assertEquals(UNDECIDED, rule2.isAllowed(new TestResource("/path/a"), new ReadOperation(), user)); + assertEquals(GRANTED, rule.isAllowed(new TestResource("/path/a"), + new ReadOperation(), user)); + assertEquals(GRANTED, rule.isAllowed(new TestResource("/path/"), + new ReadOperation(), user)); + + // path does not match. + assertEquals(UNDECIDED, rule.isAllowed(new TestResource("/path"), + new ReadOperation(), user)); + + // operation does not match. + assertEquals(UNDECIDED, rule.isAllowed(new TestResource("/path/"), + new WriteOperation(), user)); + + // group does not match. + AuthorizationRule rule2 = new TestAuthorizationRule(GRANTED, "users2", + "/path/", ReadOperation.class); + assertEquals(UNDECIDED, rule2.isAllowed(new TestResource("/path/a"), + new ReadOperation(), user)); } - } diff --git a/security/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java b/security/impl/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java similarity index 74% rename from security/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java rename to security/impl/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java index 6760efe9..7cf2593b 100644 --- a/security/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java +++ b/security/impl/src/test/java/org/wamblee/security/encryption/MessageDigesterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,19 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.security.encryption; import junit.framework.TestCase; /** - * Tests for the message digester. - * + * Tests for the message digester. + * * @author Erik Brakkee */ public class MessageDigesterTest extends TestCase { - - public void testMd5HexEncoding() { - assertEquals("e99a18c428cb38d5f260853678922e03", new Md5HexMessageDigester().hash("abc123")); + public void testMd5HexEncoding() { + assertEquals("e99a18c428cb38d5f260853678922e03", + new Md5HexMessageDigester().hash("abc123")); } } diff --git a/security/impl/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java b/security/impl/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java new file mode 100644 index 00000000..9a52241f --- /dev/null +++ b/security/impl/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java @@ -0,0 +1,207 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import java.util.Set; + +import junit.framework.TestCase; + +/** + * Tests the inmemory group set. Intended to be subclassed for other + * implementations of group set. + */ +public class InMemoryGroupSetTest extends TestCase { + private GroupSet groups; + + /** + * This method must be overriden in subclasses. + * + * @return New group set object. + */ + protected GroupSet createGroupSet() { + return new InMemoryGroupSet(); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.test.SpringTestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + groups = createGroupSet(); + checkGroupCount(0); + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aGroup + * Group to check for existence. + * + */ + protected void checkGroupExists(String aGroup) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aGroup + * Group to check for non-existence. + * + */ + protected void checkGroupNotExists(String aGroup) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aSize + * Expected number of groups. + * + */ + protected void checkGroupCount(int aSize) throws Exception { + assertEquals(aSize, groups.size()); + } + + /** + * Adds a group and verifies that the group is added using find(), list(), + * and contains(). + * + */ + public void testAdd() throws Exception { + Group group = new Group("group1"); + assertTrue(groups.add(group)); + checkGroupExists(group.getName()); + checkGroupCount(1); + + Group group2 = groups.find("group1"); + assertNotNull(group2); + assertEquals(group.getName(), group2.getName()); + + Set set = groups.list(); + assertEquals(1, set.size()); + assertTrue(set.contains(group)); + } + + /** + * Tries to find a non-existing group. Verifies that null is returned. + * + */ + public void testFindUnknownGroup() throws Exception { + Group group1 = new Group("group1"); + Group group2 = new Group("group2"); + groups.add(group1); + groups.add(group2); + checkGroupExists(group1.getName()); + checkGroupExists(group2.getName()); + + assertNull(groups.find("group3")); + checkGroupNotExists("group3"); + } + + /** + * Adds duplicate group. Verifies that the existing group is left untouched. + * + */ + public void testAddDuplicateGroup() throws Exception { + Group group1 = new Group("group1"); + groups.add(group1); + + assertEquals(1, groups.list().size()); + assertTrue(groups.contains(group1)); + group1 = new Group("group1"); + assertFalse(groups.add(group1)); + assertEquals(1, groups.list().size()); + + checkGroupExists(group1.getName()); + checkGroupCount(1); + } + + /** + * Removes a group. Verifies that the group is removed and the return value + * is true. + * + */ + public void testRemoveGroup() throws Exception { + Group group1 = new Group("group1"); + groups.add(group1); + assertTrue(groups.contains(group1)); + checkGroupCount(1); + + assertTrue(groups.remove(group1)); + assertFalse(groups.contains(group1)); + assertNull(groups.find(group1.getName())); + assertEquals(0, groups.list().size()); + checkGroupCount(0); + } + + /** + * Removes a non-existing group. Verifies that no groups are removed an that + * the return value is true. + * + */ + public void testRemoveNonExistingGroup() throws Exception { + Group group1 = new Group("group1"); + groups.add(group1); + checkGroupCount(1); + + Group nonExistingGroup = new Group("group2"); + assertFalse(groups.remove(nonExistingGroup)); + assertTrue(groups.contains(group1)); + assertEquals(1, groups.list().size()); + checkGroupCount(1); + } + + /** + * Adds a number of groups to the set and verifies that list() returns them + * all. + * + */ + public void testList() throws Exception { + Group group1 = new Group("group1"); + Group group2 = new Group("group2"); + Group group3 = new Group("group3"); + assertTrue(groups.add(group1)); + assertTrue(groups.add(group2)); + assertTrue(groups.add(group3)); + + checkGroupExists(group1.getName()); + checkGroupExists(group2.getName()); + checkGroupExists(group3.getName()); + + Set set = groups.list(); + assertTrue(set.contains(group1)); + assertTrue(set.contains(group2)); + assertTrue(set.contains(group3)); + + checkGroupCount(3); + } + + public void testRenameGroupTwice() { + Group group = new Group("x"); + groups.add(group); + groups.groupModified(group); + group.setName("y"); + groups.groupModified(group); + Group g = groups.find("y"); + assertNotNull(g); + groups.groupModified(group); + } +} diff --git a/security/impl/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java b/security/impl/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java new file mode 100644 index 00000000..5c885376 --- /dev/null +++ b/security/impl/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java @@ -0,0 +1,342 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt; + +import junit.framework.TestCase; + +import org.wamblee.security.encryption.Md5HexMessageDigester; + +import org.wamblee.usermgt.UserMgtException.Reason; + +import java.sql.SQLException; + +import java.util.Set; + +/** + * Tests the inmemory user set. Intended to be subclassed for other + * implementations of user set. + */ +public class InMemoryUserSetTest extends TestCase { + protected static final String PASSWORD = "abc123"; + + private UserSet users; + + private GroupSet groups; + + private Group group; + + /** + * This method must be overriden in subclasses. + * + * @return New user set object. + */ + protected UserSet createUserSet() { + return new InMemoryUserSet(new RegexpNameValidator( + RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, + "Password must contain at least 6 characters"), + new Md5HexMessageDigester()); + } + + /** + * This method must be overriden in subclasses. + * + * @return New group set object. + */ + protected GroupSet createGroupSet() { + return new InMemoryGroupSet(); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.test.SpringTestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + users = createUserSet(); + groups = createGroupSet(); + group = new Group("group0"); + groups.add(group); + checkUserCount(0); + } + + protected UserSet getUsers() { + return users; + } + + protected GroupSet getGroups() { + return groups; + } + + protected Group createGroup(String aName) { + return new Group(aName); + } + + protected User createUser(String aName, String aPassword, Group aGroup) + throws UserMgtException { + return UsermgtTestUtils.createUser(aName, aPassword, aGroup); + } + + protected void addUserToGroup(User aUser, Group aGroup) + throws UserMgtException { + aUser.addGroup(aGroup); + } + + protected void removeUserFromGroup(User aUser, Group aGroup) + throws UserMgtException { + aUser.removeGroup(aGroup); + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aUser + * User to check for existence. + * + */ + protected void checkUserExists(String aUser) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aUser + * User to check for non-existence. + * + */ + protected void checkUserNotExists(String aUser) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aSize + * Expected number of users. + * + */ + protected void checkUserCount(int aSize) throws Exception { + assertEquals(aSize, users.size()); + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aUser + * User to check for existence. + * + */ + protected void checkGroupExists(String aUser) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aUser + * User to check for non-existence. + * + */ + protected void checkGroupNotExists(String aUser) throws Exception { + // Empty + } + + /** + * Additional check to be implemented by a subclass. + * + * @param aSize + * Expected number of users. + * + */ + protected void checkGroupCount(int aSize) throws Exception { + // Empty + } + + /** + * Adds a user and verifies that the user is added using find(), list(), and + * contains(). + * + */ + public void testAdd() throws Exception { + User user = createUser("user1", PASSWORD, group); + assertTrue(users.add(user)); + checkUserExists(user.getName()); + checkUserCount(1); + + User user2 = users.find("user1"); + assertNotNull(user2); + assertEquals(user.getName(), user2.getName()); + + Set set = users.list(); + assertEquals(1, set.size()); + assertTrue(set.contains(user)); + } + + /** + * Tries to find a non-existing user. Verifies that null is returned. + * + */ + public void testFindUnknownUser() throws Exception { + User user1 = createUser("user1", PASSWORD, group); + User user2 = createUser("user2", PASSWORD, group); + users.add(user1); + users.add(user2); + checkUserExists(user1.getName()); + checkUserExists(user2.getName()); + + assertNull(users.find("user3")); + checkUserNotExists("user3"); + } + + /** + * Adds duplicate user. Verifies that the existing user is left untouched. + * + */ + public void testAddDuplicateUser() throws Exception { + User user1 = createUser("user1", PASSWORD, group); + users.add(user1); + + assertEquals(1, users.list().size()); + assertTrue(users.contains(user1)); + user1 = createUser("user1", PASSWORD, group); + assertFalse(users.add(user1)); + assertEquals(1, users.list().size()); + + checkUserExists(user1.getName()); + checkUserCount(1); + } + + /** + * Removes a user. Verifies that the user is removed and the return value is + * true. + * + */ + public void testRemoveUser() throws Exception { + User user1 = createUser("user1", PASSWORD, group); + users.add(user1); + assertTrue(users.contains(user1)); + checkUserCount(1); + + assertTrue(users.remove(user1)); + assertFalse(users.contains(user1)); + assertNull(users.find(user1.getName())); + assertEquals(0, users.list().size()); + checkUserCount(0); + } + + /** + * Removes a non-existing user. Verifies that no users are removed an that + * the return value is true. + * + */ + public void testRemoveNonExistingUser() throws Exception, + UserMgtException { + User user1 = createUser("user1", PASSWORD, group); + users.add(user1); + checkUserCount(1); + + User nonExistingUser = createUser("user2", PASSWORD, group); + assertFalse(users.remove(nonExistingUser)); + assertTrue(users.contains(user1)); + assertEquals(1, users.list().size()); + checkUserCount(1); + } + + /** + * Adds a number of users to the set and verifies that list() returns them + * all. + * + */ + public void testList() throws Exception { + User user1 = createUser("user1", PASSWORD, group); + User user2 = createUser("user2", PASSWORD, group); + User user3 = createUser("user3", PASSWORD, group); + assertTrue(users.add(user1)); + assertTrue(users.add(user2)); + assertTrue(users.add(user3)); + + checkUserExists(user1.getName()); + checkUserExists(user2.getName()); + checkUserExists(user3.getName()); + + Set set = users.list(); + assertTrue(set.contains(user1)); + assertTrue(set.contains(user2)); + assertTrue(set.contains(user3)); + + checkUserCount(3); + } + + /** + * Adds several users to different groups and verifies that the correct + * users are returned when looking for users in different groups. + * + * @throws SQLException + */ + public void testListByGroup() throws Exception { + Group group1 = new Group("group1"); + Group group2 = new Group("group2"); + Group group3 = new Group("group3"); + groups.add(group1); + groups.add(group2); + groups.add(group3); + + // user1 user2 user3 + // group1 y + // group2 y y + // group3 y y y + User user1 = createUser("user1", PASSWORD, group1); + user1.addGroup(group2); + user1.addGroup(group3); + + User user2 = createUser("user2", PASSWORD, group2); + user2.addGroup(group3); + + User user3 = createUser("user3", PASSWORD, group3); + users.add(user1); + users.add(user2); + users.add(user3); + + checkUserExists(user1.getName()); + checkUserExists(user2.getName()); + checkUserExists(user3.getName()); + + checkGroupExists(group1.getName()); + checkGroupExists(group2.getName()); + checkGroupExists(group3.getName()); + + checkUserCount(3); + checkGroupCount(3 + 1); // also count the group that was created in the + // setUp(). + + Set list = users.list(group1); + assertTrue(list.contains(user1)); + assertEquals(1, list.size()); + + list = users.list(group2); + assertTrue(list.contains(user1)); + assertTrue(list.contains(user2)); + assertEquals(2, list.size()); + + list = users.list(group3); + assertTrue(list.contains(user1)); + assertTrue(list.contains(user2)); + assertTrue(list.contains(user3)); + assertEquals(3, list.size()); + } +} diff --git a/security/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java b/security/impl/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java similarity index 69% rename from security/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java rename to security/impl/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java index 055828d6..0a27865b 100644 --- a/security/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java +++ b/security/impl/src/test/java/org/wamblee/usermgt/UserAdministrationImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,27 +12,27 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.usermgt; -import java.util.Set; - import junit.framework.TestCase; import org.apache.log4j.Logger; + import org.wamblee.security.encryption.Md5HexMessageDigester; + import org.wamblee.usermgt.UserMgtException.Reason; +import java.util.Set; + /** * Test of user administration implementation. - * + * * @author Erik Brakkee */ public class UserAdministrationImplTest extends TestCase { - private static final Logger LOGGER = Logger - .getLogger(UserAdministrationImplTest.class); + .getLogger(UserAdministrationImplTest.class); private static final String USER1 = "piet"; @@ -46,8 +46,7 @@ public class UserAdministrationImplTest extends TestCase { private static final String GROUP2 = "runners"; - private UserAdministration _admin; - + private UserAdministration admin; /* * (non-Javadoc) @@ -57,21 +56,25 @@ public class UserAdministrationImplTest extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); - _admin = createAdmin(); + admin = createAdmin(); } protected UserAdministration createAdmin() { - UserSet users = new InMemoryUserSet( new RegexpNameValidator(RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, "Password must contain at least 6 characters"), - new Md5HexMessageDigester()); + UserSet users = new InMemoryUserSet(new RegexpNameValidator( + RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, + "Password must contain at least 6 characters"), + new Md5HexMessageDigester()); GroupSet groups = new InMemoryGroupSet(); + return new UserAdministrationImpl(users, groups, - new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, - Reason.INVALID_USERNAME, "Invalid user"), - new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, - Reason.INVALID_GROUPNAME, "Invalid group")); + new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, + Reason.INVALID_USERNAME, "Invalid user"), + new RegexpNameValidator(RegexpNameValidator.ID_PATTERN, + Reason.INVALID_GROUPNAME, "Invalid group")); } - - protected User createUser(String aName, String aPassword, Group aGroup) throws UserMgtException { + + protected User createUser(String aName, String aPassword, Group aGroup) + throws UserMgtException { return UsermgtTestUtils.createUser(aName, aPassword, aGroup); } @@ -79,10 +82,10 @@ public class UserAdministrationImplTest extends TestCase { * Constructs the admin, verify it contains no users and no groups. */ public void testConstruct() { - assertEquals(0, _admin.getUsers().size()); - assertEquals(0, _admin.getGroups().size()); - assertEquals(0, _admin.getUserCount()); - assertEquals(0, _admin.getGroupCount()); + assertEquals(0, admin.getUsers().size()); + assertEquals(0, admin.getGroups().size()); + assertEquals(0, admin.getUserCount()); + assertEquals(0, admin.getGroupCount()); } /** @@ -91,24 +94,24 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testCreateGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); assertNotNull(group); assertEquals(GROUP1, group.getName()); - Set groups = _admin.getGroups(); + Set groups = admin.getGroups(); assertEquals(1, groups.size()); - assertEquals(1, _admin.getGroupCount()); + assertEquals(1, admin.getGroupCount()); assertTrue(groups.contains(group)); } private void createInvalidGroup(String aUsername) { try { - _admin.createGroup(aUsername); + admin.createGroup(aUsername); fail(); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.INVALID_GROUPNAME, e - .getReason()); - assertEquals(0, _admin.getGroupCount()); + .getReason()); + assertEquals(0, admin.getGroupCount()); } } @@ -132,14 +135,17 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testCreateDuplicateGroup() throws UserMgtException { - _admin.createGroup(GROUP1); + admin.createGroup(GROUP1); + try { - _admin.createGroup(GROUP1); + admin.createGroup(GROUP1); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason()); - assertEquals(1, _admin.getGroupCount()); + assertEquals(1, admin.getGroupCount()); + return; } + fail(); } @@ -149,26 +155,26 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testCreateUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); assertNotNull(user); assertEquals(USER1, user.getName()); user.checkPassword(PASS1); - Set users = _admin.getUsers(); + Set users = admin.getUsers(); assertEquals(1, users.size()); - assertEquals(1, _admin.getUserCount()); + assertEquals(1, admin.getUserCount()); assertTrue(users.contains(user)); } private void createInvalidUser(String aUsername, Group aGroup) { try { - _admin.createUser(aUsername, "pass", aGroup); + admin.createUser(aUsername, "pass", aGroup); fail(); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.INVALID_USERNAME, e - .getReason()); - assertEquals(0, _admin.getUserCount()); + .getReason()); + assertEquals(0, admin.getUserCount()); } } @@ -178,7 +184,7 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testCreateInvalidUserName() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); createInvalidUser("", group); createInvalidUser("0abc", group); // should not start with digits createInvalidUser("a b", group); // should not contain spaces @@ -192,14 +198,15 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testCreateDuplicateUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + admin.createUser(USER1, PASS1, group); + try { - _admin.createUser(USER1, PASS2, group); + admin.createUser(USER1, PASS2, group); fail(); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason()); - assertEquals(1, _admin.getUserCount()); + assertEquals(1, admin.getUserCount()); } } @@ -209,11 +216,11 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testGetUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); - User user2 = _admin.getUser(USER1); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); + User user2 = admin.getUser(USER1); assertTrue(user.equals(user2)); - assertNull(_admin.getUser(USER2)); + assertNull(admin.getUser(USER2)); } /** @@ -222,10 +229,10 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testGetGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - Group group2 = _admin.getGroup(GROUP1); + Group group = admin.createGroup(GROUP1); + Group group2 = admin.getGroup(GROUP1); assertTrue(group.equals(group2)); - assertNull(_admin.getGroup(GROUP2)); + assertNull(admin.getGroup(GROUP2)); } /** @@ -235,27 +242,29 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testAddUserToGroup() throws UserMgtException { - - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); - Group group2 = _admin.createGroup(GROUP2); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); + Group group2 = admin.createGroup(GROUP2); assertTrue(user.isInGroup(group)); assertFalse(user.isInGroup(group2)); - _admin.addUserToGroup(user, group2); + admin.addUserToGroup(user, group2); assertTrue(user.isInGroup(group)); assertTrue(user.isInGroup(group2)); - Set users = _admin.getUsers(group2); + + Set users = admin.getUsers(group2); assertNotNull(users); assertEquals(1, users.size()); assertTrue(users.contains(user)); try { - _admin.addUserToGroup(user, group); + admin.addUserToGroup(user, group); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.USER_ALREADY_IN_GROUP, e - .getReason()); + .getReason()); + return; } + fail(); } @@ -265,14 +274,17 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testAddUserToGroupUnknownUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); User user = createUser(USER1, PASS1, group); + try { - _admin.addUserToGroup(user, group); + admin.addUserToGroup(user, group); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason()); + return; } + fail(); } @@ -282,15 +294,18 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testAddUserToGroupUnknownGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); Group group2 = new Group(GROUP2); + try { - _admin.addUserToGroup(user, group2); + admin.addUserToGroup(user, group2); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason()); + return; } + fail(); } @@ -298,19 +313,21 @@ public class UserAdministrationImplTest extends TestCase { * Removes a user from a group. Verifies that the user is removed from the * group using several API calls. Verifies that an exception occurs if the * user not part of the group or if the user is only part of one group. + * */ public void testRemoveUserFromGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); + + User user = admin.createUser(USER1, PASS1, group); + Group group2 = admin.createGroup(GROUP2); + admin.addUserToGroup(user, group2); - User user = _admin.createUser(USER1, PASS1, group); - Group group2 = _admin.createGroup(GROUP2); - _admin.addUserToGroup(user, group2); Set groups = user.getGroups(); assertEquals(2, groups.size()); assertTrue(groups.contains(group)); assertTrue(groups.contains(group2)); - _admin.removeUserFromGroup(user, group); + admin.removeUserFromGroup(user, group); groups = user.getGroups(); assertEquals(1, groups.size()); assertTrue(groups.contains(group2)); @@ -323,10 +340,11 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRemoveUserFromGroupUnknownUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); User user = createUser(USER1, GROUP1, group); + try { - _admin.removeUserFromGroup(user, group); + admin.removeUserFromGroup(user, group); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason()); } @@ -338,11 +356,12 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRemoveUserFromGroupUnknownGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); Group group2 = new Group(GROUP2); + try { - _admin.removeUserFromGroup(user, group2); + admin.removeUserFromGroup(user, group2); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason()); } @@ -351,15 +370,17 @@ public class UserAdministrationImplTest extends TestCase { /** * Removes a user from a group where the user is only part of one group. * Verifies that an exception is thrown. + * */ public void testRemoveUserFromGroupOnlyGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); + try { - _admin.removeUserFromGroup(user, group); + admin.removeUserFromGroup(user, group); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.USER_MUST_BE_IN_A_GROUP, e - .getReason()); + .getReason()); } } @@ -370,19 +391,20 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testGetUsersAndGroups() throws UserMgtException { - Group group1 = _admin.createGroup(GROUP1); - Group group2 = _admin.createGroup(GROUP2); + Group group1 = admin.createGroup(GROUP1); + Group group2 = admin.createGroup(GROUP2); - User user1 = _admin.createUser(USER1, PASS1, group1); - _admin.addUserToGroup(user1, group2); - User user2 = _admin.createUser(USER2, PASS2, group2); + User user1 = admin.createUser(USER1, PASS1, group1); + admin.addUserToGroup(user1, group2); - Set users = _admin.getUsers(); + User user2 = admin.createUser(USER2, PASS2, group2); + + Set users = admin.getUsers(); assertEquals(2, users.size()); assertTrue(users.contains(user1)); assertTrue(users.contains(user2)); - Set groups = _admin.getGroups(); + Set groups = admin.getGroups(); assertEquals(2, groups.size()); assertTrue(groups.contains(group1)); assertTrue(groups.contains(group2)); @@ -406,29 +428,30 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRenameUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user1 = _admin.createUser(USER1, PASS1, group); - _admin.renameUser(user1, USER2); + Group group = admin.createGroup(GROUP1); + User user1 = admin.createUser(USER1, PASS1, group); + admin.renameUser(user1, USER2); assertEquals(USER2, user1.getName()); - assertEquals(user1, _admin.getUser(USER2)); - - _admin.createUser(USER1, PASS1, group); + assertEquals(user1, admin.getUser(USER2)); try { - _admin.renameUser(user1, USER1); + admin.renameUser(user1, USER1); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.DUPLICATE_USER, e.getReason()); // do a trivial reanem try { - _admin.renameUser(user1, user1.getName()); + admin.renameUser(user1, user1.getName()); } catch (UserMgtException e2) { assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2 - .getReason()); + .getReason()); + return; } + fail(); } + fail(); } @@ -438,10 +461,11 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRenameUserInvalidUsername() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user1 = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user1 = admin.createUser(USER1, PASS1, group); + try { - _admin.renameUser(user1, USER2); + admin.renameUser(user1, USER2); } catch (UserMgtException e) { assertEquals(e.getReason(), Reason.INVALID_USERNAME); } @@ -454,28 +478,33 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRenameGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - _admin.renameGroup(group, GROUP2); + Group group = admin.createGroup(GROUP1); + admin.renameGroup(group, GROUP2); assertEquals(GROUP2, group.getName()); - assertEquals(group, _admin.getGroup(GROUP2)); + assertEquals(group, admin.getGroup(GROUP2)); + + admin.createGroup(GROUP1); - _admin.createGroup(GROUP1); try { - _admin.renameGroup(group, GROUP1); + admin.renameGroup(group, GROUP1); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.DUPLICATE_GROUP, e.getReason()); // do a trivial reanem try { - _admin.renameGroup(group, group.getName()); + admin.renameGroup(group, group.getName()); } catch (UserMgtException e2) { assertEquals(UserMgtException.Reason.TRIVIAL_RENAME, e2 - .getReason()); + .getReason()); + return; } + fail(); + return; } + fail(); } @@ -485,9 +514,10 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRenameGroupInvalidGroupname() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); + try { - _admin.renameGroup(group, "a b"); + admin.renameGroup(group, "a b"); } catch (UserMgtException e) { assertEquals(e.getReason(), Reason.INVALID_GROUPNAME); } @@ -499,20 +529,20 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRemoveUser() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); - assertEquals(1, _admin.getUserCount()); - _admin.removeUser(user); - assertEquals(0, _admin.getUserCount()); + assertEquals(1, admin.getUserCount()); + admin.removeUser(user); + assertEquals(0, admin.getUserCount()); - _admin.createUser(USER1, PASS1, group); - assertEquals(1, _admin.getUserCount()); + admin.createUser(USER1, PASS1, group); + assertEquals(1, admin.getUserCount()); User user2 = createUser(USER2, PASS2, group); try { - _admin.removeUser(user2); + admin.removeUser(user2); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_USER, e.getReason()); } @@ -525,20 +555,23 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRemoveGroup() throws UserMgtException { - Group group1 = _admin.createGroup(GROUP1); - assertEquals(1, _admin.getGroupCount()); - _admin.removeGroup(group1); - assertEquals(0, _admin.getGroupCount()); - group1 = _admin.createGroup(GROUP1); + Group group1 = admin.createGroup(GROUP1); + assertEquals(1, admin.getGroupCount()); + admin.removeGroup(group1); + assertEquals(0, admin.getGroupCount()); + group1 = admin.createGroup(GROUP1); + + admin.createUser(USER1, PASS1, group1); - _admin.createUser(USER1, PASS1, group1); try { - _admin.removeGroup(group1); + admin.removeGroup(group1); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.GROUP_STILL_OCCUPIED, e - .getReason()); + .getReason()); + return; } + fail(); } @@ -547,10 +580,11 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testRemoveGroupUnknownGroup() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); + Group group = admin.createGroup(GROUP1); Group group2 = new Group(GROUP2); + try { - _admin.removeGroup(group2); + admin.removeGroup(group2); } catch (UserMgtException e) { assertEquals(UserMgtException.Reason.UNKNOWN_GROUP, e.getReason()); } @@ -562,12 +596,13 @@ public class UserAdministrationImplTest extends TestCase { * @throws UserMgtException */ public void testChangePassword() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - User user = _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + User user = admin.createUser(USER1, PASS1, group); user.changePassword(PASS1, PASS2); // retrieve the user and verifies the password hasn't changed. - User user2 = _admin.getUser(USER1); + User user2 = admin.getUser(USER1); + try { user2.checkPassword(PASS2); fail(); // password should not have changed already. @@ -576,11 +611,10 @@ public class UserAdministrationImplTest extends TestCase { } // now notify the admin of the change in the user - _admin.userModified(user); + admin.userModified(user); - user2 = _admin.getUser(USER1); + user2 = admin.getUser(USER1); user2.checkPassword(PASS2); // this time it should succeed. - } /** @@ -588,16 +622,17 @@ public class UserAdministrationImplTest extends TestCase { * */ public void testPerformanceFindUserByName() throws UserMgtException { - Group group = _admin.createGroup(GROUP1); - _admin.createUser(USER1, PASS1, group); + Group group = admin.createGroup(GROUP1); + admin.createUser(USER1, PASS1, group); int n = 1000; long time = System.currentTimeMillis(); + for (int i = 0; i < n; i++) { - _admin.getUser(USER1); + admin.getUser(USER1); } - LOGGER.info("Looked up a user " + n + " times in " - + (float) (System.currentTimeMillis() - time) / 1000.0); - } + LOGGER.info("Looked up a user " + n + " times in " + + ((float) (System.currentTimeMillis() - time) / 1000.0)); + } } diff --git a/security/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java b/security/impl/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java similarity index 66% rename from security/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java rename to security/impl/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java index 07a376c5..a8e1dd51 100644 --- a/security/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java +++ b/security/impl/src/test/java/org/wamblee/usermgt/UsermgtTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,50 +13,54 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.usermgt; import org.wamblee.security.encryption.Md5HexMessageDigester; + import org.wamblee.usermgt.UserMgtException.Reason; /** - * User management test utilities. - * + * User management test utilities. + * * @author Erik Brakkee */ public class UsermgtTestUtils { - private static final String DUMMY_GROUP = "dummygroup"; + private static final String DUMMY_PASSWD = "dummypasswd"; - public static Group createGroup(String aName) { + public static Group createGroup(String aName) { return new Group(aName); } - - public static User createUser(String aUsername) throws UserMgtException { + + public static User createUser(String aUsername) throws UserMgtException { return createUser(aUsername, DUMMY_GROUP); } - - public static User createUser(String aUsername, String aGroup) throws UserMgtException { - return createUser(aUsername, createGroup(aGroup)); + + public static User createUser(String aUsername, String aGroup) + throws UserMgtException { + return createUser(aUsername, createGroup(aGroup)); } - - public static User createUser(String aUsername, Group aGroup) throws UserMgtException { + + public static User createUser(String aUsername, Group aGroup) + throws UserMgtException { return createUser(aUsername, DUMMY_PASSWD, aGroup); } - - public static User createUser(String aName, String aPassword, Group aGroup) throws UserMgtException { - return new User(aName, aPassword, aGroup, - new RegexpNameValidator(RegexpNameValidator.PASSWORD_PATTERN, - Reason.INVALID_PASSWORD, "Password must be at least 6 chars"), - new Md5HexMessageDigester()); + + public static User createUser(String aName, String aPassword, Group aGroup) + throws UserMgtException { + return new User(aName, aPassword, aGroup, new RegexpNameValidator( + RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, + "Password must be at least 6 chars"), new Md5HexMessageDigester()); } - - public static void addUserToGroup(User aUser, Group aGroup) throws UserMgtException { + + public static void addUserToGroup(User aUser, Group aGroup) + throws UserMgtException { aUser.addGroup(aGroup); } - - public static void removeUserFromGroup(User aUser, Group aGroup) throws UserMgtException { + + public static void removeUserFromGroup(User aUser, Group aGroup) + throws UserMgtException { aUser.removeGroup(aGroup); } } diff --git a/security/src/test/resources/properties/test.org.wamblee.security.database.properties b/security/impl/src/test/resources/properties/test.org.wamblee.security.database.properties similarity index 100% rename from security/src/test/resources/properties/test.org.wamblee.security.database.properties rename to security/impl/src/test/resources/properties/test.org.wamblee.security.database.properties diff --git a/security/src/test/resources/properties/test.org.wamblee.security.usermgt.properties b/security/impl/src/test/resources/properties/test.org.wamblee.security.usermgt.properties similarity index 100% rename from security/src/test/resources/properties/test.org.wamblee.security.usermgt.properties rename to security/impl/src/test/resources/properties/test.org.wamblee.security.usermgt.properties diff --git a/security/src/test/resources/spring/test.org.wamblee.security.datasource.xml b/security/impl/src/test/resources/spring/test.org.wamblee.security.datasource.xml similarity index 100% rename from security/src/test/resources/spring/test.org.wamblee.security.datasource.xml rename to security/impl/src/test/resources/spring/test.org.wamblee.security.datasource.xml diff --git a/security/src/test/resources/spring/test.org.wamblee.security.properties.xml b/security/impl/src/test/resources/spring/test.org.wamblee.security.properties.xml similarity index 100% rename from security/src/test/resources/spring/test.org.wamblee.security.properties.xml rename to security/impl/src/test/resources/spring/test.org.wamblee.security.properties.xml diff --git a/security/src/test/resources/spring/test.org.wamblee.security.useraccessor.xml b/security/impl/src/test/resources/spring/test.org.wamblee.security.useraccessor.xml similarity index 100% rename from security/src/test/resources/spring/test.org.wamblee.security.useraccessor.xml rename to security/impl/src/test/resources/spring/test.org.wamblee.security.useraccessor.xml diff --git a/security/src/test/resources/spring/test.org.wamblee.security.usermgtinitializer.xml b/security/impl/src/test/resources/spring/test.org.wamblee.security.usermgtinitializer.xml similarity index 100% rename from security/src/test/resources/spring/test.org.wamblee.security.usermgtinitializer.xml rename to security/impl/src/test/resources/spring/test.org.wamblee.security.usermgtinitializer.xml diff --git a/security/jpatest/pom.xml b/security/jpatest/pom.xml new file mode 100644 index 00000000..8f6c8031 --- /dev/null +++ b/security/jpatest/pom.xml @@ -0,0 +1,64 @@ + + + + org.wamblee + wamblee-utils + 0.2.2 + + + 4.0.0 + org.wamblee + wamblee-security-jpatest + jar + /security/jpatest + http://wamblee.org + + + + org.hibernate + hibernate-entitymanager + 3.5.0-Final + + + javax.transaction + jta + + + + + org.wamblee + wamblee-security-impl + 0.2.2 + + + org.wamblee + wamblee-security-impl + 0.2.2 + test-jar + test + + + + org.wamblee + wamblee-test-enterprise + 0.2.2 + test + + + org.wamblee + wamblee-test-hibernate + 0.2.2 + test + + + + + + + jboss + JBoss Repo + http://repository.jboss.org/maven2 + + + + diff --git a/security/jpatest/src/test/java/org/wamblee/security/authorization/jpa/JpaAuthorizationServiceTest.java b/security/jpatest/src/test/java/org/wamblee/security/authorization/jpa/JpaAuthorizationServiceTest.java new file mode 100644 index 00000000..1573f473 --- /dev/null +++ b/security/jpatest/src/test/java/org/wamblee/security/authorization/jpa/JpaAuthorizationServiceTest.java @@ -0,0 +1,127 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.security.authorization.jpa; + +import javax.persistence.EntityManager; + +import org.apache.log4j.Logger; +import org.wamblee.security.authorization.AbstractAuthorizationService; +import org.wamblee.security.authorization.AllOperation; +import org.wamblee.security.authorization.AuthorizationResult; +import org.wamblee.security.authorization.AuthorizationService; +import org.wamblee.security.authorization.AuthorizationServiceTest; +import org.wamblee.security.authorization.TestAuthorizationRule; +import org.wamblee.support.persistence.JpaTester; +import org.wamblee.support.persistence.TransactionProxyFactory; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; +import org.wamblee.usermgt.jpa.SecurityPersistenceUnit; + +/** + * Unit test for the persistent authorization service. + * + * @author Erik Brakkee + */ +public class JpaAuthorizationServiceTest extends AuthorizationServiceTest { + private static final Logger LOGGER = Logger + .getLogger(JpaAuthorizationServiceTest.class); + + private static final String SERVICE_TABLE = "SEC_AUTH_SVC"; + + private static final String RULES_TABLE = "SEC_AUTH_RULE"; + + private static final String SERVICE_RULES_TABLE = "SEC_AUTH_SVC_SEC_AUTH_RULE"; + + private static final String OPERATIONCOND_TABLE = "SEC_OPERATION_CONDITION"; + + private static final String PATHCOND_TABLE = "SEC_PATH_CONDITION"; + + private static final String USERCOND_TABLE = "SEC_USER_CONDITION"; + + private JpaTester jpaTester; + + private AuthorizationService authorizationService; + + @Override + protected void setUp() throws Exception { + jpaTester = new JpaTester(new SecurityPersistenceUnit()); + jpaTester.start(); + + super.setUp(); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationServiceTest#createService + * () + */ + @Override + protected AuthorizationService createService() { + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), AuthorizationService.class); + JpaAuthorizationService service = new JpaAuthorizationService( + "DEFAULT", factory.getTransactionScopedEntityManager(), + createUserAccessor(), 10000); + + return factory.getProxy(service); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.security.authorization.AuthorizationServiceTest#checkRuleCount + * (int) + */ + @Override + protected void checkRuleCount(int aCount) { + try { + assertEquals(1, jpaTester.getDbUtils().getTableSize(SERVICE_TABLE)); + assertEquals(aCount, jpaTester.getDbUtils().getTableSize( + RULES_TABLE)); + assertEquals(aCount, jpaTester.getDbUtils().getTableSize( + SERVICE_RULES_TABLE)); + assertEquals(aCount, jpaTester.getDbUtils().getTableSize( + USERCOND_TABLE)); + assertEquals(aCount, jpaTester.getDbUtils().getTableSize( + PATHCOND_TABLE)); + assertEquals(aCount, jpaTester.getDbUtils().getTableSize( + OPERATIONCOND_TABLE)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void testPerformance() { + int n = 1000; + long time = System.currentTimeMillis(); + + for (int i = 0; i < n; i++) { + testFirstRuleGrants(); + resetTestRules(); + testSecondRuleDenies(); + resetTestRules(); + testThirdRuleGrants(); + resetTestRules(); + testNoRulesSupportResource(); + } + + LOGGER.info("Executed " + (4 * n) + " authorization checks in " + + ((float) (System.currentTimeMillis() - time) / (float) 1000) + + " seconds."); + } +} diff --git a/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaGroupSetTest.java b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaGroupSetTest.java new file mode 100644 index 00000000..4ece0ba4 --- /dev/null +++ b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaGroupSetTest.java @@ -0,0 +1,77 @@ +package org.wamblee.usermgt.jpa; + +import java.sql.Connection; +import java.sql.ResultSet; + +import org.junit.After; +import org.junit.Before; +import org.wamblee.support.persistence.JpaTester; +import org.wamblee.support.persistence.TransactionProxyFactory; +import org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork; +import org.wamblee.usermgt.GroupSet; +import org.wamblee.usermgt.InMemoryGroupSetTest; + + +public class JpaGroupSetTest extends InMemoryGroupSetTest { + + private static final String GROUP_TABLE = "SEC_GROUP"; + + private static final String GROUP_QUERY = "select * from " + GROUP_TABLE + + " where name = ?"; + + private JpaTester jpaTester; + + @Before + public void setUp() throws Exception { + jpaTester = new JpaTester(new SecurityPersistenceUnit()); + jpaTester.start(); + + // Superclass setup will call createGroupSet so requires initialized JPA. + super.setUp(); + } + + @After + public void tearDown() throws Exception { + jpaTester.stop(); + super.tearDown(); + } + + @Override + protected void checkGroupCount(int aSize) throws Exception { + super.checkGroupCount(aSize); + assertEquals(aSize, jpaTester.getDbUtils().getTableSize(GROUP_TABLE)); + } + + @Override + protected void checkGroupExists(String aGroup) throws Exception { + super.checkGroupExists(aGroup); + assertTrue(groupExists(aGroup)); + } + + private boolean groupExists(final String aGroup) throws Exception { + return jpaTester.getDbUtils().executeInTransaction( + new JdbcUnitOfWork() { + @Override + public Boolean execute(Connection aConnection) throws Exception { + ResultSet res = jpaTester.getDbUtils().executeQuery( + aConnection, GROUP_QUERY, aGroup); + return res.next(); + } + }); + } + + @Override + protected void checkGroupNotExists(String aGroup) throws Exception { + super.checkGroupNotExists(aGroup); + assertFalse(groupExists(aGroup)); + } + + @Override + protected GroupSet createGroupSet() { + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), GroupSet.class); + GroupSet groupset = new JpaGroupSet(factory.getTransactionScopedEntityManager()); + GroupSet proxy = factory.getProxy(groupset); + return proxy; + } +} diff --git a/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserAdministrationTest.java b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserAdministrationTest.java new file mode 100644 index 00000000..a0c0eb1a --- /dev/null +++ b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserAdministrationTest.java @@ -0,0 +1,143 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt.jpa; + +import java.lang.reflect.Method; +import java.sql.Connection; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wamblee.cache.EhCache; +import org.wamblee.io.ClassPathResource; +import org.wamblee.security.encryption.Md5HexMessageDigester; +import org.wamblee.security.encryption.MessageDigester; +import org.wamblee.support.persistence.JpaTester; +import org.wamblee.support.persistence.TransactionProxyFactory; +import org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork; +import org.wamblee.usermgt.GroupSet; +import org.wamblee.usermgt.NameValidator; +import org.wamblee.usermgt.RegexpNameValidator; +import org.wamblee.usermgt.User; +import org.wamblee.usermgt.UserAdministration; +import org.wamblee.usermgt.UserAdministrationImpl; +import org.wamblee.usermgt.UserAdministrationImplTest; +import org.wamblee.usermgt.UserSet; + +/** + * User administration tests with persistence based on Hibernate. This executes + * the same test cases as {@link org.wamblee.usermgt.UserAdministrationImplTest} + * with in addition, one test case that executes all Hibernate test cases + * separately with each test case in its own transaction. + * + * @author Erik Brakkee + */ +public class JpaUserAdministrationTest extends UserAdministrationImplTest { + private static final Log LOG = LogFactory + .getLog(JpaUserAdministrationTest.class); + + private JpaTester jpaTester; + + private EhCache userCache; + + private UserAdministration userAdmin; + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.UserAdministrationImplTest#setUp() + */ + @Override + protected void setUp() throws Exception { + jpaTester = new JpaTester(new SecurityPersistenceUnit()); + jpaTester.start(); + + userCache = new EhCache(new ClassPathResource( + "properties/org.wamblee.security.ehcache.xml"), "users"); + + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), UserAdministration.class); + + NameValidator passwordValidator = new RegexpNameValidator(".{5,}", + "INVALID_PASSWORD", "Password must have at least 5 characters"); + MessageDigester passwordDigester = new Md5HexMessageDigester(); + UserSet userset = new JpaUserSet(userCache, passwordValidator, + passwordDigester, factory.getTransactionScopedEntityManager()); + GroupSet groupset = new JpaGroupSet(factory + .getTransactionScopedEntityManager()); + + NameValidator userValidator = new RegexpNameValidator( + "[a-zA-Z]+[a-zA-Z0-9]*", "INVALID_USERNAME", ""); + NameValidator groupValidator = new RegexpNameValidator( + "[a-zA-Z]+[a-zA-Z0-9]*", "INVALID_GROUPNAME", ""); + UserAdministration userAdminImpl = new UserAdministrationImpl(userset, + groupset, userValidator, groupValidator); + userAdmin = factory.getProxy(userAdminImpl); + + super.setUp(); + clearUserCache(); + } + + @Override + protected void tearDown() throws Exception { + jpaTester.stop(); + super.tearDown(); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.UserAdministrationImplTest#createAdmin() + */ + @Override + protected UserAdministration createAdmin() { + return userAdmin; + } + + public void testAllTestsInASeparateTransaction() throws Exception { + Method[] methods = UserAdministrationImplTest.class.getMethods(); + + for (final Method method : methods) { + if (method.getName().startsWith("test")) { + jpaTester.getDbUtils().cleanDatabase(); + clearUserCache(); + jpaTester.getDbUtils().executeInTransaction( + new JdbcUnitOfWork() { + @Override + public Void execute(Connection aConnection) + throws Exception { + LOG.info("Running test " + method.getName()); + + try { + method.invoke(JpaUserAdministrationTest.this); + } catch (Throwable t) { + LOG.error("Test " + method.getName() + + " failed"); + throw new RuntimeException(t.getMessage(), t); + } finally { + LOG.info("Test " + method.getName() + + " finished"); + } + return null; + } + }); + } + } + } + + private void clearUserCache() { + userCache.clear(); + } +} diff --git a/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserSetTest.java b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserSetTest.java new file mode 100644 index 00000000..795bf597 --- /dev/null +++ b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/JpaUserSetTest.java @@ -0,0 +1,269 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.usermgt.jpa; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.util.Set; + +import org.wamblee.cache.EhCache; +import org.wamblee.io.ClassPathResource; +import org.wamblee.security.encryption.Md5HexMessageDigester; +import org.wamblee.security.encryption.MessageDigester; +import org.wamblee.support.persistence.JpaTester; +import org.wamblee.support.persistence.TransactionProxyFactory; +import org.wamblee.support.persistence.DatabaseUtils.JdbcUnitOfWork; +import org.wamblee.usermgt.Group; +import org.wamblee.usermgt.GroupSet; +import org.wamblee.usermgt.InMemoryUserSetTest; +import org.wamblee.usermgt.NameValidator; +import org.wamblee.usermgt.RegexpNameValidator; +import org.wamblee.usermgt.User; +import org.wamblee.usermgt.UserSet; + +/** + * Tests for {@link org.wamblee.usermgt.hibernate.HibernateGroupSet} + * + * @author Erik Brakkee + */ +public class JpaUserSetTest extends InMemoryUserSetTest { + private static final String USER_TABLE = "SEC_USER"; + + private static final String GROUP_TABLE = "SEC_GROUP"; + + private static final String USER_QUERY = "select * from " + USER_TABLE + + " where name = ?"; + + private static final String GROUP_QUERY = "select * from " + GROUP_TABLE + + " where name = ?"; + + private UserSet userset; + + private GroupSet groupset; + + private EhCache userCache; + + private JpaTester jpaTester; + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.InMemoryUserSetTest#setUp() + */ + @Override + protected void setUp() throws Exception { + jpaTester = new JpaTester(new SecurityPersistenceUnit()); + jpaTester.start(); + + userCache = new EhCache( + new ClassPathResource("properties/org.wamblee.security.ehcache.xml"), "users"); + + userset = createUserSetImpl(); + groupset = createGroupSetImpl(); + + clearUserCache(); + + super.setUp(); + } + + private UserSet createUserSetImpl() { + NameValidator passwordValidator = new RegexpNameValidator( + ".{5,}", "INVALID_PASSWORD", "Password must have at least 5 characters"); + + MessageDigester passwordDigester = new Md5HexMessageDigester(); + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), UserSet.class); + UserSet jpaUserset = new JpaUserSet(userCache, passwordValidator, passwordDigester, + factory.getTransactionScopedEntityManager()); + return factory.getProxy(jpaUserset); + } + + private GroupSet createGroupSetImpl() { + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), GroupSet.class); + GroupSet groupset = new JpaGroupSet(factory.getTransactionScopedEntityManager()); + GroupSet proxy = factory.getProxy(groupset); + return proxy; + } + + @Override + protected void tearDown() throws Exception { + jpaTester.stop(); + super.tearDown(); + } + + /** + * Clears the user cache. + */ + private void clearUserCache() { + userCache.clear(); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupCount(int) + */ + @Override + protected void checkUserCount(int aSize) throws Exception { + super.checkUserCount(aSize); + assertEquals(aSize, jpaTester.getDbUtils().getTableSize(USER_TABLE)); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupExists(java.lang.String + * ) + */ + @Override + protected void checkUserExists(final String aUser) throws Exception { + assertEquals(1, countUser(aUser)); + } + + private int countUser(final String aUser) throws Exception { + int count = jpaTester.getDbUtils().executeInTransaction(new JdbcUnitOfWork() { + @Override + public Integer execute(Connection aConnection) throws Exception { + ResultSet res = jpaTester.getDbUtils().executeQuery(aConnection, USER_QUERY, aUser); + return jpaTester.getDbUtils().countResultSet(res); + } + }); + return count; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupNotExists(java.lang + * .String) + */ + @Override + protected void checkUserNotExists(String aUser) throws Exception { + assertEquals(0, countUser(aUser)); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupCount(int) + */ + @Override + protected void checkGroupCount(int aSize) throws Exception { + assertEquals(aSize, jpaTester.getDbUtils().getTableSize(GROUP_TABLE)); + } + + private int countGroup(final String aGroup) throws Exception { + int count = jpaTester.getDbUtils().executeInTransaction(new JdbcUnitOfWork() { + @Override + public Integer execute(Connection aConnection) throws Exception { + ResultSet res = jpaTester.getDbUtils().executeQuery(aConnection, GROUP_QUERY, aGroup); + return jpaTester.getDbUtils().countResultSet(res); + } + }); + return count; + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupExists(java.lang.String + * ) + */ + @Override + protected void checkGroupExists(String aGroup) throws Exception { + assertEquals(1, countGroup(aGroup)); + } + + /* + * (non-Javadoc) + * + * @see + * org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupNotExists(java.lang + * .String) + */ + @Override + protected void checkGroupNotExists(String aGroup) throws Exception { + assertEquals(0, countGroup(aGroup)); + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.InMemoryGroupSetTest#createGroupSet() + */ + @Override + protected UserSet createUserSet() { + return userset; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.usermgt.InMemoryUserSetTest#createGroupSet() + */ + @Override + protected GroupSet createGroupSet() { + return groupset; + } + + /** + * Reproduction of a bug. Create a user which is in group1 Add it to a + * second group group2. Remove the user from group1. Verify the user is in + * group2. + * + */ + public void testVerifyAddRemove() throws Exception { + jpaTester.getDbUtils().cleanDatabase(); // super class setup always creates one group. + + GroupSet groups = getGroups(); + assertEquals(0, groups.size()); + + Group group1 = createGroup("group1"); + Group group2 = createGroup("group2"); + groups.add(group1); + groups.add(group2); + checkGroupExists("group1"); + checkGroupExists("group2"); + + User user = createUser("user", PASSWORD, group1); + getUsers().add(user); + checkUserExists("user"); + + addUserToGroup(user, group2); + getUsers().userModified(user); + clearUserCache(); + + User user2 = getUsers().find("user"); + + Set userGroups = user2.getGroups(); + assertTrue(user2.isInGroup("group1")); + assertTrue(user2.isInGroup("group2")); + assertEquals(2, userGroups.size()); + + removeUserFromGroup(user, group1); + getUsers().userModified(user); + clearUserCache(); + user2 = getUsers().find("user"); + userGroups = user2.getGroups(); + assertFalse(user2.isInGroup("group1")); + assertTrue(user2.isInGroup("group2")); + assertEquals(1, userGroups.size()); + } +} diff --git a/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/SecurityPersistenceUnit.java b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/SecurityPersistenceUnit.java new file mode 100644 index 00000000..8f3aeb8a --- /dev/null +++ b/security/jpatest/src/test/java/org/wamblee/usermgt/jpa/SecurityPersistenceUnit.java @@ -0,0 +1,18 @@ +package org.wamblee.usermgt.jpa; + +import org.dbunit.dataset.DataSetException; +import org.dbunit.dataset.filter.ITableFilterSimple; +import org.wamblee.support.persistence.PersistenceUnitDescription; + +public class SecurityPersistenceUnit extends PersistenceUnitDescription { + + public SecurityPersistenceUnit() { + super("jdbc/security", "securitytest", new ITableFilterSimple() { + + @Override + public boolean accept(String aTableName) throws DataSetException { + return aTableName.startsWith("SEC_"); + } + }); + } +} diff --git a/security/jpatest/src/test/resources/META-INF/persistence.xml b/security/jpatest/src/test/resources/META-INF/persistence.xml new file mode 100644 index 00000000..6b69b34c --- /dev/null +++ b/security/jpatest/src/test/resources/META-INF/persistence.xml @@ -0,0 +1,28 @@ + + + + jdbc/security + + org.wamblee.usermgt.User + org.wamblee.usermgt.Group + org.wamblee.security.authorization.AbstractUserCondition + org.wamblee.security.authorization.AnyUserCondition + org.wamblee.security.authorization.GroupUserCondition + org.wamblee.security.authorization.AbstractOperationCondition + org.wamblee.security.authorization.IsaOperationCondition + org.wamblee.security.authorization.AbstractPathCondition + org.wamblee.security.authorization.RegexpPathCondition + org.wamblee.security.authorization.StartsWithPathCondition + org.wamblee.security.authorization.AbstractAuthorizationRule + org.wamblee.security.authorization.UrlAuthorizationRule + org.wamblee.security.authorization.TestAuthorizationRule + org.wamblee.security.authorization.AbstractAuthorizationService + org.wamblee.security.authorization.DefaultAuthorizationService + + true + + + \ No newline at end of file diff --git a/security/pom.xml b/security/pom.xml index 5a302f7a..517fb00b 100644 --- a/security/pom.xml +++ b/security/pom.xml @@ -9,93 +9,27 @@ 4.0.0 org.wamblee wamblee-security - jar + pom /security http://wamblee.org - - - - org.wamblee - wamblee-support-general - 0.2.2 - - - org.wamblee - wamblee-support-general - test-jar - 0.2.2 - - - org.wamblee - wamblee-test-enterprise - 0.2.2 - test - - - org.wamblee - wamblee-system-spring - 0.2.2 - - - org.wamblee - wamblee-system-spring - test-jar - 0.2.2 - - - org.wamblee - wamblee-system-general - test-jar - 0.2.2 - - - org.wamblee - wamblee-support-spring - 0.2.2 - - - org.wamblee - wamblee-support-spring - test-jar - 0.2.2 - - - - org.wamblee - wamblee-hibernate-jpa - 0.2.2 - - - - commons-codec - commons-codec - - - - org.springframework - spring-beans - - - org.springframework - spring-hibernate3 - - - org.hibernate - hibernate - - - - - org.springframework - spring-aop - - - javax.transaction - transaction-api - 1.1 - test - - - + + impl + + + + + all + + + !performRelease + + + + jpatest + + + + + diff --git a/security/src/main/java/org/wamblee/security/authorization/AuthorizationService.java b/security/src/main/java/org/wamblee/security/authorization/AuthorizationService.java deleted file mode 100644 index 01150622..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/AuthorizationService.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import org.wamblee.persistence.Persistent; - -/** - * Service to determine if access to a certain resource is allowed. - * - * @author Erik Brakkee - */ -public interface AuthorizationService extends Persistent { - - /** - * Checks whether an operation is allowed on a resource. - * @param aResource Resource. - * @param aOperation Operation. - * @return Checks whether the operation is allowed on a resource. - */ - boolean isAllowed(Object aResource, Operation aOperation); - - /** - * Same as {@link #isAllowed(Object, Operation)} but throws a - * RuntimeException in case access is not allowed. - * @param aResource Resource to check. - * @param aOperation Operation to perform. - * @return Resource that was checked. - */ - T check(T aResource, Operation aOperation); - - /** - * Gets the authorization rules. - * @return Rules. - */ - AuthorizationRule[] getRules(); - - /** - * Appends a new authorization rule to the end. - * @param aRule Rule to append. - */ - void appendRule(AuthorizationRule aRule); - - /** - * Removes a rule. - * @param aRule Index of the rule to remove. - */ - void removeRule(int aIndex); - - /** - * Inserts a rule. - * @param aIndex Index of the position of the rule after insertion. - * @param aRule Rule to insert. - */ - void insertRuleAfter(int aIndex, AuthorizationRule aRule); -} diff --git a/security/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java b/security/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java deleted file mode 100644 index b3dc524d..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/DefaultAuthorizationService.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import java.util.ArrayList; -import java.util.List; - -import org.wamblee.persistence.AbstractPersistent; -import org.wamblee.usermgt.User; -import org.wamblee.usermgt.UserAccessor; - -/** - * Default implementation of an authorization service. - * To determine whether access to a resource is allowed, the service consults a number - * of authorization rules in a fixed order. The first rule that gives a result GRANTED or - * DENIED determines the result of the evaluation. Rules that return any other result are - * ignoed. If none of the rules match, than access is denied. - * - * @author Erik Brakkee - */ -public class DefaultAuthorizationService extends AbstractPersistent implements AuthorizationService { - - /** - * List of ordered authorization rules. - */ - private List _rules; - - /** - * User accessor used to obtain the current user. - */ - private UserAccessor _userAccessor; - - /** - * Name for this instance of the authorization service. - */ - private String _name; - - /** - * Constructs the service. - * @param aAccessor User accessor. - * @param aName Name of this instance of the service. - */ - public DefaultAuthorizationService(UserAccessor aAccessor, String aName) { - _rules = new ArrayList(); - _userAccessor = aAccessor; - _name = aName; - } - - /** - * Constructs the authorization service. - */ - public DefaultAuthorizationService() { - _rules = new ArrayList(); - _userAccessor = null; - _name = null; - } - - /** - * Sets the user accessor. - * @param aUserAccessor User accessor. - */ - public void setUserAccessor(UserAccessor aUserAccessor) { - _userAccessor = aUserAccessor; - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#isAllowed(java.lang.Object, org.wamblee.security.authorization.Operation) - */ - public boolean isAllowed(Object aResource, Operation aOperation) { - User user = _userAccessor.getCurrentUser(); - for (AuthorizationRule rule: _rules) { - switch ( rule.isAllowed(aResource, aOperation, user)) { - case DENIED: { return false; } - case GRANTED: { return true; } - } - } - return false; - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#check(T, org.wamblee.security.authorization.Operation) - */ - public T check(T aResource, Operation aOperation) { - if ( !isAllowed(aResource, aOperation)) { - throw new AuthorizationException(aResource, aOperation); - } - return aResource; - } - - protected String getName() { - return _name; - } - - public void setName(String aName) { - _name = aName; - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#getRules() - */ - public AuthorizationRule[] getRules() { - return _rules.toArray(new AuthorizationRule[0]); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#appendRule(org.wamblee.security.authorization.AuthorizationRule) - */ - public void appendRule(AuthorizationRule aRule) { - _rules.add(aRule); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#insertRuleAfter(int, org.wamblee.security.authorization.AuthorizationRule) - */ - public void insertRuleAfter(int aIndex, AuthorizationRule aRule) { - _rules.add(aIndex, aRule); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#removeRule(int) - */ - public void removeRule(int aIndex) { - _rules.remove(aIndex); - } - - /** - * For OR mapping. - * @return The rules. - */ - protected List getMappedRules() { - return _rules; - } - - /** - * For OR mapping. - * @param aRules The rules. - */ - protected void setMappedRules(List aRules) { - _rules = aRules; - } -} diff --git a/security/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java b/security/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java deleted file mode 100644 index 0a240923..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/DefaultOperationRegistry.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import java.util.ArrayList; -import java.util.Map; -import java.util.TreeMap; - -/** - * Operation registry implementation. - * This implementation ignores the distinction between different types of resources - * and simply assumes that every operation is applicable to every type of resource. - * - * @author Erik Brakkee - */ -public class DefaultOperationRegistry implements OperationRegistry { - - private Map _operations; - - public DefaultOperationRegistry(Operation[] aOperations) { - _operations = new TreeMap(); - for (Operation operation: aOperations) { - _operations.put(operation.getName(), operation); - } - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.OperationRegistry#getOperations(java.lang.Class) - */ - public Operation[] getOperations(Class aResourceClass) { - return _operations.values().toArray(new Operation[0]); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.OperationRegistry#encode(org.wamblee.security.authorization.Operation[]) - */ - public String encode(Operation[] aOperations) { - StringBuffer buffer = new StringBuffer(); - for (Operation operation: aOperations) { - if ( buffer.length() > 0 ) { - buffer.append(','); - } - buffer.append(operation.getName()); - } - return buffer.toString(); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.OperationRegistry#decode(java.lang.Class, java.lang.String) - */ - public Operation[] decode(Class aResourceClass, String aOperationsString) { - return decode(aOperationsString); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.OperationRegistry#decode(java.lang.String) - */ - public Operation[] decode(String aOperationsString) { - if ( aOperationsString.length() == 0 ) { - return new Operation[0]; - } - String[] names = aOperationsString.split(","); - ArrayList result = new ArrayList(); - for (String name: names) { - Operation operation = _operations.get(name); - if ( operation == null ) { - throw new IllegalArgumentException("Unknown operation '" + name + "'"); - } - result.add(operation); - } - return result.toArray(new Operation[0]); - } - -} diff --git a/security/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java b/security/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java deleted file mode 100644 index 8949fc76..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/GroupUserCondition.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import org.wamblee.persistence.AbstractPersistent; -import org.wamblee.usermgt.User; - -/** - * Checks if a user against a specific group. - * - * @author Erik Brakkee - */ -public class GroupUserCondition extends AbstractPersistent implements UserCondition { - - /** - * Group the user must be in. - */ - private String _group; - - /** - * Constructs the condition. - * @param aGroup Group the user must be in. - */ - public GroupUserCondition(String aGroup) { - _group = aGroup; - } - - /** - * For OR mapping. - * - */ - protected GroupUserCondition() { - _group = null; - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.UserCondition#matches(org.wamblee.usermgt.UserAccessor) - */ - public boolean matches(User aUser) { - return aUser.isInGroup(_group); - } - - /** - * @return Returns the _group. - */ - protected String getGroup() { - return _group; - } - - /** - * @param _group The _group to set. - */ - protected void setGroup(String aGroup) { - _group = aGroup; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "GroupUserCondition(group=" + _group + ")"; - } - -} diff --git a/security/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java b/security/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java deleted file mode 100644 index 5c373e84..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/RegexpPathCondition.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import org.wamblee.persistence.AbstractPersistent; - -/** - * Condition to check whether a path matches a given regula expression. - * - * @author Erik Brakkee - */ -public class RegexpPathCondition extends AbstractPersistent implements PathCondition { - - /** - * String the path must start with. - */ - private String _pattern; - - /** - * Constructs the condition. - * @param aPattern String the path must start with. - */ - public RegexpPathCondition(String aPattern) { - _pattern = aPattern; - } - - /** - * For OR mapping. - * - */ - protected RegexpPathCondition() { - _pattern = null; - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.PathCondition#matches(java.lang.String) - */ - public boolean matches(String aPath) { - return aPath.matches(_pattern); - } - - /** - * @return Returns the _path. - */ - protected String getPattern() { - return _pattern; - } - - /** - * @param aPattern The _path to set. - */ - protected void setPattern(String aPattern) { - _pattern = aPattern; - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "RegexpCondition(pattern = '" + _pattern + "')"; - } -} diff --git a/security/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java b/security/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java deleted file mode 100644 index 0d22d1ca..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/UrlAuthorizationRule.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import static org.wamblee.security.authorization.AuthorizationResult.DENIED; -import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; -import static org.wamblee.security.authorization.AuthorizationResult.UNDECIDED; -import static org.wamblee.security.authorization.AuthorizationResult.UNSUPPORTED_RESOURCE; - -import org.apache.log4j.Logger; -import org.wamblee.persistence.AbstractPersistent; -import org.wamblee.usermgt.User; - -/** - * Utility base class for implementation of authentication rules based on the - *
    - *
  • The path of the resource. To obtain the path of a resource, subclasses - * must implement {@link #getResourcePath(Object)}. - * Whether a path is appropriate is determined by a - * {@link org.wamblee.security.authorization.PathCondition}. - *
  • - *
  • The user identity with which the resource is accessed. - * Whether a user is appropriate is determined by - * a {@link org.wamblee.security.authorization.UserCondition}. - *
  • - *
  • The operation that is requested. - * Whether the operation is appropriate is determined by a - * {@link org.wamblee.security.authorization.OperationCondition}. - *
  • - *
- * - * In case all three conditions match, the condition returns the configured - * result passed at construction (GRANTED or DENIED). If the resource is not - * of the specified type, the result is UNSUPPORTED_RESOURCE, otherwise, the - * result is UNDECIDED. - */ -public abstract class UrlAuthorizationRule extends AbstractPersistent implements AuthorizationRule { - - private static final Logger LOGGER = Logger.getLogger(UrlAuthorizationRule.class); - - /** - * Result that the rule will return in case there is a match. - */ - private AuthorizationResult _result; - - /** - * A condition which specifies which users the rule is for. - */ - private UserCondition _userCondition; - - /** - * Path the rule applies for. - */ - private PathCondition _pathCondition; - - /** - * Resource class that the rule applies for. - */ - private Class _resourceClass; - - /** - * Operation that this rule is for. - */ - private OperationCondition _operationCondition; - - /** - * Constructs an authorization rule. - * IF the group and path match, then the provided result will be returned. - * @param aResult Result of the authorization when the path and group match. - * @param aUserCondition Condition to match users. - * @param aPathCondition Condition to match paths with. - * @param aResourceClass Supported resource class this is for. - * @param aOperationCondition Condition to match the operation with. - */ - protected UrlAuthorizationRule(AuthorizationResult aResult, UserCondition aUserCondition, - PathCondition aPathCondition, Class aResourceClass, OperationCondition aOperationCondition) { - if ( !aResult.equals(GRANTED) && !aResult.equals(DENIED)) { - throw new IllegalArgumentException("Only GRANTED or DENIED may be used: " + aResult); - } - _result = aResult; - _userCondition = aUserCondition; - _pathCondition = aPathCondition; - _resourceClass = aResourceClass; - _operationCondition = aOperationCondition; - } - - /** - * For OR mapping. - * - */ - protected UrlAuthorizationRule(Class aResourceClass) { - _result = null; - _userCondition = null; - _pathCondition = null; - _resourceClass = aResourceClass; - _operationCondition = null; - } - - /** - * For OR mapping. - * - */ - protected UrlAuthorizationRule() { - _result = null; - _userCondition = null; - _pathCondition = null; - _resourceClass = null; - _operationCondition = null; - } - - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationRule#getSupportedTypes() - */ - public Class[] getSupportedTypes() { - return new Class[] { _resourceClass }; - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationRule#isAllowed(java.lang.Object, - * org.wamblee.security.authorization.Operation) - */ - public AuthorizationResult isAllowed(Object aResource, Operation anOperation, User aUser) { - if ( ! _resourceClass.isInstance(aResource)) { - return UNSUPPORTED_RESOURCE; - } - String path = getResourcePath(aResource); - return isAllowed(path, anOperation, aUser); - } - - /** - * Determines if the operation is allowed on the resource. - * @param aPath Path of the resource. - * @param aOperation Operation to be done. - * @param aUser Currently logged in user or null if no user is logged in. - * @return Authorization result, - */ - protected AuthorizationResult isAllowed(String aPath, Operation aOperation, User aUser) { - if ( ! _pathCondition.matches(aPath) ) { - return UNDECIDED; - } - if ( !_operationCondition.matches(aOperation) ) { - return UNDECIDED; - } - if ( !_userCondition.matches(aUser)) { - return UNDECIDED; - } - return _result; - } - - /** - * Gets the path of the resource. - * @param aResource Resource, guaranteed to be an instance of - * {@link #_resourceClass}. - * @return Path of the resource. - */ - protected abstract String getResourcePath(Object aResource); - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "UrlAUthorizationRule(result = " + _result + - ", pathCondition = " + _pathCondition + - ", userCondition = " + _userCondition + - ", resourceClass = " + _resourceClass + ")"; - } - - /** - * Gets the authorization result for OR mapping. - * @return Result. - */ - protected String getAuthorizationResultString() { - if ( _result == null ) { - return null; - } - return _result.toString(); - } - - /** - * Sets the authorization result, for OR mapping. - * @param aResult Result. - */ - protected void setAuthorizationResultString(String aResult) { - _result = AuthorizationResult.valueOf(aResult); - } - - protected String getResourceClassName() { - if ( _resourceClass == null ) { - return ""; - } - return _resourceClass.getName(); - } - - protected void setResourceClassName(String aResourceClass) { - try { - _resourceClass = Class.forName(aResourceClass); - } catch (ClassNotFoundException e) { - LOGGER.error("Cannot find resource class '" + aResourceClass + "'", e); - throw new IllegalArgumentException(e.getMessage(), e); - } - } - - /** - * @return Returns the _operationCondition. - */ - public OperationCondition getOperationCondition() { - return _operationCondition; - } - - /** - * @param aOperationCondition The _operationCondition to set. - */ - protected void setOperationCondition(OperationCondition aOperationCondition) { - _operationCondition = aOperationCondition; - } - - /** - * @return Returns the _pathCondition. - */ - public PathCondition getPathCondition() { - return _pathCondition; - } - - /** - * @param aPathCondition The _pathCondition to set. - */ - protected void setPathCondition(PathCondition aPathCondition) { - _pathCondition = aPathCondition; - } - - /** - * @return Returns the _userCondition. - */ - public UserCondition getUserCondition() { - return _userCondition; - } - - /** - * @param aUserCondition The _userCondition to set. - */ - protected void setUserCondition(UserCondition aUserCondition) { - _userCondition = aUserCondition; - } -} diff --git a/security/src/main/java/org/wamblee/security/authorization/hibernate/AuthorizationMappingFiles.java b/security/src/main/java/org/wamblee/security/authorization/hibernate/AuthorizationMappingFiles.java deleted file mode 100644 index 6bd87f6c..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/hibernate/AuthorizationMappingFiles.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization.hibernate; - -import org.wamblee.usermgt.hibernate.UsermgtHibernateMappingFiles; - -/** - * Mapping files for authorization. - * - * @author Erik Brakkee - */ -public class AuthorizationMappingFiles extends UsermgtHibernateMappingFiles { - - public AuthorizationMappingFiles() { - super(new String[]{ "hbm/AuthorizationRule.hbm.xml", "hbm/UserCondition.hbm.xml", - "hbm/AuthorizationService.hbm.xml", "hbm/OperationCondition.hbm.xml", "hbm/PathCondition.hbm.xml", - "hbm/TestAuthorizationRule.hbm.xml" }); - } -} diff --git a/security/src/main/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationService.java b/security/src/main/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationService.java deleted file mode 100644 index dfe2439c..00000000 --- a/security/src/main/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationService.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization.hibernate; - -import java.util.List; - -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.wamblee.persistence.AbstractPersistent; -import org.wamblee.persistence.hibernate.HibernateSupport; -import org.wamblee.security.authorization.AuthorizationRule; -import org.wamblee.security.authorization.AuthorizationService; -import org.wamblee.security.authorization.DefaultAuthorizationService; -import org.wamblee.security.authorization.Operation; -import org.wamblee.usermgt.UserAccessor; - -/** - * Authorization service with persistent storage. - * This is a wrapper for {@link org.wamblee.security.authorization.DefaultAuthorizationService} - * which refreshes the state of the service at certain time intervals. - * - * @author Erik Brakkee - */ -public class PersistentAuthorizationService extends AbstractPersistent - implements AuthorizationService { - - /** - * Name of query to find the service by name. - */ - private static final String FIND_QUERY = "findAuthorizationServiceByName"; - - /** - * Name of the query parameter for the service name. - */ - private static final String NAME_PARAM = "name"; - - /** - * Authorization service to use. - */ - private DefaultAuthorizationService _service; - - /** - * Hibernate template to use. - */ - private HibernateTemplate _template; - - /** - * User accessor. - */ - private UserAccessor _userAccessor; - - /** - * Name of the service. - */ - private String _name; - - /** - * Refresh interval in milliseconds. - */ - private final long _refreshInterval; - - /** - * Last refresh time. - */ - private long _lastRefreshTime; - - /** - * Constructs the persistent service. - * - * @param aName - * Name of the service. - * @param aTemplate - * Hibernate template for hibernate usage. - * @param aAccessor - * User accessor. - * @param aRefresh - * Whether or not to refresh the state of the service at the - * start of every operation. - */ - public PersistentAuthorizationService(String aName, - HibernateTemplate aTemplate, UserAccessor aAccessor, - long aRefreshInterval) { - _template = aTemplate; - _refreshInterval = aRefreshInterval; - _lastRefreshTime = System.currentTimeMillis(); - _userAccessor = aAccessor; - _name = aName; - } - - /** - * Initialize service if needed. - */ - private void initialize() { - if (_service == null) { - List result = _template - .findByNamedQueryAndNamedParam(FIND_QUERY, NAME_PARAM, - _name); - - if (result.size() > 1) { - throw new IllegalArgumentException( - "Returned more than one service for name '" + _name - + "' (" + result.size() + ")"); - } - - if (result.size() == 0) { - _service = new DefaultAuthorizationService(_userAccessor, _name); - _template.persist(_service); - } else { - _service = result.get(0); - _service.setUserAccessor(_userAccessor); - } - } - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationService#isAllowed(java.lang.Object, - * org.wamblee.security.authorization.Operation) - */ - public boolean isAllowed(Object aResource, Operation aOperation) { - initialize(); - refresh(); - return _service.isAllowed(aResource, aOperation); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.AuthorizationService#check(T, org.wamblee.security.authorization.Operation) - */ - public T check(T aResource, Operation aOperation) { - initialize(); - refresh(); - return _service.check(aResource, aOperation); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationService#getRules() - */ - public AuthorizationRule[] getRules() { - initialize(); - refresh(); - return _service.getRules(); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationService#appendRule(org.wamblee.security.authorization.AuthorizationRule) - */ - public void appendRule(AuthorizationRule aRule) { - initialize(); - refresh(); - _service.appendRule(aRule); - save(); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationService#removeRule(int) - */ - public void removeRule(int aIndex) { - initialize(); - refresh(); - _service.removeRule(aIndex); - save(); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.security.authorization.AuthorizationService#insertRuleAfter(int, - * org.wamblee.security.authorization.AuthorizationRule) - */ - public void insertRuleAfter(int aIndex, AuthorizationRule aRule) { - initialize(); - refresh(); - _service.insertRuleAfter(aIndex, aRule); - save(); - } - - /** - * Refreshes the state of the service through hibernate. - * - */ - private synchronized void refresh() { - long time = System.currentTimeMillis(); - if ( time - _lastRefreshTime > _refreshInterval ) { - _template.refresh(_service); - _lastRefreshTime = time; - } - } - - /** - * Saves any changes to the service state if necessary. - */ - private void save() { - HibernateSupport.merge(_template, _service); - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/Group.java b/security/src/main/java/org/wamblee/usermgt/Group.java deleted file mode 100644 index 1e7a3f59..00000000 --- a/security/src/main/java/org/wamblee/usermgt/Group.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.io.Serializable; - -import org.wamblee.persistence.AbstractPersistent; - -/** - * Represents a group. - * - * @author Erik Brakkee - */ -public class Group extends AbstractPersistent implements Serializable, Comparable { - - /** - * Group name. - */ - private String _name; - - /** - * Constructs the group. - * @param aName - */ - Group(String aName) { - super(); - _name = aName; - } - - public Group(Group aGroup) { - super(aGroup); - _name = aGroup._name; - } - - protected Group() { - super(); - _name = null; - } - - /** - * Gets the name of the group. - * @return Group name. - */ - public String getName() { - return _name; - } - - /** - * Sets the group name. - * @param aName Group name. - */ - void setName(String aName) { - _name = aName; - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object aGroup) { - if ( !( aGroup instanceof Group )) { - return false; - } - return _name.equals(((Group)aGroup)._name); - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return _name.hashCode(); - } - - /* (non-Javadoc) - * @see java.lang.Comparable#compareTo(T) - */ - public int compareTo(Object aGroup) { - return _name.compareTo(((Group)aGroup)._name); - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return "Group(pk = " + getPrimaryKey() + ", name=" + _name + ")"; - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/User.java b/security/src/main/java/org/wamblee/usermgt/User.java deleted file mode 100644 index f239c141..00000000 --- a/security/src/main/java/org/wamblee/usermgt/User.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.io.Serializable; -import java.util.Set; -import java.util.TreeSet; - -import org.wamblee.persistence.AbstractPersistent; -import org.wamblee.security.encryption.MessageDigester; -import org.wamblee.usermgt.UserMgtException.Reason; - -/** - * Represents a user. - * The methods for managing the groups of the user have package scope. - * Managing the groups of the user should be done through the - * {@link org.wamblee.usermgt.UserAdministration} interface. - */ -public class User extends AbstractPersistent implements Serializable, Comparable { - - /** - * User name. - */ - private String _name; - - /** - * Password. - */ - private String _password; - - /** - * Groups the user belongs to. - */ - private Set _groups; - - /** - * Password validator. - */ - private NameValidator _passwordValidator; - - /** - * Password encoder. - */ - private MessageDigester _passwordEncoder; - - /** - * Constructs the user. - * @param aName User name. - * @param aPassword Password. - * @param aGroup Group the user belongs to. - */ - User(String aName, String aPassword, Group aGroup, NameValidator aPasswordValidator, - MessageDigester aPasswordEncoder) throws UserMgtException { - super(); - _name = aName; - aPasswordValidator.validate(aPassword); - _password = aPasswordEncoder.hash(aPassword); - _groups = new TreeSet(); - _groups.add(aGroup); - _passwordValidator = aPasswordValidator; - _passwordEncoder = aPasswordEncoder; - } - - public User(User aUser) { - super(aUser); - _name = aUser._name; - _password = aUser._password; - _groups = new TreeSet(); - for (Group group: aUser._groups) { - _groups.add(new Group(group)); - } - _passwordValidator = aUser._passwordValidator; - _passwordEncoder = aUser._passwordEncoder; - } - - User() { - super(); - _name = null; - _password = null; - _groups = null; - _passwordValidator = null; - _passwordEncoder = null; - } - - /** - * Sets the password validator. - * @param aPasswordValidator Validator. - */ - public void setPasswordValidator(NameValidator aPasswordValidator) { - _passwordValidator = aPasswordValidator; - } - - /** - * Sets the password encoder. - * @param aPasswordEncoder Encoder. - */ - public void setPasswordEncoder(MessageDigester aPasswordEncoder) { - _passwordEncoder = aPasswordEncoder; - } - - /** - * @return Returns the _password. - */ - String getPassword() { - return _password; - } - - /** - * Checks the password. - * @param aPassword Password to check. - * @throws UserMgtException In case the password is incorrect. - */ - public void checkPassword(String aPassword) throws UserMgtException { - String encoded = _passwordEncoder.hash(aPassword); - if ( !_password.equals(encoded) ) { - throw new UserMgtException(Reason.INVALID_PASSWORD, this); - } - } - - /** - * Changes the password. - * @param aOldPassword Old password. - * @param aNewPassword New password. - * @throws UserMgtException In case the old password is incorrect. - */ - public void changePassword(String aOldPassword, String aNewPassword) throws UserMgtException { - checkPassword(aOldPassword); - _passwordValidator.validate(aNewPassword); - setPassword(aNewPassword); - } - - /** - * @param aPassword - * The password to set. - */ - public void setPassword(String aPassword) throws UserMgtException { - _passwordValidator.validate(aPassword); - _password = _passwordEncoder.hash(aPassword); - } - - /** - * For OR mapping. - * @return Password. - */ - protected String getPasswordString() { - return _password; - } - - /** - * For OR mapping. - * @param aPassword Password. - */ - protected void setPasswordString(String aPassword) { - _password = aPassword; - } - - /** - * @return Returns the _user. - */ - public String getName() { - return _name; - } - - /** - * @param aName - * The username to set. - */ - void setName(String aName) { - _name = aName; - } - - /** - * Gets the groups the user belongs to. - * @return Groups. - */ - public Set getGroups() { - Set result = new TreeSet(); - result.addAll(_groups); - return result; - } - - /** - * Checks whether the user belongs to the given group. - * @param aGroup Group. - * @return True if the user belongs to the group. - */ - public boolean isInGroup(Group aGroup) { - return _groups.contains(aGroup); - } - - /** - * Checks whether the user belongs to the given group. - * @param aGroup Group. - * @return True if the user belongs to the group. - */ - public boolean isInGroup(String aGroup) { - return _groups.contains(new Group(aGroup)); - } - - /** - * Gets the group set. For OR mapping. - * @return set of groups. - */ - Set getGroupSet() { - return _groups; - } - - /** - * Sets the groups the user belongs to, for OR mapping. - * @param aGroups Groups. - */ - void setGroupSet(Set aGroups) { - _groups = aGroups; - } - - /** - * Adds the user to a group. - * @param aGroup Group to add the user to. - * @throws UserMgtException In case the user already belongs to the group. - */ - void addGroup(Group aGroup) throws UserMgtException { - if (_groups.contains(aGroup)) { - throw new UserMgtException(Reason.USER_ALREADY_IN_GROUP, aGroup); - } - _groups.add(aGroup); - } - - /** - * Removes the user from a group. - * @param aGroup Group. - * @throws UserMgtException In case the user does not belong to the group. - */ - void removeGroup(Group aGroup) throws UserMgtException { - if (!_groups.contains(aGroup)) { - throw new UserMgtException(Reason.USER_NOT_IN_GROUP, this, aGroup); - } - if ( _groups.size() == 1 ) { - throw new UserMgtException(Reason.USER_MUST_BE_IN_A_GROUP, this, aGroup); - } - _groups.remove(aGroup); - } - - /* (non-Javadoc) - * @see java.lang.Object#equals(java.lang.Object) - */ - @Override - public boolean equals(Object aUser) { - if ( !(aUser instanceof User)) { - return false; - } - User user = (User)aUser; - return _name.equals(user._name); - } - - /* (non-Javadoc) - * @see java.lang.Object#hashCode() - */ - @Override - public int hashCode() { - return _name.hashCode(); - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - String result = "User(name=" + _name + ", password=" + _password; - for (Group group: _groups) { - result += ", group=" + group; - } - return result + ")"; - } - - /* (non-Javadoc) - * @see java.lang.Comparable#compareTo(T) - */ - public int compareTo(Object aUser) { - return _name.compareTo(((User)aUser)._name); - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/UserAdministration.java b/security/src/main/java/org/wamblee/usermgt/UserAdministration.java deleted file mode 100644 index 1ce6fbfa..00000000 --- a/security/src/main/java/org/wamblee/usermgt/UserAdministration.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.util.Set; - -/** - * Interface for user administration. Manages the users and groups. - * - * @author Erik Brakkee - */ -public interface UserAdministration { - - /** - * Creates a new user. - * @param aUser Username. - * @param aPassword Password. - * @param aGroup Group. - * @return User. - * @throws UserMgtException In case there is a conflict with an existing user. - */ - User createUser(String aUser, String aPassword, Group aGroup) throws UserMgtException; - - /** - * Creates a new group. - * @param aName Group name. - * @return Group - * @throws UserMgtException In case there is a conflict with an existing group. - */ - Group createGroup(String aName) throws UserMgtException; - - /** - * @return Number of users. - */ - int getUserCount(); - - /** - * @return Number of groups. - */ - int getGroupCount(); - - /** - * Must be called when the user is modified. - * @param aUser User. - */ - void userModified(User aUser); - - /** - * Must be called when the group is modified. - * @param aGroup Group. - */ - void groupModified(Group aGroup); - - /** - * Gets the user for a given name. - * @param aName User name. - * @return User or null if not found. - */ - User getUser(String aName); - - /** - * Gets the group for a given group name. - * @param aName Group name. - * @return Group or null if not found. - */ - Group getGroup(String aName); - - /** - * Get the users. - * @return All known users. - */ - Set getUsers(); - - /** - * Gets the users for a given group. - * @param aGroup Group. - * @return Set of users (always non-null). - */ - Set getUsers(Group aGroup); - - /** - * Gets all known groups. - * @return Groups. - */ - Set getGroups(); - - /** - * Renames a user. - * @param aUser User object for which user name must be changed. - * @param aUserName New user name. - * @throws UserMgtException In case the user is not known or the new user - * name is already in use by another user. - */ - void renameUser(User aUser, String aUserName) throws UserMgtException; - - /** - * Renames a group. - * @param aGroup Group to rename. - * @param aGroupName New name for the group. - * @throws UserMgtException In case the new group name is already used by - * another group of if the existing group is unknown. - */ - void renameGroup(Group aGroup, String aGroupName) throws UserMgtException; - - /** - * Removes the user. - * @param aUser User to remove. - * @throws UserMgtException In case the user does not exist. - */ - void removeUser(User aUser) throws UserMgtException; - - /** - * Removes the group. - * @param aGroup Group to remove. - * @throws UserMgtException In case there are still users that are in the given group. - */ - void removeGroup(Group aGroup) throws UserMgtException; - - /** - * Adds a user to a group. - * @param aUser User. - * @param aGroup Group. - * @throws UserMgtException In case the user or group or not known or if the user - * is already part of the group. - */ - void addUserToGroup(User aUser, Group aGroup) throws UserMgtException; - - /** - * Removes a user from a group. - * @param aUser User - * @param aGroup Group - * @throws UserMgtException In case the user or group are unknown or if the user - * is not part of the group. - */ - void removeUserFromGroup(User aUser, Group aGroup) throws UserMgtException; -} - diff --git a/security/src/main/java/org/wamblee/usermgt/UserGroupRepositoryComponent.java b/security/src/main/java/org/wamblee/usermgt/UserGroupRepositoryComponent.java deleted file mode 100644 index fb3378cf..00000000 --- a/security/src/main/java/org/wamblee/usermgt/UserGroupRepositoryComponent.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeMap; - -import net.sf.ehcache.Ehcache; - -import org.hibernate.SessionFactory; -import org.wamblee.cache.EhCache; -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; -import org.wamblee.system.core.RequiredInterface; -import org.wamblee.system.spring.SpringComponent; - -public class UserGroupRepositoryComponent extends SpringComponent { - - public UserGroupRepositoryComponent(String aName) { - super(aName, new String[] { "spring/org.wamblee.security.usermgt-repositories.xml" } , - createProvided(), createRequired()); - - } - - private static Map createRequired() { - Map required = new HashMap(); - required.put(new DefaultRequiredInterface("sessionFactory", SessionFactory.class), "sessionFactory"); - return required; - } - - private static Map createProvided() { - Map provided = new HashMap(); - provided.put("userCache", new DefaultProvidedInterface("cache", EhCache.class)); - provided.put(UserSet.class.getName(), new DefaultProvidedInterface("userset", UserSet.class)); - provided.put(GroupSet.class.getName(), new DefaultProvidedInterface("groupset", GroupSet.class)); - return provided; - } - - -} diff --git a/security/src/main/java/org/wamblee/usermgt/UserSet.java b/security/src/main/java/org/wamblee/usermgt/UserSet.java deleted file mode 100644 index ac3f5a70..00000000 --- a/security/src/main/java/org/wamblee/usermgt/UserSet.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.util.Set; - -/** - * Represents a set of users. - * Typical implementations would be an implementation based on a static configuration file or - * an implementation backed by a database. - * - * @author Erik Brakkee - */ -public interface UserSet { - - /** - * Creates a user. - * @param aUsername User name. - * @param aPassword Password. - * @param aGroup Group. - * @return New user. - * @throws UserMgtException In case the user cannot be created. - */ - User createUser(String aUsername, String aPassword, Group aGroup) throws UserMgtException; - - /** - * Must be called whenever a user object has been modified to notify the - * user set. - * @param aUser Modified user. - */ - void userModified(User aUser); - - /** - * Finds user. - * @param aName Username. - * @return User or null if not found. - */ - User find(String aName); - - /** - * Checks if a user exists. - * @param aUser User. - * @return True iff the user exists. - */ - boolean contains(User aUser); - - /** - * Adds a user. If the user already exists, the user details are updated with that - * of the specified user object. - * @param aUser User to add. - */ - boolean add(User aUser); - - /** - * Removes a user. If the user does not exist, nothing happens. - * @param aUser - */ - boolean remove(User aUser); - - /** - * Lists the current users. - * @return Users. - */ - Set list(); - - /** - * Lists the users belonging to a particular group. - * @param aGroup Group. - * @return Groups. - */ - Set list(Group aGroup); - - /** - * - * @return The number of users. - */ - int size(); -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationComponent.java b/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationComponent.java deleted file mode 100644 index 150a8447..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationComponent.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.io.IOException; - -import javax.sql.DataSource; - -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.transaction.PlatformTransactionManager; -import org.wamblee.cache.EhCache; -import org.wamblee.security.authorization.AuthorizationService; -import org.wamblee.security.authorization.hibernate.AuthorizationMappingFiles; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.components.ORMappingConfig; -import org.wamblee.system.core.Component; -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.HibernateComponent; -import org.wamblee.usermgt.UserAccessor; -import org.wamblee.usermgt.UserAdministration; -import org.wamblee.usermgt.UserGroupRepositoryComponent; - -public class AuthorizationComponent extends DefaultContainer { - - private ProvidedInterface TRANSACTION_MGR = new DefaultProvidedInterface( - "transactionManager", PlatformTransactionManager.class); - private ProvidedInterface HIBERNATE_TEMPLATE = new DefaultProvidedInterface( - "hibernateTemplate", HibernateTemplate.class); - private ProvidedInterface AUTHORIZATION_SERVICE = new DefaultProvidedInterface( - "authorizationService", AuthorizationService.class); - - public AuthorizationComponent(String aName, boolean aExposeInternals) - throws IOException { - super(aName); - - ObjectConfiguration authConfig = new ObjectConfiguration(AuthorizationMappingFiles.class); - authConfig.getSetterConfig().initAllSetters(); - addComponent("mappingFiles", new AuthorizationMappingFiles(), authConfig); - - Component hibernate = new HibernateComponent("hibernate"); - addComponent(hibernate); - - Component authorization = new AuthorizationLightComponent("authorization"); - addComponent(authorization); - - addRequiredInterface(new DefaultRequiredInterface("datasource", DataSource.class)); - addRequiredInterface(new DefaultRequiredInterface("userAccessor", - UserAccessor.class)); - addRequiredInterface(new DefaultRequiredInterface("ormconfig", ORMappingConfig.class)); - - if (aExposeInternals) { - addProvidedInterface(TRANSACTION_MGR); - addProvidedInterface(HIBERNATE_TEMPLATE); - } - addProvidedInterface(AUTHORIZATION_SERVICE); - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationLightComponent.java b/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationLightComponent.java deleted file mode 100644 index e7b0c963..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/AuthorizationLightComponent.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.util.HashMap; -import java.util.Map; - -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.wamblee.security.authorization.AuthorizationService; -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; -import org.wamblee.system.core.RequiredInterface; -import org.wamblee.system.spring.SpringComponent; -import org.wamblee.usermgt.GroupSet; -import org.wamblee.usermgt.UserAccessor; -import org.wamblee.usermgt.UserAdministration; -import org.wamblee.usermgt.UserSet; - -/** - * Light version of the user administration component that requires external - * datasource, and userset and group set components, as well as an external - * hibernate session factory. - * - * @author Erik Brakkee - * - */ -public class AuthorizationLightComponent extends SpringComponent { - - public AuthorizationLightComponent(String aName) { - super( - aName, - new String[] { "spring/org.wamblee.security.authorization.xml" }, - createProvided(), createRequired()); - } - - private static Map createRequired() { - Map required = new HashMap(); - required.put(new DefaultRequiredInterface("userArccessor", - UserAccessor.class), UserAccessor.class.getName()); - required.put(new DefaultRequiredInterface("hibernateTemplate", - HibernateTemplate.class), HibernateTemplate.class.getName()); - return required; - } - - private static Map createProvided() { - Map provided = new HashMap(); - provided.put(AuthorizationService.class.getName(), - new DefaultProvidedInterface(AuthorizationService.class - .getName(), AuthorizationService.class)); - return provided; - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/HibernateGroupSet.java b/security/src/main/java/org/wamblee/usermgt/hibernate/HibernateGroupSet.java deleted file mode 100644 index 957ee44d..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/HibernateGroupSet.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.util.List; -import java.util.Set; -import java.util.TreeSet; - -import org.wamblee.persistence.hibernate.HibernateSupport; -import org.wamblee.usermgt.Group; -import org.wamblee.usermgt.GroupSet; - -/** - * Set of groups backed by the database. - * - * @author Erik Brakkee - */ -public class HibernateGroupSet extends HibernateSupport implements GroupSet { - - - private static final String QUERY_FIND_BY_NAME = "findGroupByName"; - - private static final String PARAM_NAME = "name"; - - private static final String QUERY_COUNT_GROUPS = "countGroups"; - - public HibernateGroupSet() { - // Empty - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#groupModified(org.wamblee.usermgt.Group) - */ - public void groupModified(Group aGroup) { - assert aGroup.getPrimaryKey() != null; - super.merge(aGroup); - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#find(java.lang.String) - */ - public Group find(String aName) { - List list = getHibernateTemplate().findByNamedQueryAndNamedParam(QUERY_FIND_BY_NAME, PARAM_NAME, aName); - if ( list.size() > 1 ) { - throw new RuntimeException("More than one group with the same name '" + aName + "'"); - } - if ( list.size() == 0 ) { - return null; - } - return new Group((Group)list.get(0)); - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#contains(org.wamblee.usermgt.Group) - */ - public boolean contains(Group aGroup) { - return find(aGroup.getName()) != null; - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#add(org.wamblee.usermgt.Group) - */ - public boolean add(Group aGroup) { - assert aGroup.getPrimaryKey() == null; - if ( contains(aGroup) ) { - return false; - } - super.merge(aGroup); - return true; - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#remove(org.wamblee.usermgt.Group) - */ - public boolean remove(Group aGroup) { - assert aGroup.getPrimaryKey() != null; - if ( !contains(aGroup)) { - return false; - } - Group group = (Group) getHibernateTemplate().merge(aGroup); - getHibernateTemplate().delete(group); - aGroup.setPrimaryKey(null); - aGroup.setPersistedVersion(-1); - return true; - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#list() - */ - public Set list() { - Set groups = new TreeSet(); - List list = getHibernateTemplate().loadAll(Group.class); - for (Group group: list) { - groups.add(new Group(group)); - } - return groups; - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.GroupSet#size() - */ - public int size() { - Long result = (Long) getHibernateTemplate().findByNamedQuery(QUERY_COUNT_GROUPS).get(0); - return result.intValue(); - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationComponent.java b/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationComponent.java deleted file mode 100644 index 66e3850f..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationComponent.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.io.IOException; - -import javax.sql.DataSource; - -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.springframework.transaction.PlatformTransactionManager; -import org.wamblee.cache.EhCache; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.components.ORMappingConfig; -import org.wamblee.system.core.Component; -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.HibernateComponent; -import org.wamblee.usermgt.UserAdministration; -import org.wamblee.usermgt.UserGroupRepositoryComponent; - -public class UserAdministrationComponent extends DefaultContainer { - - private ProvidedInterface TRANSACTION_MGR = new DefaultProvidedInterface( - "transactionManager", PlatformTransactionManager.class); - private ProvidedInterface USER_CACHE = new DefaultProvidedInterface( - "userCache", EhCache.class); - private ProvidedInterface HIBERNATE_TEMPLATE = new DefaultProvidedInterface( - "hibernateTemplate", HibernateTemplate.class); - private ProvidedInterface USER_MGT = new DefaultProvidedInterface( - "usermgt", UserAdministration.class); - - public UserAdministrationComponent(String aName, boolean aExposeInternals) - throws IOException { - super(aName); - - ObjectConfiguration mappingFilesConfig = new ObjectConfiguration(UsermgtHibernateMappingFiles.class); - mappingFilesConfig.getSetterConfig().initAllSetters(); - addComponent("mappingFiles", new UsermgtHibernateMappingFiles(), mappingFilesConfig); - - Component _hibernate = new HibernateComponent("hibernate"); - addComponent(_hibernate); - - Component _repository = new UserGroupRepositoryComponent("usersgroups"); - addComponent(_repository); - - Component _usermgt = new UserAdministrationLightComponent("usermgtlight"); - addComponent(_usermgt); - - addRequiredInterface(new DefaultRequiredInterface("datasource", - DataSource.class)); - addRequiredInterface(new DefaultRequiredInterface("ormconfig", ORMappingConfig.class)); - - if (aExposeInternals) { - addProvidedInterface(TRANSACTION_MGR); - addProvidedInterface(USER_CACHE); - addProvidedInterface(HIBERNATE_TEMPLATE); - } - addProvidedInterface(USER_MGT); - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationLightComponent.java b/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationLightComponent.java deleted file mode 100644 index 1a06ae7a..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/UserAdministrationLightComponent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.util.HashMap; -import java.util.Map; - -import org.wamblee.system.core.DefaultProvidedInterface; -import org.wamblee.system.core.DefaultRequiredInterface; -import org.wamblee.system.core.ProvidedInterface; -import org.wamblee.system.core.RequiredInterface; -import org.wamblee.system.spring.SpringComponent; -import org.wamblee.usermgt.GroupSet; -import org.wamblee.usermgt.UserAdministration; -import org.wamblee.usermgt.UserSet; - -/** - * Light version of the user administration component that requires external - * datasource, and userset and group set components, as well as an external - * hibernate session factory. - * @author Erik Brakkee - * - */ -public class UserAdministrationLightComponent extends SpringComponent { - - public UserAdministrationLightComponent(String aName) { - super(aName, new String[] { "spring/org.wamblee.security.usermgt.xml" }, - createProvided(), createRequired() ); - } - - private static Map createRequired() { - Map required = new HashMap(); - required.put(new DefaultRequiredInterface("userSet", UserSet.class), UserSet.class.getName()); - required.put(new DefaultRequiredInterface("groupSet", GroupSet.class), GroupSet.class.getName()); - return required; - } - - private static Map createProvided() { - Map provided = new HashMap(); - provided.put(UserAdministration.class.getName(), new DefaultProvidedInterface("org.wamblee.usermgt.UserAdministration", - UserAdministration.class)); - return provided; - } -} diff --git a/security/src/main/java/org/wamblee/usermgt/hibernate/UsermgtHibernateMappingFiles.java b/security/src/main/java/org/wamblee/usermgt/hibernate/UsermgtHibernateMappingFiles.java deleted file mode 100644 index 8d523c2e..00000000 --- a/security/src/main/java/org/wamblee/usermgt/hibernate/UsermgtHibernateMappingFiles.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.util.Collections; - -import org.wamblee.persistence.hibernate.HibernateMappingFiles; - -/** - * Hibernate mapping files for user management. - * - * @author Erik Brakkee - */ -public class UsermgtHibernateMappingFiles extends HibernateMappingFiles { - - public UsermgtHibernateMappingFiles() { - super(new String[] { - "hbm/Group.hbm.xml", "hbm/User.hbm.xml" - }); - } - - public UsermgtHibernateMappingFiles(String[] aFiles) { - this(); - Collections.addAll(this, aFiles); - } -} diff --git a/security/src/main/resources/hbm/PageAuthorizationRule.hbm.xml b/security/src/main/resources/hbm/PageAuthorizationRule.hbm.xml deleted file mode 100644 index 332e5d83..00000000 --- a/security/src/main/resources/hbm/PageAuthorizationRule.hbm.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/security/src/main/resources/hbm/PhotoAuthorizationRule.hbm.xml b/security/src/main/resources/hbm/PhotoAuthorizationRule.hbm.xml deleted file mode 100644 index fc00dda7..00000000 --- a/security/src/main/resources/hbm/PhotoAuthorizationRule.hbm.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/security/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java b/security/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java deleted file mode 100644 index 151dbd7e..00000000 --- a/security/src/test/java/org/wamblee/security/authorization/AuthorizationServiceTest.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import static org.wamblee.security.authorization.AuthorizationResult.DENIED; -import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; -import junit.framework.TestCase; - -import org.wamblee.usermgt.UserAccessor; - -/** - * Tests the authorization service. - * - * @author Erik Brakkee - */ -public class AuthorizationServiceTest extends TestCase { - - private AuthorizationRule _rule1; - private AuthorizationRule _rule2; - private AuthorizationRule _rule3; - private AuthorizationService _service; - - protected AuthorizationService getService() { - return _service; - } - - /* (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - - _rule1 = createRule(GRANTED, "users", "/oni/", AllOperation.class); - _rule2 = createRule(DENIED, "users", "/abc/", ReadOperation.class); - _rule3 = createRule(GRANTED, "users", "/abc/", AllOperation.class); - - _service = createService(); - _service.appendRule(_rule1); - _service.appendRule(_rule2); - _service.appendRule(_rule3); - } - - protected void resetTestRules() { - ((TestAuthorizationRule)_rule1).reset(); - ((TestAuthorizationRule)_rule2).reset(); - ((TestAuthorizationRule)_rule3).reset(); - } - - protected UserAccessor createUserAccessor() { - return new TestUserAccessor(); - } - - /** - * Creates an authorization service with some rules for testing. . - * @return Authorization service. - */ - protected AuthorizationService createService() { - DefaultAuthorizationService service = new DefaultAuthorizationService() ; - service.setUserAccessor(createUserAccessor()); - return service; - } - - protected AuthorizationRule createRule(AuthorizationResult aResult, String aGroup, String aPath, Class aOperation) { - return new TestAuthorizationRule(aResult, aGroup, aPath, aOperation); - } - - protected void checkMatchCount(int aCount, AuthorizationRule aRule) { - assertEquals( aCount, ((TestAuthorizationRule)aRule).getMatchCount()); - } - - protected Object createResource(String aPath) { - return new TestResource(aPath); - } - - protected void checkRuleCount(int aCount) { - // Empty - } - - /** - * Several checks to verify the outcome of matching against the first rule. - * - */ - public void testFirstRuleGrants() { - assertTrue( _service.isAllowed(createResource("/oni/xyz.jpg"), new ReadOperation())); - checkMatchCount(1, _rule1); - assertTrue(_service.isAllowed(createResource("/oni/xyz.jpg"), new WriteOperation())); - checkMatchCount(2, _rule1); - assertTrue(_service.isAllowed(createResource("/oni/xyz.jpg"), new DeleteOperation())); - checkMatchCount(3, _rule1); - assertTrue(_service.isAllowed(createResource("/oni/xyz.jpg"), new CreateOperation())); - checkMatchCount(4, _rule1); - checkMatchCount(0, _rule2); - checkMatchCount(0, _rule3); - } - - /** - * Verify that a match with the second rule leads to a denial of authorization. - * - */ - public void testSecondRuleDenies() { - assertFalse(_service.isAllowed(createResource("/abc/xyz.jpg"), new ReadOperation())); - checkMatchCount(0, _rule1); - checkMatchCount(1, _rule2); - checkMatchCount(0, _rule3); - } - - /** - * Verifies that the third rule is used when appropriate and that it grants access. - * - */ - public void testThirdRuleGrants() { - assertTrue(_service.isAllowed(createResource("/abc/xyz.jpg"), new WriteOperation())); - checkMatchCount(0, _rule1); - checkMatchCount(0, _rule2); - checkMatchCount(1, _rule3); - } - - /** - * Removes a rule and checks it is removed. - * - */ - public void testRemoveRule() { - checkRuleCount(3); - assertTrue(_service.isAllowed(createResource("/abc/xyz.jpg"), new WriteOperation())); - _service.removeRule(2); - assertFalse(_service.isAllowed(createResource("/abc/xyz.jpg"), new WriteOperation())); - checkRuleCount(2); - } - - /** - * Inserts a rule and checks it is inserted. - * - */ - public void testInsertRule() { - checkRuleCount(3); - assertFalse(_service.isAllowed(createResource("/janse/xyz.jpg"), new WriteOperation())); - _service.appendRule(createRule(GRANTED, "users", "/janse/", WriteOperation.class)); - assertTrue(_service.isAllowed(createResource("/janse/xyz.jpg"), new WriteOperation())); - checkRuleCount(4); - - } - - /** - * Gets the rules. Verifies that all rules are obtained. - * - */ - public void testGetRules() { - AuthorizationRule[] rules = _service.getRules(); - assertEquals(3, rules.length); - } - - /** - * Verifies that when no rules match, access is denied. - * - */ - public void testNoRulesSupportResource() { - assertFalse(_service.isAllowed(createResource("/xyxyxyxy"), new ReadOperation())); - checkMatchCount(0, _rule1); - checkMatchCount(0, _rule2); - checkMatchCount(0, _rule3); - } -} diff --git a/security/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java b/security/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java deleted file mode 100644 index 3dcfe2d2..00000000 --- a/security/src/test/java/org/wamblee/security/authorization/DefaultOperationRegistryTest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import junit.framework.TestCase; - -/** - * Test of the operation registry. - * - * @author Erik Brakkee - */ -public class DefaultOperationRegistryTest extends TestCase { - - private OperationRegistry _registry; - - /* (non-Javadoc) - * @see junit.framework.TestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - - _registry = new DefaultOperationRegistry(new Operation[] { - new AllOperation(), - new ReadOperation(), - new WriteOperation(), - new DeleteOperation(), - new CreateOperation() - }); - } - - /** - * Tests encoding and decoding of no operations. - * - */ - public void testEncodeDecodeNooperations() { - assertEquals("", _registry.encode(new Operation[0])); - assertEquals(0, _registry.decode(Object.class, "").length); - } - - /** - * Verifies that encoding of operations into a string works. - * - */ - public void testEncode() { - assertEquals("read,write", _registry.encode(new Operation[] { new ReadOperation(), new WriteOperation() })); - } - - /** - * Verifies that decoding of operation from a string works. - * - */ - public void testDecode() { - Operation[] operations = _registry.decode(Object.class, "read,write"); - assertTrue( operations[0] instanceof ReadOperation); - assertTrue( operations[1] instanceof WriteOperation); - } - - /** - * Verifies that an IllegalArgumentException occurs when attempting to decode - * an operation that is not known. - * - */ - public void testDecodeUnknownOperation() { - try { - _registry.decode(Object.class, "bla"); - fail(); - } catch (IllegalArgumentException e) { - // ok - } - } -} diff --git a/security/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java b/security/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java deleted file mode 100644 index 93141fde..00000000 --- a/security/src/test/java/org/wamblee/security/authorization/TestAuthorizationRule.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization; - -import static org.wamblee.security.authorization.AuthorizationResult.DENIED; -import static org.wamblee.security.authorization.AuthorizationResult.GRANTED; - -import org.wamblee.usermgt.User; - -/** - * Test authorization rule that also counts the number of times the rule matches. - * - * @author Erik Brakkee - */ -public class TestAuthorizationRule extends UrlAuthorizationRule { - - /** - * Counts the number of matches. - */ - private int _matches = 0; - - public TestAuthorizationRule( AuthorizationResult aResult, String aGroup, - String aPath, Class aOperation) { - super(aResult, new GroupUserCondition(aGroup), - new StartsWithPathCondition(aPath), TestResource.class, new IsaOperationCondition(aOperation)); - } - - protected TestAuthorizationRule() { - super(); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.UrlAuthorizationRule#getPath(java.lang.Object) - */ - @Override - protected String getResourcePath(Object aResource) { - return ((TestResource)aResource).getPath(); - } - - /* (non-Javadoc) - * @see org.wamblee.security.authorization.UrlAuthorizationRule#isAllowed(java.lang.Object, org.wamblee.security.authorization.Operation, org.wamblee.usermgt.UserAccessor) - */ - @Override - public AuthorizationResult isAllowed(Object aResource, Operation anOperation, User aUser) { - - AuthorizationResult result = super.isAllowed(aResource, anOperation, aUser); - if ( result.equals(GRANTED) || result.equals(DENIED)) { - _matches++; - } - return result; - } - - public int getMatchCount() { - return _matches; - } - - public void reset() { - _matches = 0; - } - -} diff --git a/security/src/test/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationServiceTest.java b/security/src/test/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationServiceTest.java deleted file mode 100644 index f55fc293..00000000 --- a/security/src/test/java/org/wamblee/security/authorization/hibernate/PersistentAuthorizationServiceTest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.security.authorization.hibernate; - -import java.sql.SQLException; - -import org.apache.log4j.Logger; -import org.hibernate.cfg.Configuration; -import org.hibernate.dialect.MySQL5Dialect; -import org.hibernate.dialect.MySQL5InnoDBDialect; -import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.springframework.orm.hibernate3.HibernateTemplate; -import org.wamblee.general.BeanKernel; -import org.wamblee.security.authorization.AuthorizationService; -import org.wamblee.security.authorization.AuthorizationServiceTest; -import org.wamblee.security.authorization.TestUserAccessor; -import org.wamblee.system.adapters.ClassConfiguration; -import org.wamblee.system.adapters.ClassConfigurationTest; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.components.DatabaseComponentFactory; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.DatabaseTesterComponent; -import org.wamblee.system.spring.component.DatasourceComponent; -import org.wamblee.usermgt.UserAccessor; -import org.wamblee.usermgt.hibernate.AuthorizationComponent; -import org.wamblee.usermgt.hibernate.HibernateUserAdministrationTest; -import org.wamblee.usermgt.hibernate.UserAdministrationComponent; - -/** - * Unit test for the persistent authorization service. - * - * @author Erik Brakkee - */ -public class PersistentAuthorizationServiceTest extends - AuthorizationServiceTest { - - private static final Logger LOGGER = Logger - .getLogger(PersistentAuthorizationServiceTest.class); - - private static final String SERVICE_TABLE = "AUTHORIZATION_SERVICE"; - private static final String RULES_TABLE = "AUTHORIZATION_RULES"; - private static final String SERVICE_RULES_TABLE = "AUTHORIZATION_SERVICE_RULES"; - private static final String OPERATIONCOND_TABLE = "OPERATION_CONDITIONS"; - private static final String PATHCOND_TABLE = "PATH_CONDITIONS"; - private static final String USERCOND_TABLE = "USER_CONDITIONS"; - - private DefaultContainer _container; - private Scope _scope; - - private DatabaseTesterComponent _databaseTester; - private UserAccessor _userAccessor; - private HibernateTemplate _hibernateTemplate; - private AuthorizationService _authorizationService; - - @Override - protected void setUp() throws Exception { - - _container = new DefaultContainer("top"); - DatabaseComponentFactory.addDatabaseConfig(_container); - _container.addComponent(new DatasourceComponent("datasource")); - ClassConfiguration useraccessorConfig = new ClassConfiguration( - TestUserAccessor.class); - useraccessorConfig.getObjectConfig().getSetterConfig().initAllSetters(); - _container.addComponent("userAccessor", useraccessorConfig); - _container.addComponent(new AuthorizationComponent("authorization", - true)); - - ClassConfiguration dbtesterConfig = new ClassConfiguration( - DatabaseTesterComponent.class); - dbtesterConfig.getObjectConfig().getSetterConfig().initAllSetters(); - _container.addComponent("databaseTester", dbtesterConfig); - - ObjectConfiguration config = new ObjectConfiguration( - PersistentAuthorizationServiceTest.class); - config.getSetterConfig().clear().add("setUserAccessor").add( - "setDatabaseTester").add("setHibernateTemplate").add( - "setAuthorizationService"); - _container.addComponent("testcase", this, config); - - _scope = _container.start(); - - _databaseTester.cleanDatabase(); - - super.setUp(); - } - - public void setDatabaseTester(DatabaseTesterComponent aDatabaseTester) { - _databaseTester = aDatabaseTester; - } - - public void setUserAccessor(UserAccessor aUserAccessor) { - _userAccessor = aUserAccessor; - } - - public void setHibernateTemplate(HibernateTemplate aHibernateTemplate) { - _hibernateTemplate = aHibernateTemplate; - } - - public void setAuthorizationService( - AuthorizationService aAuthorizationService) { - _authorizationService = aAuthorizationService; - } - - /* - * (non-Javadoc) - * - * @see - * org.wamblee.security.authorization.AuthorizationServiceTest#createService - * () - */ - @Override - protected AuthorizationService createService() { - PersistentAuthorizationService service = new PersistentAuthorizationService( - "DEFAULT", _hibernateTemplate, createUserAccessor(), 10000); - return service; - } - - /* - * (non-Javadoc) - * - * @see - * org.wamblee.security.authorization.AuthorizationServiceTest#checkRuleCount - * (int) - */ - @Override - protected void checkRuleCount(int aCount) { - try { - assertEquals(1, _databaseTester.getTableSize(SERVICE_TABLE)); - assertEquals(aCount, _databaseTester.getTableSize(RULES_TABLE)); - assertEquals(aCount, _databaseTester - .getTableSize(SERVICE_RULES_TABLE)); - assertEquals(aCount, _databaseTester.getTableSize(USERCOND_TABLE)); - assertEquals(aCount, _databaseTester.getTableSize(PATHCOND_TABLE)); - assertEquals(aCount, _databaseTester - .getTableSize(OPERATIONCOND_TABLE)); - } catch (SQLException e) { - throw new RuntimeException(e); - } - - } - - public void testSchemaExport() { - Configuration config = new Configuration(); - for (String mappingFile: new AuthorizationMappingFiles()) { - config.addResource(mappingFile); - } - config.setProperty("hibernate.dialect", MySQL5InnoDBDialect.class.getName()); - SchemaExport exporter = new SchemaExport(config); - exporter.setOutputFile("target/mysql5.schema.sql"); - exporter.create(true,false); - } - - public void testPerformance() { - - PersistentAuthorizationService service = (PersistentAuthorizationService) getService(); - - int n = 1000; - long time = System.currentTimeMillis(); - for (int i = 0; i < n; i++) { - testFirstRuleGrants(); - resetTestRules(); - testSecondRuleDenies(); - resetTestRules(); - testThirdRuleGrants(); - resetTestRules(); - testNoRulesSupportResource(); - } - LOGGER.info("Executed " + 4 * n + " authorization checks in " - + (float) (System.currentTimeMillis() - time) / (float) 1000 - + " seconds."); - } -} diff --git a/security/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java b/security/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java deleted file mode 100644 index 2ea11905..00000000 --- a/security/src/test/java/org/wamblee/usermgt/InMemoryGroupSetTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.sql.SQLException; -import java.util.Set; - -import junit.framework.TestCase; - -/** - * Tests the inmemory group set. Intended to be subclassed for other - * implementations of group set. - */ -public class InMemoryGroupSetTest extends TestCase { - - protected GroupSet _groups; - - /** - * This method must be overriden in subclasses. - * @return New group set object. - */ - protected GroupSet createGroupSet() { - return new InMemoryGroupSet(); - } - - /* (non-Javadoc) - * @see org.wamblee.test.SpringTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - _groups = createGroupSet(); - checkGroupCount(0); - } - - - - /** - * Additional check to be implemented by a subclass. - * @param aGroup Group to check for existence. - */ - protected void checkGroupExists(String aGroup) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aGroup Group to check for non-existence. - */ - protected void checkGroupNotExists(String aGroup) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aSize Expected number of groups. - */ - protected void checkGroupCount(int aSize) throws SQLException { - assertEquals(aSize, _groups.size()); - } - - /** - * Adds a group and verifies that the group is added using - * find(), list(), and contains(). - * - */ - public void testAdd() throws SQLException { - Group group = new Group("group1"); - assertTrue( _groups.add(group) ); - checkGroupExists(group.getName()); - checkGroupCount(1); - Group group2 = _groups.find("group1"); - assertNotNull(group2); - assertEquals(group.getName(), group2.getName()); - Set set = _groups.list(); - assertEquals(1, set.size()); - assertTrue(set.contains(group)); - } - - /** - * Tries to find a non-existing group. Verifies that null is - * returned. - * - */ - public void testFindUnknownGroup() throws SQLException { - Group group1 = new Group("group1"); - Group group2 = new Group("group2"); - _groups.add(group1); - _groups.add(group2); - checkGroupExists(group1.getName()); - checkGroupExists(group2.getName()); - - assertNull( _groups.find("group3") ); - checkGroupNotExists("group3"); - } - - /** - * Adds duplicate group. Verifies that the existing group is left untouched. - */ - public void testAddDuplicateGroup() throws SQLException { - Group group1 = new Group("group1"); - _groups.add(group1); - - assertEquals(1, _groups.list().size()); - assertTrue(_groups.contains(group1)); - group1 = new Group("group1"); - assertFalse(_groups.add(group1)); - assertEquals(1, _groups.list().size()); - - checkGroupExists(group1.getName()); - checkGroupCount(1); - } - - /** - * Removes a group. Verifies that the group is - * removed and the return value is true. - * - */ - public void testRemoveGroup() throws SQLException { - Group group1 = new Group("group1"); - _groups.add(group1); - assertTrue(_groups.contains(group1)); - checkGroupCount(1); - - assertTrue(_groups.remove(group1)); - assertFalse(_groups.contains(group1)); - assertNull(_groups.find(group1.getName())); - assertEquals(0, _groups.list().size()); - checkGroupCount(0); - } - - /** - * Removes a non-existing group. Verifies that no groups are - * removed an that the return value is true. - * - */ - public void testRemoveNonExistingGroup() throws SQLException { - Group group1 = new Group("group1"); - _groups.add(group1); - checkGroupCount(1); - Group nonExistingGroup = new Group("group2"); - nonExistingGroup.setPrimaryKey(new Long(1000)); - nonExistingGroup.setPersistedVersion(1000); - assertFalse(_groups.remove(nonExistingGroup)); - assertTrue(_groups.contains(group1)); - assertEquals(1, _groups.list().size()); - checkGroupCount(1); - } - - /** - * Adds a number of groups to the set and verifies that list() - * returns them all. - * - */ - public void testList() throws SQLException { - Group group1 = new Group("group1"); - Group group2 = new Group("group2"); - Group group3 = new Group("group3"); - assertTrue(_groups.add(group1)); - assertTrue(_groups.add(group2)); - assertTrue(_groups.add(group3)); - - checkGroupExists(group1.getName()); - checkGroupExists(group2.getName()); - checkGroupExists(group3.getName()); - - Set set = _groups.list(); - assertTrue(set.contains(group1)); - assertTrue(set.contains(group2)); - assertTrue(set.contains(group3)); - - checkGroupCount(3); - } -} diff --git a/security/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java b/security/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java deleted file mode 100644 index 8d60d433..00000000 --- a/security/src/test/java/org/wamblee/usermgt/InMemoryUserSetTest.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt; - -import java.sql.SQLException; -import java.util.Set; - -import junit.framework.TestCase; - -import org.wamblee.security.encryption.Md5HexMessageDigester; -import org.wamblee.usermgt.UserMgtException.Reason; - -/** - * Tests the inmemory user set. Intended to be subclassed for other - * implementations of user set. - */ -public class InMemoryUserSetTest extends TestCase { - - protected static final String PASSWORD = "abc123"; - - private UserSet _users; - private GroupSet _groups; - - private Group _group; - - /** - * This method must be overriden in subclasses. - * @return New user set object. - */ - protected UserSet createUserSet() { - return new InMemoryUserSet( new RegexpNameValidator(RegexpNameValidator.PASSWORD_PATTERN, Reason.INVALID_PASSWORD, "Password must contain at least 6 characters"), - new Md5HexMessageDigester()); - } - - /** - * This method must be overriden in subclasses. - * @return New group set object. - */ - protected GroupSet createGroupSet() { - return new InMemoryGroupSet(); - } - - /* (non-Javadoc) - * @see org.wamblee.test.SpringTestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - _users = createUserSet(); - _groups = createGroupSet(); - _group = new Group("group0"); - _groups.add(_group); - checkUserCount(0); - - } - - protected UserSet getUsers() { - return _users; - } - - protected GroupSet getGroups() { - return _groups; - } - - protected Group createGroup(String aName) { - return new Group(aName); - } - - protected User createUser(String aName, String aPassword, Group aGroup) throws UserMgtException { - return UsermgtTestUtils.createUser(aName, aPassword, aGroup); - } - - protected void addUserToGroup(User aUser, Group aGroup) throws UserMgtException { - aUser.addGroup(aGroup); - } - - protected void removeUserFromGroup(User aUser, Group aGroup ) throws UserMgtException { - aUser.removeGroup(aGroup); - } - - /** - * Additional check to be implemented by a subclass. - * @param aUser User to check for existence. - */ - protected void checkUserExists(String aUser) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aUser User to check for non-existence. - */ - protected void checkUserNotExists(String aUser) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aSize Expected number of users. - */ - protected void checkUserCount(int aSize) throws SQLException { - assertEquals(aSize, _users.size()); - } - - /** - * Additional check to be implemented by a subclass. - * @param aUser User to check for existence. - */ - protected void checkGroupExists(String aUser) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aUser User to check for non-existence. - */ - protected void checkGroupNotExists(String aUser) throws SQLException { - // Empty - } - - /** - * Additional check to be implemented by a subclass. - * @param aSize Expected number of users. - */ - protected void checkGroupCount(int aSize) throws SQLException { - // Empty - } - - - /** - * Adds a user and verifies that the user is added using - * find(), list(), and contains(). - * - */ - public void testAdd() throws SQLException, UserMgtException { - User user = createUser("user1", PASSWORD, _group); - assertTrue( _users.add(user) ); - checkUserExists(user.getName()); - checkUserCount(1); - User user2 = _users.find("user1"); - assertNotNull(user2); - assertEquals(user.getName(), user2.getName()); - Set set = _users.list(); - assertEquals(1, set.size()); - assertTrue(set.contains(user)); - } - - /** - * Tries to find a non-existing user. Verifies that null is - * returned. - * - */ - public void testFindUnknownUser() throws SQLException, UserMgtException { - User user1 = createUser("user1", PASSWORD, _group); - User user2 = createUser("user2", PASSWORD, _group); - _users.add(user1); - _users.add(user2); - checkUserExists(user1.getName()); - checkUserExists(user2.getName()); - - assertNull( _users.find("user3") ); - checkUserNotExists("user3"); - } - - /** - * Adds duplicate user. Verifies that the existing user is left untouched. - */ - public void testAddDuplicateUser() throws SQLException, UserMgtException { - User user1 = createUser("user1", PASSWORD, _group); - _users.add(user1); - - assertEquals(1, _users.list().size()); - assertTrue(_users.contains(user1)); - user1 = createUser("user1", PASSWORD, _group); - assertFalse(_users.add(user1)); - assertEquals(1, _users.list().size()); - - checkUserExists(user1.getName()); - checkUserCount(1); - } - - /** - * Removes a user. Verifies that the user is - * removed and the return value is true. - * - */ - public void testRemoveUser() throws SQLException, UserMgtException { - User user1 = createUser("user1", PASSWORD, _group); - _users.add(user1); - assertTrue(_users.contains(user1)); - checkUserCount(1); - - assertTrue(_users.remove(user1)); - assertFalse(_users.contains(user1)); - assertNull(_users.find(user1.getName())); - assertEquals(0, _users.list().size()); - checkUserCount(0); - } - - /** - * Removes a non-existing user. Verifies that no users are - * removed an that the return value is true. - * - */ - public void testRemoveNonExistingUser() throws SQLException, UserMgtException { - User user1 = createUser("user1", PASSWORD, _group); - _users.add(user1); - checkUserCount(1); - User nonExistingUser = createUser("user2", PASSWORD, _group); - nonExistingUser.setPrimaryKey(new Long(1000)); - nonExistingUser.setPersistedVersion(10); - assertFalse(_users.remove(nonExistingUser)); - assertTrue(_users.contains(user1)); - assertEquals(1, _users.list().size()); - checkUserCount(1); - } - - /** - * Adds a number of users to the set and verifies that list() - * returns them all. - * - */ - public void testList() throws SQLException, UserMgtException { - User user1 = createUser("user1", PASSWORD, _group); - User user2 = createUser("user2", PASSWORD, _group); - User user3 = createUser("user3", PASSWORD, _group); - assertTrue(_users.add(user1)); - assertTrue(_users.add(user2)); - assertTrue(_users.add(user3)); - - checkUserExists(user1.getName()); - checkUserExists(user2.getName()); - checkUserExists(user3.getName()); - - Set set = _users.list(); - assertTrue(set.contains(user1)); - assertTrue(set.contains(user2)); - assertTrue(set.contains(user3)); - - checkUserCount(3); - } - - /** - * Adds several users to different groups and verifies that - * the correct users are returned when looking for users in - * different groups. - * @throws SQLException - */ - public void testListByGroup() throws SQLException, UserMgtException { - Group group1 = new Group("group1"); - Group group2 = new Group("group2"); - Group group3 = new Group("group3"); - _groups.add(group1); - _groups.add(group2); - _groups.add(group3); - - // user1 user2 user3 - // group1 y - // group2 y y - // group3 y y y - - User user1 = createUser("user1", PASSWORD, group1); - user1.addGroup(group2); - user1.addGroup(group3); - User user2 = createUser("user2", PASSWORD, group2); - user2.addGroup(group3); - User user3 = createUser("user3", PASSWORD, group3); - _users.add(user1); - _users.add(user2); - _users.add(user3); - - checkUserExists(user1.getName()); - checkUserExists(user2.getName()); - checkUserExists(user3.getName()); - - checkGroupExists(group1.getName()); - checkGroupExists(group2.getName()); - checkGroupExists(group3.getName()); - - checkUserCount(3); - checkGroupCount(3+1); // also count the group that was created in the setUp(). - - Set list = _users.list(group1); - assertTrue(list.contains(user1)); - assertEquals(1, list.size()); - - list = _users.list(group2); - assertTrue(list.contains(user1)); - assertTrue(list.contains(user2)); - assertEquals(2, list.size()); - - list = _users.list(group3); - assertTrue(list.contains(user1)); - assertTrue(list.contains(user2)); - assertTrue(list.contains(user3)); - assertEquals(3, list.size()); - } -} diff --git a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateGroupSetTest.java b/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateGroupSetTest.java deleted file mode 100644 index fa80b1a4..00000000 --- a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateGroupSetTest.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; - -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.DatabaseTesterComponent; -import org.wamblee.test.spring.TestTransactionCallback; -import org.wamblee.usermgt.GroupSet; -import org.wamblee.usermgt.InMemoryGroupSetTest; - -/** - * Tests for {@link org.wamblee.usermgt.hibernate.HibernateGroupSet} - * - * @author Erik Brakkee - */ -public class HibernateGroupSetTest extends InMemoryGroupSetTest { - - private static final String GROUP_TABLE = "GROUPS"; - - private static final String GROUP_QUERY = "select * from " + GROUP_TABLE + " where name = ?"; - - private DefaultContainer _container; - private Scope _scope; - - private DatabaseTesterComponent _databaseTester; - private GroupSet _groupSet; - - @Override - protected void setUp() throws Exception { - - _container = new UserMgtRepositoryTestContainer("top"); - - ObjectConfiguration config = new ObjectConfiguration( - HibernateGroupSetTest.class); - config.getSetterConfig().clear().add( - "setGroupSet").add("setDatabaseTester"); - _container.addComponent("testcase", this, config); - - _scope = _container.start(); - - _databaseTester.cleanDatabase(); - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - _container.stop(_scope); - super.tearDown(); - } - - public void setDatabaseTester(DatabaseTesterComponent aDatabaseTester) { - _databaseTester = aDatabaseTester; - } - - public void setGroupSet(GroupSet aGroupSet) { - _groupSet = aGroupSet; - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupCount(int) - */ - @Override - protected void checkGroupCount(int aSize) throws SQLException { - _databaseTester.flush(); - super.checkGroupCount(aSize); - assertEquals(aSize, _databaseTester.getTableSize(GROUP_TABLE)); - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupExists(java.lang.String) - */ - @Override - protected void checkGroupExists(final String aGroup) throws SQLException { - _databaseTester.flush(); - Map result = - _databaseTester.executeTransaction(new TestTransactionCallback() { - /* (non-Javadoc) - * @see org.wamblee.test.TestTransactionCallback#execute() - */ - @Override - public Map execute() throws Exception { - ResultSet result = _databaseTester.executeQuery(GROUP_QUERY, aGroup); - Map res = new HashMap(); - res.put("result", _databaseTester.countResultSet(result)); - return res; - } - }); - - int count = result.get("result"); - assertEquals(1, count); - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupNotExists(java.lang.String) - */ - @Override - protected void checkGroupNotExists(String aGroup) throws SQLException { - _databaseTester.flush(); - ResultSet result = _databaseTester.executeQuery(GROUP_QUERY, aGroup); - assertEquals(0, _databaseTester.countResultSet(result)); - } - - /* (non-Javadoc) - * @see org.wamblee.usermgt.InMemoryGroupSetTest#createGroupSet() - */ - @Override - protected GroupSet createGroupSet() { - return _groupSet; - } - -} diff --git a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserAdministrationTest.java b/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserAdministrationTest.java deleted file mode 100644 index f707dba0..00000000 --- a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserAdministrationTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.sql.SQLException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.wamblee.cache.EhCache; -import org.wamblee.system.adapters.ClassConfiguration; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.components.DatabaseComponentFactory; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.DatabaseTesterComponent; -import org.wamblee.system.spring.component.DatasourceComponent; -import org.wamblee.test.spring.TestTransactionCallbackWithoutResult; -import org.wamblee.usermgt.UserAdministration; -import org.wamblee.usermgt.UserAdministrationImplTest; - -/** - * User administration tests with persistence based on Hibernate. This executes - * the same test cases as {@link org.wamblee.usermgt.UserAdministrationImplTest} - * with in addition, one test case that executes all Hibernate test cases - * separately with each test case in its own transaction. - * - * @author Erik Brakkee - */ -public class HibernateUserAdministrationTest extends UserAdministrationImplTest { - - private static final Log LOG = LogFactory.getLog(HibernateUserAdministrationTest.class); - - private DefaultContainer _container; - private Scope _scope; - - private DatabaseTesterComponent _databaseTester; - private EhCache _userCache; - private UserAdministration _userAdmin; - - - /* (non-Javadoc) - * @see org.wamblee.usermgt.UserAdministrationImplTest#setUp() - */ - @Override - protected void setUp() throws Exception { - - _container = new DefaultContainer("top"); - DatabaseComponentFactory.addDatabaseConfig(_container); - _container.addComponent(new DatasourceComponent("datasource")); - _container.addComponent(new UserAdministrationComponent("admin", true)); - - ClassConfiguration dbtesterConfig = new ClassConfiguration(DatabaseTesterComponent.class); - dbtesterConfig.getObjectConfig().getSetterConfig().initAllSetters(); - _container.addComponent("databaseTester", dbtesterConfig); - - ObjectConfiguration config = new ObjectConfiguration( - HibernateUserAdministrationTest.class); - config.getSetterConfig().clear().add( - "setUserCache").add("setDatabaseTester").add("setUserAdmin"); - _container.addComponent("testcase", this, config); - - _scope = _container.start(); - - _databaseTester.cleanDatabase(); - - super.setUp(); - clearUserCache(); - } - - public void setUserCache(EhCache aUserCache) { - _userCache = aUserCache; - } - - public void setDatabaseTester(DatabaseTesterComponent aDatabaseTester) { - _databaseTester = aDatabaseTester; - } - - public void setUserAdmin(UserAdministration aUserAdmin) { - _userAdmin = aUserAdmin; - } - - @Override - protected void tearDown() throws Exception { - _container.stop(_scope); - super.tearDown(); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.UserAdministrationImplTest#createAdmin() - */ - @Override - protected UserAdministration createAdmin() { - return _userAdmin; - } - - public void testAllTestsInASeparateTransaction() throws SQLException { - - Method[] methods = UserAdministrationImplTest.class.getMethods(); - for (final Method method : methods) { - if (method.getName().startsWith("test")) { - _databaseTester.cleanDatabase(); - clearUserCache(); - _databaseTester.executeTransaction(new TestTransactionCallbackWithoutResult() { - public void execute() throws Exception { - LOG.info("Running test " + method.getName()); - try { - method.invoke(HibernateUserAdministrationTest.this); - } catch (Throwable t) { - LOG.error("Test " + method.getName() + " failed"); - throw new RuntimeException(t.getMessage(), t); - } - finally { - LOG.info("Test " + method.getName() + " finished"); - } - - } - }); - } - } - } - - /** - * - */ - private void clearUserCache() { - _userCache.clear(); - } -} diff --git a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserSetTest.java b/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserSetTest.java deleted file mode 100644 index 82588b3b..00000000 --- a/security/src/test/java/org/wamblee/usermgt/hibernate/HibernateUserSetTest.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2005 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.io.Serializable; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Set; - -import org.wamblee.cache.EhCache; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.core.Scope; -import org.wamblee.system.spring.component.DatabaseTesterComponent; -import org.wamblee.usermgt.Group; -import org.wamblee.usermgt.GroupSet; -import org.wamblee.usermgt.InMemoryUserSetTest; -import org.wamblee.usermgt.User; -import org.wamblee.usermgt.UserMgtException; -import org.wamblee.usermgt.UserSet; - -/** - * Tests for {@link org.wamblee.usermgt.hibernate.HibernateGroupSet} - * - * @author Erik Brakkee - */ -public class HibernateUserSetTest extends InMemoryUserSetTest { - - private static final String USER_TABLE = "USERS"; - private static final String GROUP_TABLE = "GROUPS"; - - private static final String USER_QUERY = "select * from " + USER_TABLE - + " where name = ?"; - private static final String GROUP_QUERY = "select * from " + GROUP_TABLE - + " where name = ?"; - - private DefaultContainer _container; - private Scope _scope; - - private UserSet _userset; - private GroupSet _groupset; - private EhCache _userCache; - private DatabaseTesterComponent _databaseTester; - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryUserSetTest#setUp() - */ - @Override - protected void setUp() throws Exception { - - _container = new UserMgtRepositoryTestContainer("top"); - - ObjectConfiguration config = new ObjectConfiguration( - HibernateUserSetTest.class); - config.getSetterConfig().clear().add("setUserset").add( - "setGroupset").add("setDatabaseTester").add("setUserCache"); - _container.addComponent("testcase", this, config); - - _scope = _container.start(); - - clearUserCache(); - _databaseTester.cleanDatabase(); - - super.setUp(); - } - - public void setUserset(UserSet aUserset) { - _userset = aUserset; - } - - public void setGroupset(GroupSet aGroupset) { - _groupset = aGroupset; - } - - public void setUserCache(EhCache aUserCache) { - _userCache = aUserCache; - } - - public void setDatabaseTester(DatabaseTesterComponent aDatabaseTester) { - _databaseTester = aDatabaseTester; - } - - @Override - protected void tearDown() throws Exception { - _container.stop(_scope); - super.tearDown(); - } - - /** - * Clears the user cache. - */ - private void clearUserCache() { - _userCache.clear(); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupCount(int) - */ - @Override - protected void checkUserCount(int aSize) throws SQLException { - _databaseTester.flush(); - super.checkUserCount(aSize); - assertEquals(aSize, _databaseTester.getTableSize(USER_TABLE)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupExists(java.lang.String) - */ - @Override - protected void checkUserExists(String aUser) throws SQLException { - _databaseTester.flush(); - ResultSet result = _databaseTester.executeQuery(USER_QUERY, aUser); - assertEquals(1, _databaseTester.countResultSet(result)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupNotExists(java.lang.String) - */ - @Override - protected void checkUserNotExists(String aUser) throws SQLException { - _databaseTester.flush(); - ResultSet result = _databaseTester.executeQuery(USER_QUERY, aUser); - assertEquals(0, _databaseTester.countResultSet(result)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupCount(int) - */ - @Override - protected void checkGroupCount(int aSize) throws SQLException { - _databaseTester.flush(); - assertEquals(aSize, _databaseTester.getTableSize(GROUP_TABLE)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupExists(java.lang.String) - */ - @Override - protected void checkGroupExists(String aGroup) throws SQLException { - _databaseTester.flush(); - - ResultSet result = _databaseTester.executeQuery(GROUP_QUERY, aGroup); - assertEquals(1, _databaseTester.countResultSet(result)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#checkGroupNotExists(java.lang.String) - */ - @Override - protected void checkGroupNotExists(String aGroup) throws SQLException { - _databaseTester.flush(); - ResultSet result = _databaseTester.executeQuery(GROUP_QUERY, aGroup); - assertEquals(0, _databaseTester.countResultSet(result)); - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryGroupSetTest#createGroupSet() - */ - @Override - protected UserSet createUserSet() { - return _userset; - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.usermgt.InMemoryUserSetTest#createGroupSet() - */ - @Override - protected GroupSet createGroupSet() { - return _groupset; - } - - /** - * Reproduction of a bug. Create a user which is in group1 Add it to a - * second group group2. Remove the user from group1. Verify the user is in - * group2. - */ - public void testVerifyAddRemove() throws SQLException, UserMgtException { - _databaseTester.cleanDatabase(); // just to be sure. - GroupSet groups = getGroups(); - assertEquals(0, groups.size()); - Group group1 = createGroup("group1"); - Group group2 = createGroup("group2"); - groups.add(group1); - groups.add(group2); - checkGroupExists("group1"); - checkGroupExists("group2"); - - User user = createUser("user", PASSWORD, group1); - getUsers().add(user); - checkUserExists("user"); - - addUserToGroup(user, group2); - getUsers().userModified(user); - clearUserCache(); - User user2 = getUsers().find("user"); - Set userGroups = user2.getGroups(); - assertTrue(user2.isInGroup("group1")); - assertTrue(user2.isInGroup("group2")); - assertEquals(2, userGroups.size()); - - removeUserFromGroup(user, group1); - getUsers().userModified(user); - clearUserCache(); - user2 = getUsers().find("user"); - userGroups = user2.getGroups(); - assertFalse(user2.isInGroup("group1")); - assertTrue(user2.isInGroup("group2")); - assertEquals(1, userGroups.size()); - } - -} diff --git a/security/src/test/java/org/wamblee/usermgt/hibernate/UserMgtRepositoryTestContainer.java b/security/src/test/java/org/wamblee/usermgt/hibernate/UserMgtRepositoryTestContainer.java deleted file mode 100644 index dd443916..00000000 --- a/security/src/test/java/org/wamblee/usermgt/hibernate/UserMgtRepositoryTestContainer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2008 the original author or authors. - * - * 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.wamblee.usermgt.hibernate; - -import java.io.IOException; - -import org.wamblee.system.adapters.ClassConfiguration; -import org.wamblee.system.adapters.DefaultContainer; -import org.wamblee.system.adapters.ObjectConfiguration; -import org.wamblee.system.components.DatabaseComponentFactory; -import org.wamblee.system.spring.component.DatabaseTesterComponent; -import org.wamblee.system.spring.component.DatasourceComponent; -import org.wamblee.system.spring.component.HibernateComponent; -import org.wamblee.usermgt.UserGroupRepositoryComponent; - -/** - * - * Test container for repository tests of user management. - * - * @author Erik Brakkee - */ -public class UserMgtRepositoryTestContainer extends DefaultContainer { - - public UserMgtRepositoryTestContainer(String aName) throws IOException { - super(aName); - DatabaseComponentFactory.addDatabaseConfig(this); - addComponent(new DatasourceComponent("datasource")); - - ObjectConfiguration mappingFilesConfig = new ObjectConfiguration(UsermgtHibernateMappingFiles.class); - mappingFilesConfig.getSetterConfig().initAllSetters(); - addComponent("mappingFiles", new UsermgtHibernateMappingFiles(), mappingFilesConfig); - addComponent(new HibernateComponent("hibernate")); - addComponent(new UserGroupRepositoryComponent("usersgroups")); - ClassConfiguration dbtesterConfig = new ClassConfiguration(DatabaseTesterComponent.class); - dbtesterConfig.getObjectConfig().getSetterConfig().initAllSetters(); - addComponent("databaseTester", dbtesterConfig); - - } - -} diff --git a/support/general/pom.xml b/support/general/pom.xml index 5208957a..7d161bad 100644 --- a/support/general/pom.xml +++ b/support/general/pom.xml @@ -13,6 +13,10 @@ /support/general http://wamblee.org + + javax + javaee-api + oro oro diff --git a/support/general/src/main/java/org/wamblee/cache/Cache.java b/support/general/src/main/java/org/wamblee/cache/Cache.java index 15f2c508..6e0f1b3c 100644 --- a/support/general/src/main/java/org/wamblee/cache/Cache.java +++ b/support/general/src/main/java/org/wamblee/cache/Cache.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,43 +13,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.cache; import java.io.Serializable; /** - * The Cache interface represents... a cache. - * In some circumstances it is more optimal to implement caching directly in - * the code instead of relying on Hibernate caching methods. This interface abstracts - * from the used cache implementation. - * Cache implementations must be thread-safe. + * The Cache interface represents... a cache. In some circumstances + * it is more optimal to implement caching directly in the code instead of + * relying on Hibernate caching methods. This interface abstracts from the used + * cache implementation. Cache implementations must be thread-safe. */ public interface Cache { - /** - * Adds a key-value pair to the cache. - * @param aKey Key. - * @param aValue Value. + * Adds a key-value pair to the cache. + * + * @param aKey + * Key. + * @param aValue + * Value. */ - void put(KeyType aKey, ValueType aValue); - + void put(KeyType aKey, ValueType aValue); + /** - * Retrieves a value from the cache. - * @param aKey Key to retrieve. - * @return Key. + * Retrieves a value from the cache. + * + * @param aKey + * Key to retrieve. + * + * @return Key. */ ValueType get(KeyType aKey); - + /** - * Removes an entry from the cache. - * @param aKey Key to remove the entry for. + * Removes an entry from the cache. + * + * @param aKey + * Key to remove the entry for. */ - void remove(KeyType aKey); - + void remove(KeyType aKey); + /** - * Removes all entries from the cache. - * + * Removes all entries from the cache. */ - void clear(); + void clear(); } diff --git a/support/general/src/main/java/org/wamblee/cache/CachedObject.java b/support/general/src/main/java/org/wamblee/cache/CachedObject.java index 58daf8c9..3d200b5a 100644 --- a/support/general/src/main/java/org/wamblee/cache/CachedObject.java +++ b/support/general/src/main/java/org/wamblee/cache/CachedObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,56 +12,38 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.cache; -import java.io.Serializable; - import org.apache.log4j.Logger; +import java.io.Serializable; + /** * Represents a cached object. The object is either retrieved from the cache if * the cache has it, or a call back is invoked to get the object (and put it in * the cache). - * + * * @author Erik Brakkee + * */ public class CachedObject { - private static final Logger LOGGER = Logger.getLogger(CachedObject.class); - /** - * Callback invoked to compute an object if it was not found in the cache. - * - * @param - * Type of the object - */ - public static interface Computation { - /** - * Gets the object. Called when the object is not in the cache. - * - * @param aObjectKey - * Id of the object in the cache. - * @return Object, must be non-null. - */ - Value getObject(Key aObjectKey); - } - /** * Cache to use. */ - private Cache _cache; + private Cache cache; /** * Key of the object in the cache. */ - private KeyType _objectKey; + private KeyType objectKey; /** * Computation used to obtain the object if it is not found in the cache. */ - private Computation _computation; + private Computation computation; /** * Constructs the cached object. @@ -75,10 +57,10 @@ public class CachedObject aCache, KeyType aObjectKey, - Computation aComputation) { - _cache = aCache; - _objectKey = aObjectKey; - _computation = aComputation; + Computation aComputation) { + cache = aCache; + objectKey = aObjectKey; + computation = aComputation; } /** @@ -88,9 +70,10 @@ public class CachedObject + * Type of the object + */ + public static interface Computation { + /** + * Gets the object. Called when the object is not in the cache. + * + * @param aObjectKey + * Id of the object in the cache. + * + * @return Object, must be non-null. + */ + Value getObject(Key aObjectKey); } } diff --git a/support/general/src/main/java/org/wamblee/cache/EhCache.java b/support/general/src/main/java/org/wamblee/cache/EhCache.java index 6a631866..6c262bf9 100644 --- a/support/general/src/main/java/org/wamblee/cache/EhCache.java +++ b/support/general/src/main/java/org/wamblee/cache/EhCache.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,41 +12,41 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.cache; -import java.io.IOException; -import java.io.InputStream; -import java.io.Serializable; - import net.sf.ehcache.Cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; import org.apache.log4j.Logger; + import org.wamblee.io.InputResource; +import java.io.IOException; +import java.io.InputStream; +import java.io.Serializable; + /** * Cache implemented on top of EhCache. - * + * * @author Erik Brakkee + * */ public class EhCache - implements org.wamblee.cache.Cache { - + implements org.wamblee.cache.Cache { private static final Logger LOGGER = Logger.getLogger(EhCache.class); /** * EH Cache manager. */ - private CacheManager _manager; + private CacheManager manager; /** * EH cache. */ - private Cache _cache; + private Cache cache; /** * Constructs a cache based on EHCache. @@ -60,22 +60,23 @@ public class EhCache - implements Cache { - + implements Cache { /** * Cached entries. */ - private HashMap _map; + private HashMap map; /** * Constructs the cache. * */ public ForeverCache() { - _map = new HashMap(); + map = new HashMap(); } /* @@ -47,7 +47,7 @@ public class ForeverCache - implements Cache { - - public ZeroCache() { - // Empty. +public class ZeroCache + implements Cache { + /** + * Creates a new ZeroCache object. + */ + public ZeroCache() { + // Empty. } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.cache.Cache#put(KeyType, ValueType) */ public void put(KeyType aKey, ValueType aValue) { - // Empty. + // Empty. } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.cache.Cache#get(KeyType) */ public ValueType get(KeyType aKey) { return null; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.cache.Cache#remove(KeyType) */ public void remove(KeyType aKey) { - // Empty + // Empty } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.cache.Cache#clear() */ public void clear() { - // Empty + // Empty } } diff --git a/support/general/src/main/java/org/wamblee/collections/CollectionFilter.java b/support/general/src/main/java/org/wamblee/collections/CollectionFilter.java index 75cdcb1e..4a1845c2 100644 --- a/support/general/src/main/java/org/wamblee/collections/CollectionFilter.java +++ b/support/general/src/main/java/org/wamblee/collections/CollectionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,26 +15,35 @@ */ package org.wamblee.collections; -import java.util.Collection; - import org.wamblee.conditions.Condition; -public class CollectionFilter { +import java.util.Collection; +/** + * + * @author $author$ + * @version $Revision$ + */ +public class CollectionFilter { /** - * Filters a collection by adding all elements in the from collection - * that satisfy a given condition to the to collection. - * @param Type of contained element. - * @param aFrom From container to which the condition is applied. - * @param aTo To container to which matching elements are added. - * @param aCondition Condition by which elements are matched. + * Filters a collection by adding all elements in the from collection that + * satisfy a given condition to the to collection. + * + * @param + * Type of contained element. + * @param aFrom + * From container to which the condition is applied. + * @param aTo + * To container to which matching elements are added. + * @param aCondition + * Condition by which elements are matched. */ - public static void filter(Collection aFrom, Collection aTo, Condition aCondition) { - for (T t: aFrom) { - if ( aCondition.matches(t)) { - aTo.add(t); - } - } - } - + public static void filter(Collection aFrom, Collection aTo, + Condition aCondition) { + for (T t : aFrom) { + if (aCondition.matches(t)) { + aTo.add(t); + } + } + } } diff --git a/support/general/src/main/java/org/wamblee/concurrency/JvmLock.java b/support/general/src/main/java/org/wamblee/concurrency/JvmLock.java index 2fe0d11f..c7164004 100644 --- a/support/general/src/main/java/org/wamblee/concurrency/JvmLock.java +++ b/support/general/src/main/java/org/wamblee/concurrency/JvmLock.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,41 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.concurrency; import java.util.concurrent.locks.ReentrantLock; /** - * In memory JVM lock. - * + * In memory JVM lock. + * * @author Erik Brakkee - */ + */ public class JvmLock implements Lock { - /** - * Reentrant lock to use. + * Reentrant lock to use. */ - private ReentrantLock _lock; - + private ReentrantLock lock; + /** - * In-memory lock. + * In-memory lock. */ - public JvmLock() { - _lock = new ReentrantLock(true); + public JvmLock() { + lock = new ReentrantLock(true); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.concurrency.Lock#acquire() */ public void acquire() { - _lock.lock(); + lock.lock(); } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.concurrency.Lock#release() */ public void release() { - _lock.unlock(); + lock.unlock(); } } diff --git a/support/general/src/main/java/org/wamblee/concurrency/Lock.java b/support/general/src/main/java/org/wamblee/concurrency/Lock.java index 50cc7842..ac8eee4b 100644 --- a/support/general/src/main/java/org/wamblee/concurrency/Lock.java +++ b/support/general/src/main/java/org/wamblee/concurrency/Lock.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,25 +13,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.concurrency; /** - * Represents a re-entrant lock. - * Implementations can provide inmemory JVM locking or full cluster safe locking - * mechanisms. - * + * Represents a re-entrant lock. Implementations can provide inmemory JVM + * locking or full cluster safe locking mechanisms. + * * @author Erik Brakkee */ public interface Lock { - /** - * Acquires the lock. + * Acquires the lock. */ - void acquire(); - + void acquire(); + /** - * Releases the lock. + * Releases the lock. */ - void release(); + void release(); } diff --git a/support/general/src/main/java/org/wamblee/concurrency/ReadWriteLock.java b/support/general/src/main/java/org/wamblee/concurrency/ReadWriteLock.java index e7658161..59f876c9 100644 --- a/support/general/src/main/java/org/wamblee/concurrency/ReadWriteLock.java +++ b/support/general/src/main/java/org/wamblee/concurrency/ReadWriteLock.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.wamblee.concurrency; import java.util.HashSet; - /** * Read-write lock for allowing multiple concurrent readers or at most one * writer. This implementation does not aim for high performance but for @@ -26,48 +25,48 @@ import java.util.HashSet; */ public class ReadWriteLock { /** - * Sets containing the references to the threads that are currently - * reading. This administration is useful to check that the lock has - * already been acquired before it is release. This check adds robustness - * to the application. + * Sets containing the references to the threads that are currently reading. + * This administration is useful to check that the lock has already been + * acquired before it is release. This check adds robustness to the + * application. */ - private HashSet _readers; + private HashSet readers; /** * The thread that has acquired the lock for writing or null if no such * thread exists currently. */ - private Thread _writer; + private Thread writer; /** * Constructs read-write lock. */ public ReadWriteLock() { - _readers = new HashSet(); - _writer = null; + readers = new HashSet(); + writer = null; } /** - * Acquires the lock for reading. This call will block until the lock can - * be acquired. - * - * @throws IllegalStateException Thrown if the read or write lock is - * already acquired. + * Acquires the lock for reading. This call will block until the lock can be + * acquired. + * + * @throws IllegalStateException + * Thrown if the read or write lock is already acquired. */ public synchronized void acquireRead() { - if (_readers.contains(Thread.currentThread())) { + if (readers.contains(Thread.currentThread())) { throw new IllegalStateException( - "Read lock already acquired by current thread: " - + Thread.currentThread()); + "Read lock already acquired by current thread: " + + Thread.currentThread()); } - if (_writer == Thread.currentThread()) { + if (writer == Thread.currentThread()) { throw new IllegalStateException( - "Trying to acquire the read lock while already holding a write lock: " - + Thread.currentThread()); + "Trying to acquire the read lock while already holding a write lock: " + + Thread.currentThread()); } - while (_writer != null) { + while (writer != null) { try { wait(); } catch (InterruptedException e) { @@ -75,23 +74,23 @@ public class ReadWriteLock { } } - _readers.add(Thread.currentThread()); + readers.add(Thread.currentThread()); } /** - * Releases the lock for reading. Note: This implementation assumes that - * the lock has already been acquired for reading previously. - * - * @throws IllegalStateException Thrown when the lock was not acquired by - * this thread. + * Releases the lock for reading. Note: This implementation assumes that the + * lock has already been acquired for reading previously. + * + * @throws IllegalStateException + * Thrown when the lock was not acquired by this thread. */ public synchronized void releaseRead() { - if (!_readers.remove(Thread.currentThread())) { + if (!readers.remove(Thread.currentThread())) { throw new IllegalStateException( "Cannot release read lock because current thread has not acquired it."); } - if (_readers.size() == 0) { + if (readers.size() == 0) { notifyAll(); } } @@ -99,26 +98,26 @@ public class ReadWriteLock { /** * Acquires the lock for writing. This call will block until the lock has * been acquired. - * - * @throws IllegalStateException Thrown if the read or write lock is - * already acquired. + * + * @throws IllegalStateException + * Thrown if the read or write lock is already acquired. */ public synchronized void acquireWrite() { - if (_writer == Thread.currentThread()) { + if (writer == Thread.currentThread()) { throw new IllegalStateException( - "Trying to acquire a write lock while already holding the write lock: " - + Thread.currentThread()); + "Trying to acquire a write lock while already holding the write lock: " + + Thread.currentThread()); } - if (_readers.contains(Thread.currentThread())) { + if (readers.contains(Thread.currentThread())) { throw new IllegalStateException( - "Trying to acquire a write lock while already holding the read lock: " - + Thread.currentThread()); + "Trying to acquire a write lock while already holding the read lock: " + + Thread.currentThread()); } // wait until there are no more writers and no more - // readers - while ((_writer != null) || (_readers.size() > 0)) { + // readers + while ((writer != null) || (readers.size() > 0)) { try { wait(); } catch (InterruptedException e) { @@ -126,7 +125,7 @@ public class ReadWriteLock { } } - _writer = Thread.currentThread(); + writer = Thread.currentThread(); // notification not necessary since all writers and // readers are now blocked by this thread. @@ -134,16 +133,17 @@ public class ReadWriteLock { /** * Releases the lock for writing. - * - * @throws IllegalStateException Thrown when the lock was not acquired. + * + * @throws IllegalStateException + * Thrown when the lock was not acquired. */ public synchronized void releaseWrite() { - if (_writer != Thread.currentThread()) { + if (writer != Thread.currentThread()) { throw new IllegalStateException( "Cannot release write lock because it was not acquired. "); } - _writer = null; + writer = null; notifyAll(); } } diff --git a/support/general/src/main/java/org/wamblee/conditions/AndCondition.java b/support/general/src/main/java/org/wamblee/conditions/AndCondition.java index 50898739..0964b941 100644 --- a/support/general/src/main/java/org/wamblee/conditions/AndCondition.java +++ b/support/general/src/main/java/org/wamblee/conditions/AndCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.conditions; import java.util.ArrayList; @@ -21,12 +20,12 @@ import java.util.List; /** * Represents a logical and of different boolean conditions. - * + * * @author Erik Brakkee + * */ public class AndCondition implements Condition { - - private List> _conditions; + private List> conditions; /** * Constructs the condition. @@ -37,9 +36,9 @@ public class AndCondition implements Condition { * Second condition. */ public AndCondition(Condition aCondition1, Condition aCondition2) { - _conditions = new ArrayList>(); - _conditions.add(aCondition1); - _conditions.add(aCondition2); + conditions = new ArrayList>(); + conditions.add(aCondition1); + conditions.add(aCondition2); } /** @@ -49,21 +48,23 @@ public class AndCondition implements Condition { * List of conditions to use in the logical and. */ public AndCondition(List> aConditions) { - _conditions = aConditions; + conditions = aConditions; } /* * (non-Javadoc) * - * @see org.wamblee.crawler.kiss.ProgramMatcher#matches(org.wamblee.crawler.kiss.Program) + * @see + * org.wamblee.crawler.kiss.ProgramMatcher#matches(org.wamblee.crawler.kiss + * .Program) */ public boolean matches(T aObject) { - for (Condition condition : _conditions) { + for (Condition condition : conditions) { if (!condition.matches(aObject)) { return false; } } + return true; } - } diff --git a/support/general/src/main/java/org/wamblee/conditions/Condition.java b/support/general/src/main/java/org/wamblee/conditions/Condition.java index bf4c217a..8e3de50c 100644 --- a/support/general/src/main/java/org/wamblee/conditions/Condition.java +++ b/support/general/src/main/java/org/wamblee/conditions/Condition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; - /** * Determines if an object matches a certain condition. - * + * * @author Erik Brakkee */ public interface Condition { - /** - * Determines if an object matches a condition. - * @param aObject object to match. - * @return True iff the object matches. + * Determines if an object matches a condition. + * + * @param aObject + * object to match. + * + * @return True iff the object matches. */ - boolean matches(T aObject); + boolean matches(T aObject); } diff --git a/support/general/src/main/java/org/wamblee/conditions/FixedCondition.java b/support/general/src/main/java/org/wamblee/conditions/FixedCondition.java index eff83b1b..72840b08 100644 --- a/support/general/src/main/java/org/wamblee/conditions/FixedCondition.java +++ b/support/general/src/main/java/org/wamblee/conditions/FixedCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,31 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; /** - * Condition which always returns a fixed value. - * + * Condition which always returns a fixed value. + * * @author Erik Brakkee + * */ public class FixedCondition implements Condition { - - private boolean _value; - + private boolean value; + /** - * Constructs the condition. - * @param aValue Fixed value of the condition. + * Constructs the condition. + * + * @param aValue + * Fixed value of the condition. */ - public FixedCondition(boolean aValue) { - _value = aValue; + public FixedCondition(boolean aValue) { + value = aValue; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.conditions.Condition#matches(T) */ public boolean matches(T aObject) { - return _value; + return value; } - } diff --git a/support/general/src/main/java/org/wamblee/conditions/OrCondition.java b/support/general/src/main/java/org/wamblee/conditions/OrCondition.java index 0840c78b..3d645ad6 100644 --- a/support/general/src/main/java/org/wamblee/conditions/OrCondition.java +++ b/support/general/src/main/java/org/wamblee/conditions/OrCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.conditions; import java.util.ArrayList; @@ -21,12 +20,12 @@ import java.util.List; /** * Represents a logical or of different boolean conditions. - * + * * @author Erik Brakkee + * */ public class OrCondition implements Condition { - - private List> _conditions; + private List> conditions; /** * Constructs the condition. @@ -37,9 +36,9 @@ public class OrCondition implements Condition { * Second condition. */ public OrCondition(Condition aCondition1, Condition aCondition2) { - _conditions = new ArrayList>(); - _conditions.add(aCondition1); - _conditions.add(aCondition2); + conditions = new ArrayList>(); + conditions.add(aCondition1); + conditions.add(aCondition2); } /** @@ -49,21 +48,23 @@ public class OrCondition implements Condition { * List of conditions to use in the logical or. */ public OrCondition(List> aConditions) { - _conditions = aConditions; + conditions = aConditions; } /* * (non-Javadoc) * - * @see org.wamblee.crawler.kiss.ProgramMatcher#matches(org.wamblee.crawler.kiss.Program) + * @see + * org.wamblee.crawler.kiss.ProgramMatcher#matches(org.wamblee.crawler.kiss + * .Program) */ public boolean matches(T aObject) { - for (Condition condition : _conditions) { + for (Condition condition : conditions) { if (condition.matches(aObject)) { return true; } } + return false; } - } diff --git a/support/general/src/main/java/org/wamblee/conditions/PropertyRegexCondition.java b/support/general/src/main/java/org/wamblee/conditions/PropertyRegexCondition.java index 2ce7a0e9..97550904 100644 --- a/support/general/src/main/java/org/wamblee/conditions/PropertyRegexCondition.java +++ b/support/general/src/main/java/org/wamblee/conditions/PropertyRegexCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,61 +13,72 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; +import org.apache.commons.beanutils.PropertyUtils; + import java.lang.reflect.InvocationTargetException; + import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.beanutils.PropertyUtils; - /** - * Condition to check whether a given property value matches a certain - * regular expression. - * + * Condition to check whether a given property value matches a certain regular + * expression. + * * @author Erik Brakkee + * */ public class PropertyRegexCondition implements Condition { - /** - * Property name. + * Property name. */ - private String _property; - + private String property; + /** - * Regular expression. + * Regular expression. */ - private Pattern _regex; - + private Pattern regex; + /** - * Whether or not to convert the value to lowercase before matching. + * Whether or not to convert the value to lowercase before matching. */ - private boolean _tolower; - + private boolean tolower; + /** - * Constructs the condition. - * @param aProperty Name of the property to examine. - * @param aRegex Regular expression to use. - * @param aTolower Whether or not to convert the value to lowercase before matching. + * Constructs the condition. + * + * @param aProperty + * Name of the property to examine. + * @param aRegex + * Regular expression to use. + * @param aTolower + * Whether or not to convert the value to lowercase before + * matching. */ - public PropertyRegexCondition(String aProperty, String aRegex, boolean aTolower) { - _property = aProperty; - _regex = Pattern.compile(aRegex); - _tolower = aTolower; + public PropertyRegexCondition(String aProperty, String aRegex, + boolean aTolower) { + property = aProperty; + regex = Pattern.compile(aRegex); + tolower = aTolower; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.conditions.Condition#matches(T) */ public boolean matches(T aObject) { try { - String value = PropertyUtils.getProperty(aObject, _property) + ""; - if ( _tolower ) { - value = value.toLowerCase(); + String value = PropertyUtils.getProperty(aObject, property) + ""; + + if (tolower) { + value = value.toLowerCase(); } - Matcher matcher = _regex.matcher(value); - return matcher.matches(); + + Matcher matcher = regex.matcher(value); + + return matcher.matches(); } catch (IllegalAccessException e) { throw new RuntimeException(e.getMessage(), e); } catch (InvocationTargetException e) { diff --git a/support/general/src/main/java/org/wamblee/general/BeanFactory.java b/support/general/src/main/java/org/wamblee/general/BeanFactory.java index 56844bd7..bee62b1b 100644 --- a/support/general/src/main/java/org/wamblee/general/BeanFactory.java +++ b/support/general/src/main/java/org/wamblee/general/BeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,40 +16,23 @@ package org.wamblee.general; /** - * Bean factory used to obtain objects in a transparent way. - * + * Bean factory used to obtain objects in a transparent way. + * * @author Erik Brakkee */ public interface BeanFactory { - - /** - * Finds a bean based on id. - * @param aId Id of the bean. - * @return Object (always non-null). - * @throws BeanFactoryException In case the object could not be found. - */ - Object find(String aId); - /** - * Finds a bean of the given class and which can be cast to the - * specified class. This is typically used by specifying the interface - * class for retrieving an implementation of that class. This - * means that the bean implementing the class is configured in the bean factory - * with id equal to the class name of the interface. - * @param aClass Class of the object to find. + * Finds a bean based on id. + * + * @param aId + * Id of the bean. * @return Object (always non-null). - * @throws BeanFactoryException In case the object could not be found. + * @throws BeanFactoryException + * In case the object could not be found. */ - T find(Class aClass); - - /** - * Finds a bean with the given id which can be cast to the specified - * class. - * @param Type of the object to get. - * @param aId Id of the object to lookup. - * @param aClass Class that the object must extends. - * @return Object, always non-null. - * @throws BeanFactoryException In case the object could not be found. - */ - T find(String aId, Class aClass); + Object find(String aId); + + T find(Class aClass); + + T find(String aId, Class aClass); } diff --git a/support/general/src/main/java/org/wamblee/general/BeanFactoryException.java b/support/general/src/main/java/org/wamblee/general/BeanFactoryException.java index 9110db9b..125fd8bf 100644 --- a/support/general/src/main/java/org/wamblee/general/BeanFactoryException.java +++ b/support/general/src/main/java/org/wamblee/general/BeanFactoryException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,25 +16,30 @@ package org.wamblee.general; /** - * Exception thrown by the BeanFactory if an object could not be found. - * + * Exception thrown by the BeanFactory if an object could not be found. + * * @author Erik Brakkee */ public class BeanFactoryException extends RuntimeException { static final long serialVersionUID = -1215992188624874902L; /** - * Constructs the exception. - * @param aMsg Message. + * Constructs the exception. + * + * @param aMsg + * Message. */ - public BeanFactoryException(String aMsg) { - super(aMsg); + public BeanFactoryException(String aMsg) { + super(aMsg); } - + /** - * Constructs the exception. - * @param aMsg Message. - * @param aThrowable Cause of the exception. + * Constructs the exception. + * + * @param aMsg + * Message. + * @param aThrowable + * Cause of the exception. */ public BeanFactoryException(String aMsg, Throwable aThrowable) { super(aMsg, aThrowable); diff --git a/support/general/src/main/java/org/wamblee/general/BeanKernel.java b/support/general/src/main/java/org/wamblee/general/BeanKernel.java index d05eef3d..619c7da3 100644 --- a/support/general/src/main/java/org/wamblee/general/BeanKernel.java +++ b/support/general/src/main/java/org/wamblee/general/BeanKernel.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,20 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.general; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.wamblee.io.ClassPathResource; import org.wamblee.io.InputResource; +import java.io.IOException; +import java.io.InputStream; + +import java.util.Properties; + /** * The standard means to obtain the bean factory. This works by reading a * property {@value #BEAN_FACTORY_CLASS} from a property file named @@ -32,7 +34,6 @@ import org.wamblee.io.InputResource; * a no-arg constructor. */ public final class BeanKernel { - private static final Log LOG = LogFactory.getLog(BeanKernel.class); /** @@ -81,32 +82,39 @@ public final class BeanKernel { BEAN_FACTORY = lookupBeanFactory(BEAN_KERNEL_PROP_FILE); } } + return BEAN_FACTORY; } /** * Lookup the bean factory based on the properties file. * + * * @return Bean factory. + * */ static BeanFactory lookupBeanFactory(String aPropertyFilename) { InputResource resource = new ClassPathResource(aPropertyFilename); InputStream is; + try { is = resource.getInputStream(); } catch (IOException e) { throw new BeanFactoryException("Cannot open resource " + resource, - e); + e); } + try { Properties props = new Properties(); props.load(is); + String className = props.getProperty(BEAN_FACTORY_CLASS); Class beanFactory = Class.forName(className); + return (BeanFactory) beanFactory.newInstance(); } catch (Exception e) { - throw new BeanFactoryException("Cannot read from resource " - + resource, e); + throw new BeanFactoryException("Cannot read from resource " + + resource, e); } finally { try { is.close(); diff --git a/support/general/src/main/java/org/wamblee/general/ClassLoaderUtils.java b/support/general/src/main/java/org/wamblee/general/ClassLoaderUtils.java index 5275e159..27245ddf 100644 --- a/support/general/src/main/java/org/wamblee/general/ClassLoaderUtils.java +++ b/support/general/src/main/java/org/wamblee/general/ClassLoaderUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,31 +12,32 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.general; -import java.io.IOException; import java.io.File; -import java.net.URLClassLoader; -import java.net.URL; +import java.io.IOException; + import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; + /** * Utility for working with the class loader. Based on the ClassPathHacker - * example found on the internet. + * example found on the internet. */ public class ClassLoaderUtils { - // No logging in this class to keep the required class libraries // limited to the standard java classes. This allows use of the - // utilities in an environment with a very limited classpath. - + // utilities in an environment with a very limited classpath. private static final String JAR_SUFFIX = ".jar"; /** - * Adds all jars in the given directory to the class path. - * @param aDirectory Directory. + * Adds all jars in the given directory to the class path. + * + * @param aDirectory + * Directory. * @throws IOException */ public static void addJarsInDirectory(File aDirectory) throws IOException { @@ -44,10 +45,11 @@ public class ClassLoaderUtils { for (File aFile : aDirectory.listFiles()) { System.out - .println("Considering '" + aFile.getCanonicalPath() + "'"); + .println("Considering '" + aFile.getCanonicalPath() + "'"); + if (aFile.getName().toLowerCase().endsWith(JAR_SUFFIX)) { - System.out.println("Adding '" + aFile.getCanonicalPath() - + "' to classpath."); + System.out.println("Adding '" + aFile.getCanonicalPath() + + "' to classpath."); addFile(aFile); } } @@ -55,7 +57,9 @@ public class ClassLoaderUtils { /** * Adds a file to the classpath. - * @param aFilename Filename to add. + * + * @param aFilename + * Filename to add. * @throws IOException */ public static void addFile(String aFilename) throws IOException { @@ -64,8 +68,10 @@ public class ClassLoaderUtils { } /** - * Adds a file to the classpath. - * @param aFile File to add. + * Adds a file to the classpath. + * + * @param aFile + * File to add. * @throws IOException */ public static void addFile(File aFile) throws IOException { @@ -74,25 +80,25 @@ public class ClassLoaderUtils { /** * Adds a url to the classpath. - * @param aUrl Url to add. + * + * @param aUrl + * Url to add. * @throws IOException */ public static void addURL(URL aUrl) throws IOException { - URLClassLoader sysloader = (URLClassLoader) ClassLoader - .getSystemClassLoader(); + .getSystemClassLoader(); Class sysclass = URLClassLoader.class; try { - Method method = sysclass.getDeclaredMethod("addURL", new Class[]{ URL.class } ); + Method method = sysclass.getDeclaredMethod("addURL", + new Class[] { URL.class }); method.setAccessible(true); method.invoke(sysloader, new Object[] { aUrl }); } catch (Throwable t) { t.printStackTrace(); throw new IOException( - "Error, could not add URL to system classloader"); + "Error, could not add URL to system classloader"); } - } - } diff --git a/support/general/src/main/java/org/wamblee/general/Pair.java b/support/general/src/main/java/org/wamblee/general/Pair.java index 2d90387f..4ea88079 100644 --- a/support/general/src/main/java/org/wamblee/general/Pair.java +++ b/support/general/src/main/java/org/wamblee/general/Pair.java @@ -1,8 +1,5 @@ - - - /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.general; /** @@ -26,14 +23,12 @@ package org.wamblee.general; * Type of the first object. * @param * Type of the second object. - * + * * @author Erik Brakkee */ public class Pair { - - private T _t; - - private U _u; + private T t; + private U u; /** * Constructs the pair. @@ -44,8 +39,8 @@ public class Pair { * Second object. */ public Pair(T aT, U aU) { - _t = aT; - _u = aU; + t = aT; + u = aU; } /** @@ -55,8 +50,8 @@ public class Pair { * Pair to copy. */ public Pair(Pair aPair) { - _t = aPair._t; - _u = aPair._u; + t = aPair.t; + u = aPair.u; } /** @@ -65,7 +60,7 @@ public class Pair { * @return First object. */ public T getFirst() { - return _t; + return t; } /** @@ -74,7 +69,6 @@ public class Pair { * @return Second object. */ public U getSecond() { - return _u; + return u; } - } diff --git a/support/general/src/main/java/org/wamblee/io/ClassPathResource.java b/support/general/src/main/java/org/wamblee/io/ClassPathResource.java index 32014a10..5cd67853 100644 --- a/support/general/src/main/java/org/wamblee/io/ClassPathResource.java +++ b/support/general/src/main/java/org/wamblee/io/ClassPathResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; import java.io.IOException; @@ -25,7 +25,7 @@ public class ClassPathResource implements InputResource { /** * Resource name. */ - private String _resource; + private String resource; /** * Construct the class path resource. @@ -34,7 +34,7 @@ public class ClassPathResource implements InputResource { * Resource */ public ClassPathResource(String aResource) { - _resource = aResource; + resource = aResource; } /* @@ -44,11 +44,13 @@ public class ClassPathResource implements InputResource { */ public InputStream getInputStream() throws IOException { InputStream stream = Thread.currentThread().getContextClassLoader() - .getResourceAsStream(_resource); + .getResourceAsStream(resource); + if (stream == null) { - throw new IOException("Class path resource '" + _resource - + "' not found."); + throw new IOException("Class path resource '" + resource + + "' not found."); } + return stream; } @@ -58,6 +60,6 @@ public class ClassPathResource implements InputResource { * @see java.lang.Object#toString() */ public String toString() { - return "ClassPathResource(" + _resource + ")"; + return "ClassPathResource(" + resource + ")"; } } diff --git a/support/general/src/main/java/org/wamblee/io/DirectoryMonitor.java b/support/general/src/main/java/org/wamblee/io/DirectoryMonitor.java index 029f33ef..a4ad6d87 100644 --- a/support/general/src/main/java/org/wamblee/io/DirectoryMonitor.java +++ b/support/general/src/main/java/org/wamblee/io/DirectoryMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,97 +12,109 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.io; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import java.io.File; import java.io.FileFilter; + import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * Monitors a directory for changes. * * @author Erik Brakkee */ public class DirectoryMonitor { + private static final Log LOG = LogFactory.getLog(DirectoryMonitor.class); + + private File directory; + + private FileFilter filter; + + private Listener listener; + + private Map contents; + + /** + * Creates a new DirectoryMonitor object. + * + */ + public DirectoryMonitor(File aDirectory, FileFilter aFilefilter, + Listener aListener) { + directory = aDirectory; + + if (!directory.isDirectory()) { + throw new IllegalArgumentException("Directory '" + directory + + "' does not exist"); + } + + filter = aFilefilter; + listener = aListener; + contents = new HashMap(); + } + + /** + * Polls the directory for changes and notifies the listener of any changes. + * In case of any exceptions thrown by the listener while handling the + * changes, the next call to this method will invoked the listeners again + * for the same changes. + */ + public void poll() { + LOG.debug("Polling " + directory); + + Map newContents = new HashMap(); + File[] files = directory.listFiles(filter); + + // Check deleted files. + Set deletedFiles = new HashSet(contents.keySet()); + + for (File file : files) { + if (file.isFile()) { + if (contents.containsKey(file)) { + deletedFiles.remove(file); + } + } + } + + for (File file : deletedFiles) { + listener.fileDeleted(file); + } + + for (File file : files) { + if (file.isFile()) { + if (contents.containsKey(file)) { + Date oldDate = contents.get(file); + + if (file.lastModified() != oldDate.getTime()) { + listener.fileChanged(file); + } else { + // No change. + } + + newContents.put(file, new Date(file.lastModified())); + } else { + listener.fileCreated(file); + newContents.put(file, new Date(file.lastModified())); + } + } + } + + contents = newContents; + } + + public static interface Listener { + void fileChanged(File aFile); - private static final Log LOG = LogFactory.getLog(DirectoryMonitor.class); - - public static interface Listener { - - void fileChanged(File aFile); - - void fileCreated(File aFile); - - void fileDeleted(File aFile); - }; - - private File _directory; - private FileFilter _filter; - private Listener _listener; - private Map _contents; - - public DirectoryMonitor(File aDirectory, FileFilter aFilefilter, - Listener aListener) { - _directory = aDirectory; - if (!_directory.isDirectory()) { - throw new IllegalArgumentException("Directory '" + _directory - + "' does not exist"); - } - _filter = aFilefilter; - _listener = aListener; - _contents = new HashMap(); - } - - /** - * Polls the directory for changes and notifies the listener of any changes. - * In case of any exceptions thrown by the listener while handling the changes, - * the next call to this method will invoked the listeners again for the same changes. - */ - public void poll() { - LOG.debug("Polling " + _directory); - Map newContents = new HashMap(); - File[] files = _directory.listFiles(_filter); - - // Check deleted files. - Set deletedFiles = new HashSet(_contents.keySet()); - for (File file : files) { - if (file.isFile()) { - if (_contents.containsKey(file)) { - deletedFiles.remove(file); - } - } - } - for (File file : deletedFiles) { - _listener.fileDeleted(file); - } - - for (File file : files) { - if (file.isFile()) { - if (_contents.containsKey(file)) { - Date oldDate = _contents.get(file); - if (file.lastModified() != oldDate.getTime()) { - _listener.fileChanged(file); - } else { - // No change. - } - newContents.put(file, new Date(file.lastModified())); - } else { - _listener.fileCreated(file); - newContents.put(file, new Date(file.lastModified())); - } - } - } - - _contents = newContents; - } + void fileCreated(File aFile); + void fileDeleted(File aFile); + } } diff --git a/support/general/src/main/java/org/wamblee/io/FileResource.java b/support/general/src/main/java/org/wamblee/io/FileResource.java index 4f8c0ad9..f62ecc8a 100644 --- a/support/general/src/main/java/org/wamblee/io/FileResource.java +++ b/support/general/src/main/java/org/wamblee/io/FileResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; import java.io.BufferedInputStream; @@ -23,14 +23,14 @@ import java.io.InputStream; /** * Resource implemention for reading from a file. - * + * * @author Erik Brakkee */ public class FileResource implements InputResource { /** * File to read. */ - private File _file; + private File file; /** * Constructs the resource. @@ -39,7 +39,7 @@ public class FileResource implements InputResource { * File to read. */ public FileResource(File aFile) { - _file = aFile; + file = aFile; } /* @@ -48,6 +48,6 @@ public class FileResource implements InputResource { * @see org.wamblee.io.InputResource#getInputStream() */ public InputStream getInputStream() throws IOException { - return new BufferedInputStream(new FileInputStream(_file)); + return new BufferedInputStream(new FileInputStream(file)); } } diff --git a/support/general/src/main/java/org/wamblee/io/InputResource.java b/support/general/src/main/java/org/wamblee/io/InputResource.java index 2a0e8cda..58d61f08 100644 --- a/support/general/src/main/java/org/wamblee/io/InputResource.java +++ b/support/general/src/main/java/org/wamblee/io/InputResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; import java.io.IOException; @@ -20,7 +20,7 @@ import java.io.InputStream; /** * Represents a resource from which information can be read. - * + * * @author Erik Brakkee */ public interface InputResource { @@ -29,6 +29,7 @@ public interface InputResource { * closed once reading has finished. * * @return Input stream to the resource, never null. + * * @throws IOException * in case the resource cannot be found. */ diff --git a/support/general/src/main/java/org/wamblee/io/SimpleProcess.java b/support/general/src/main/java/org/wamblee/io/SimpleProcess.java index d4f7b16b..5e18b16c 100644 --- a/support/general/src/main/java/org/wamblee/io/SimpleProcess.java +++ b/support/general/src/main/java/org/wamblee/io/SimpleProcess.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,149 +20,173 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; import java.io.StringWriter; import java.io.Writer; +import java.util.Arrays; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +/** + * + * @author $author$ + * @version $Revision$ + */ public class SimpleProcess { + private static final Log LOG = LogFactory.getLog(SimpleProcess.class); - private static final Log LOG = LogFactory.getLog(SimpleProcess.class); + private File directory; - private File _directory; + private String[] cmd; - private String[] _cmd; - - private String _stdout; - private String _stderr; + private String stdout; - public SimpleProcess(File aDirectory, String[] aCmd) { - _directory = aDirectory; - _cmd = aCmd; - } + private String stderr; /** + * Creates a new SimpleProcess object. + * + */ + public SimpleProcess(File aDirectory, String[] aCmd) { + directory = aDirectory; + cmd = Arrays.copyOf(aCmd, aCmd.length); + } + + /** + * * @return the stdout */ public String getStdout() { - return _stdout; + return stdout; } - + /** + * * @return the stderr */ public String getStderr() { - return _stderr; + return stderr; + } + + /** + * Runs the process and blocks until it is done. + * + * @return Exit status of the process. + * + * @throws IOException + * In case of problems. + */ + public int run() throws IOException { + return runImpl(); + } + + private int runImpl() throws IOException { + try { + StringBuffer fullcmd = new StringBuffer(); + + for (String part : cmd) { + fullcmd.append(" " + part); + } + + LOG.debug("Executing '" + fullcmd + "' in directory '" + directory + + "'"); + + java.lang.Process proc = Runtime.getRuntime().exec(cmd, null, + directory); + + // Read standard output and error in separate threads to avoid + // deadlock. + StringWriter myStdout = new StringWriter(); + StringWriter myStderr = new StringWriter(); + Thread stdoutReader = readAndLogStream("STDOUT> ", proc + .getInputStream(), myStdout); + Thread stderrReader = readAndLogStream("STDERR> ", proc + .getErrorStream(), myStderr); + + try { + proc.waitFor(); + } catch (InterruptedException e) { + IOException exception = new IOException( + "Process was terminated: " + this); + exception.initCause(e); + throw exception; + } + + waitForReader(stdoutReader); + waitForReader(stderrReader); + + stdout = myStdout.toString(); + stderr = myStderr.toString(); + + if (proc.exitValue() != 0) { + LOG.warn("Exit value was non-zero: " + this); + } else { + LOG.debug("Process finished"); + } + + return proc.exitValue(); + } catch (IOException e) { + IOException exception = new IOException( + "Error executing process: " + this); + exception.initCause(e); + throw exception; + } } - - /** - * Runs the process and blocks until it is done. - * - * @return Exit status of the process. - * @throws IOException - * In case of problems. - */ - public int run() throws IOException { - return runImpl(); - } - - private int runImpl() throws IOException { - try { - String fullcmd = ""; - for (String part: _cmd) { - fullcmd += " " + part; - } - LOG.debug("Executing '" + fullcmd + "' in directory '" + _directory - + "'"); - java.lang.Process proc = Runtime.getRuntime().exec(_cmd, null, _directory); - - // Read standard output and error in separate threads to avoid - // deadlock. - - StringWriter stdout = new StringWriter(); - StringWriter stderr = new StringWriter(); - Thread stdoutReader = readAndLogStream("STDOUT> ", proc - .getInputStream(), stdout); - Thread stderrReader = readAndLogStream("STDERR> ", proc - .getErrorStream(), stderr); - - try { - proc.waitFor(); - } catch (InterruptedException e) { - IOException exception = new IOException( - "Process was terminated: " + this); - exception.initCause(e); - throw exception; - } - waitForReader(stdoutReader); - waitForReader(stderrReader); - - _stdout = stdout.toString(); - _stderr = stderr.toString(); - - if (proc.exitValue() != 0) { - LOG.warn("Exit value was non-zero: " + this); - } else { - LOG.debug("Process finished"); - } - return proc.exitValue(); - } catch (IOException e) { - IOException exception = new IOException("Error executing process: " - + this); - exception.initCause(e); - throw exception; - } - } - - private void waitForReader(Thread aReaderThread) { - try { - aReaderThread.join(); - } catch (InterruptedException e) { - LOG - .warn(this - + ": error waiting for output stream reader of process to finish"); - } - } - - private Thread readAndLogStream(final String aPrefix, - final InputStream aStream, final Writer aOutput) { - Thread inputReader = new Thread() { - @Override - public void run() { - BufferedReader br = null; - try { - br = new BufferedReader(new InputStreamReader(aStream)); - String str; - while ((str = br.readLine()) != null) { - LOG.debug(aPrefix + str); + + private void waitForReader(Thread aReaderThread) { + try { + aReaderThread.join(); + } catch (InterruptedException e) { + LOG + .warn(this + + ": error waiting for output stream reader of process to finish"); + } + } + + private Thread readAndLogStream(final String aPrefix, + final InputStream aStream, final Writer aOutput) { + Thread inputReader = new Thread() { + @Override + public void run() { + BufferedReader br = null; + + try { + br = new BufferedReader(new InputStreamReader(aStream)); + + String str; + + while ((str = br.readLine()) != null) { + LOG.debug(aPrefix + str); aOutput.write(str); - } - } catch (IOException e) { - LOG.warn(SimpleProcess.this + ": error reading input stream", e); - } finally { - if (br != null) { - try { - br.close(); - } catch (IOException e) { - LOG.warn("Error closing stream " + aPrefix); - } - } - } - } - }; - inputReader.start(); - return inputReader; - } - - @Override - public String toString() { - String fullcmd = ""; - for (String part: _cmd) { - fullcmd += part + " "; + } + } catch (IOException e) { + LOG.warn(SimpleProcess.this + + ": error reading input stream", e); + } finally { + if (br != null) { + try { + br.close(); + } catch (IOException e) { + LOG.warn("Error closing stream " + aPrefix); + } + } + } + } + }; + + inputReader.start(); + + return inputReader; + } + + @Override + public String toString() { + StringBuffer fullcmd = new StringBuffer(); + + for (String part : cmd) { + fullcmd.append(part + " "); } - return "process(dir = '" + _directory + "', cmd = '" + fullcmd + "')"; - } + + return "process(dir = '" + directory + "', cmd = '" + fullcmd + "')"; + } } diff --git a/support/general/src/main/java/org/wamblee/io/StreamResource.java b/support/general/src/main/java/org/wamblee/io/StreamResource.java index e3291aeb..9aae3d32 100644 --- a/support/general/src/main/java/org/wamblee/io/StreamResource.java +++ b/support/general/src/main/java/org/wamblee/io/StreamResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; import java.io.IOException; @@ -20,14 +20,14 @@ import java.io.InputStream; /** * Input resource based on an input stream. - * + * * @author Erik Brakkee */ public class StreamResource implements InputResource { /** * Input stream to read. */ - private InputStream _stream; + private InputStream stream; /** * Constructs a resource. @@ -36,7 +36,7 @@ public class StreamResource implements InputResource { * Input stream to read. */ public StreamResource(InputStream aStream) { - _stream = aStream; + stream = aStream; } /* @@ -45,6 +45,6 @@ public class StreamResource implements InputResource { * @see InputResource#getInputStream() */ public InputStream getInputStream() throws IOException { - return _stream; + return stream; } } diff --git a/support/general/src/main/java/org/wamblee/observer/DefaultObserverNotifier.java b/support/general/src/main/java/org/wamblee/observer/DefaultObserverNotifier.java index 0b14585c..e6ba0134 100644 --- a/support/general/src/main/java/org/wamblee/observer/DefaultObserverNotifier.java +++ b/support/general/src/main/java/org/wamblee/observer/DefaultObserverNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,20 +12,18 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.observer; /** * Default observer notifier which calls * {@link org.wamblee.observer.Observer#send(ObservableType, Event)} * immediately. - * + * * @author Erik Brakkee */ public class DefaultObserverNotifier implements - ObserverNotifier { - + ObserverNotifier { /** * Constructs the notifier. * @@ -37,11 +35,12 @@ public class DefaultObserverNotifier implements /* * (non-Javadoc) * - * @see org.wamblee.observer.ObserverNotifier#update(org.wamblee.observer.Observer, - * ObservableType, Event) + * @see + * org.wamblee.observer.ObserverNotifier#update(org.wamblee.observer.Observer + * , ObservableType, Event) */ public void update(Observer aObserver, - ObservableType aObservable, Event aEvent) { + ObservableType aObservable, Event aEvent) { aObserver.send(aObservable, aEvent); } } diff --git a/support/general/src/main/java/org/wamblee/observer/Observable.java b/support/general/src/main/java/org/wamblee/observer/Observable.java index 2980afaf..5c2e9a4f 100644 --- a/support/general/src/main/java/org/wamblee/observer/Observable.java +++ b/support/general/src/main/java/org/wamblee/observer/Observable.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,44 +12,42 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.observer; -import java.util.List; +import org.apache.log4j.Logger; + import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.TreeMap; -import org.apache.log4j.Logger; - /** * Implements subscription and notification logic for an observer pattern. This * class is thread safe. */ public class Observable { - private static final Logger LOGGER = Logger.getLogger(Observable.class); /** * Observable. */ - private ObservableType _observable; + private ObservableType observable; /** * Used to notify observers. */ - private ObserverNotifier _notifier; + private ObserverNotifier notifier; /** * Map of subscription to observer. */ - private Map> _observers; + private Map> observers; /** * Counter for subscriptions. Holds the next subscription. */ - private long _counter; + private long counter; /** * Constructs the observable. @@ -60,11 +58,11 @@ public class Observable { * Object used for implementing notification of listeners. */ public Observable(ObservableType aObservable, - ObserverNotifier aNotifier) { - _observable = aObservable; - _notifier = aNotifier; - _observers = new TreeMap>(); - _counter = 0; + ObserverNotifier aNotifier) { + observable = aObservable; + notifier = aNotifier; + observers = new TreeMap>(); + counter = 0; } /** @@ -75,9 +73,11 @@ public class Observable { * @return Event Event to send. */ public synchronized long subscribe(Observer aObserver) { - long subscription = _counter++; // integer rage is so large it will - // never roll over. - _observers.put(subscription, aObserver); + long subscription = counter++; // integer rage is so large it will + // never roll over. + + observers.put(subscription, aObserver); + return subscription; } @@ -90,10 +90,11 @@ public class Observable { * In case the subscription is not known. */ public synchronized void unsubscribe(long aSubscription) { - Object obj = _observers.remove(aSubscription); + Object obj = observers.remove(aSubscription); + if (obj == null) { - throw new IllegalArgumentException("Subscription '" + aSubscription - + "'"); + throw new IllegalArgumentException("Subscription '" + + aSubscription + "'"); } } @@ -103,7 +104,7 @@ public class Observable { * @return Number of subscribed observers. */ public int getObserverCount() { - return _observers.size(); + return observers.size(); } /** @@ -116,31 +117,14 @@ public class Observable { // Make sure we do the notification while not holding the lock to avoid // potential deadlock // situations. - List> observers = new ArrayList>(); + List> myObservers = new ArrayList>(); + synchronized (this) { - observers.addAll(_observers.values()); + myObservers.addAll(observers.values()); } - for (Observer observer : observers) { - _notifier.update(observer, _observable, aEvent); - } - } - /* - * (non-Javadoc) - * - * @see java.lang.Object#finalize() - */ - @Override - protected void finalize() throws Throwable { - if (_observers.size() > 0) { - LOGGER - .error("Still observers registered at finalization of observer!"); - for (Observer observer : _observers.values()) { - LOGGER.error(" observer: " + observer); - } + for (Observer observer : myObservers) { + notifier.update(observer, observable, aEvent); } - - super.finalize(); } - } diff --git a/support/general/src/main/java/org/wamblee/observer/Observer.java b/support/general/src/main/java/org/wamblee/observer/Observer.java index a0e64314..bca6436d 100644 --- a/support/general/src/main/java/org/wamblee/observer/Observer.java +++ b/support/general/src/main/java/org/wamblee/observer/Observer.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,20 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.observer; /** - * This is a type-safe version of {@link java.util.Observable}. - * + * This is a type-safe version of {@link java.util.Observable}. + * * @author Erik Brakkee */ public interface Observer { - /** * Called when an event has occurred on the observable. - * @param aObservable Observable. - * @param aEvent Event. + * + * @param aObservable + * Observable. + * @param aEvent + * Event. */ - void send(ObservableType aObservable, Event aEvent); + void send(ObservableType aObservable, Event aEvent); } diff --git a/support/general/src/main/java/org/wamblee/observer/ObserverNotifier.java b/support/general/src/main/java/org/wamblee/observer/ObserverNotifier.java index f09c5f0c..e0ffd926 100644 --- a/support/general/src/main/java/org/wamblee/observer/ObserverNotifier.java +++ b/support/general/src/main/java/org/wamblee/observer/ObserverNotifier.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.observer; /** - * Implementation of notification of subscribers. - * + * Implementation of notification of subscribers. + * * @author Erik Brakkee */ public interface ObserverNotifier { - /** - * Notifies an observer. - * - * @param aObserver Observer to notify - * @param aObservable Observable at which the event occured. - * @param aEvent Event that occured. + * Notifies an observer. + * + * @param aObserver + * Observer to notify + * @param aObservable + * Observable at which the event occured. + * @param aEvent + * Event that occured. */ - void update(Observer aObserver, ObservableType aObservable, Event aEvent); - + void update(Observer aObserver, + ObservableType aObservable, Event aEvent); } diff --git a/support/general/src/main/java/org/wamblee/persistence/JpaMergeSupport.java b/support/general/src/main/java/org/wamblee/persistence/JpaMergeSupport.java new file mode 100644 index 00000000..6230656f --- /dev/null +++ b/support/general/src/main/java/org/wamblee/persistence/JpaMergeSupport.java @@ -0,0 +1,319 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.persistence; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import javax.persistence.EntityManager; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wamblee.persistence.PersistentFactory.EntityAccessor; +import org.wamblee.reflection.ReflectionUtils; + +/** + * Support for merging of JPA entities. This utility allows the result of a + * merge (modifications of primary key and/or version) to be merged back into + * the argument that was merged. As a result, the merged entity can be reused + * and the application is not forced to use the new version that was returned + * from the merge. + * + * The utility traverses the object graph based on the public getter methods. + * Therefore, care should be taken with this utility as usage could lead to + * recursively loading all objects reachable from the given object. Then again, + * this utility is for working with detached objects and it would, in general, + * be bad practice to work with detached objects that still contain unresolved + * lazy loaded relations and with detached objects that implicitly refer to + * almost the entire datamodel. + * + * This utility best supports a service oriented design where interaction is + * through service interfaces where each service has its own storage isolated + * from other services. That would be opposed to a shared data design with many + * services acting on the same data. + * + * @author Erik Brakkee + */ +public class JpaMergeSupport { + private static final Log LOG = LogFactory.getLog(JpaMergeSupport.class); + + /** + * Constructs the object. + * + */ + public JpaMergeSupport() { + // Empty + } + + /** + * As {@link #merge(Persistent)} but with a given template. This method can + * be accessed in a static way. + * + * @param aMerge + * The result of the call to {@link EntityManager#merge(Object)}. + * @param aPersistent + * Object that was passed to {@link EntityManager#merge(Object)}. + */ + public static void merge(Object aMerged, Object aPersistent) { + processPersistent(aMerged, aPersistent, new ArrayList()); + } + + /** + * Copies primary keys and version from the result of the merged to the + * object that was passed to the merge operation. It does this by traversing + * the public properties of the object. It copies the primary key and + * version for objects that implement {@link Persistent} and applies the + * same rules to objects in maps and sets as well (i.e. recursively). + * + * @param aPersistent + * Object whose primary key and version are to be set. + * @param aMerged + * Object that was the result of the merge. + * @param aProcessed + * List of already processed Persistent objects of the persistent + * part. + * + */ + public static void processPersistent(Object aMerged, Object aPersistent, + List aProcessed) { + if ((aPersistent == null) && (aMerged == null)) { + return; + } + + if ((aPersistent == null) || (aMerged == null)) { + throw new RuntimeException("persistent or merged object is null '" + + aPersistent + "'" + " '" + aMerged + "'"); + } + + ObjectElem elem = new ObjectElem(aPersistent); + + if (aProcessed.contains(elem)) { + return; // already processed. + } + + aProcessed.add(elem); + + LOG.debug("Setting pk/version on " + aPersistent + " from " + aMerged); + + Persistent persistentWrapper = PersistentFactory.create(aPersistent); + Persistent mergedWrapper = PersistentFactory.create(aMerged); + + if (persistentWrapper == null) { + // Not an entity so it is ignored. + return; + } + + Serializable pk = persistentWrapper.getPrimaryKey(); + boolean pkIsNull = false; + if (pk instanceof Number) { + if (((Number) pk).longValue() != 0l) { + pkIsNull = false; + } else { + pkIsNull = true; + } + } else { + pkIsNull = (pk == null); + } + if (!pkIsNull && + !mergedWrapper.getPrimaryKey().equals( + persistentWrapper.getPrimaryKey())) { + throw new IllegalArgumentException( + "Mismatch between primary key values: " + aPersistent + " " + + aMerged); + } else { + persistentWrapper.setPersistedVersion(mergedWrapper + .getPersistedVersion()); + persistentWrapper.setPrimaryKey(mergedWrapper.getPrimaryKey()); + } + + List methods = ReflectionUtils.getAllMethods(aPersistent + .getClass(), Object.class); + + for (Method getter : methods) { + if ((getter.getName().startsWith("get") || getter.getName() + .startsWith("is")) && + !Modifier.isStatic(getter.getModifiers()) && + Modifier.isPublic(getter.getModifiers()) && + getter.getParameterTypes().length == 0 && + getter.getReturnType() != Void.class) { + Class returnType = getter.getReturnType(); + + try { + if (Set.class.isAssignableFrom(returnType)) { + Set merged = (Set) getter.invoke(aMerged); + Set persistent = (Set) getter.invoke(aPersistent); + processSet(merged, persistent, aProcessed); + } else if (List.class.isAssignableFrom(returnType)) { + List merged = (List) getter.invoke(aMerged); + List persistent = (List) getter.invoke(aPersistent); + processList(merged, persistent, aProcessed); + } else if (Map.class.isAssignableFrom(returnType)) { + Map merged = (Map) getter.invoke(aMerged); + Map persistent = (Map) getter.invoke(aPersistent); + processMap(merged, persistent, aProcessed); + } else if (returnType.isArray()) { + Object[] merged = (Object[]) getter.invoke(aMerged); + Object[] persistent = (Object[]) getter + .invoke(aPersistent); + if (merged.length != persistent.length) { + throw new IllegalArgumentException( + "Array sizes differ " + merged.length + " " + + persistent.length); + } + for (int i = 0; i < persistent.length; i++) { + processPersistent(merged[i], persistent[i], + aProcessed); + } + } else { + Object merged = getter.invoke(aMerged); + Object persistent = getter.invoke(aPersistent); + processPersistent(merged, persistent, aProcessed); + } + } catch (InvocationTargetException e) { + throw new RuntimeException(e.getMessage(), e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + } + } + + /** + * Process the persistent objects in the collections. + * + * @param aPersistent + * Collection in the original object. + * @param aMerged + * Collection as a result of the merge. + * @param aProcessed + * List of processed persistent objects. + * + */ + public static void processList(List aMerged, List aPersistent, + List aProcessed) { + Object[] merged = aMerged.toArray(); + Object[] persistent = aPersistent.toArray(); + + if (merged.length != persistent.length) { + throw new IllegalArgumentException("Array sizes differ " + + merged.length + " " + persistent.length); + } + + for (int i = 0; i < merged.length; i++) { + assert merged[i].equals(persistent[i]); + processPersistent(merged[i], persistent[i], aProcessed); + } + } + + /** + * Process the persistent objects in sets. + * + * @param aPersistent + * Collection in the original object. + * @param aMerged + * Collection as a result of the merge. + * @param aProcessed + * List of processed persistent objects. + * + */ + public static void processSet(Set aMerged, Set aPersistent, + List aProcessed) { + if (aMerged.size() != aPersistent.size()) { + throw new IllegalArgumentException("Array sizes differ " + + aMerged.size() + " " + aPersistent.size()); + } + + for (Object merged : aMerged) { + // Find the object that equals the merged[i] + for (Object persistent : aPersistent) { + if (persistent.equals(merged)) { + processPersistent(merged, persistent, aProcessed); + break; + } + } + } + } + + /** + * Process the Map objects in the collections. + * + * @param aPersistent + * Collection in the original object. + * @param aMerged + * Collection as a result of the merge. + * @param aProcessed + * List of processed persistent objects. + * + */ + public static void processMap(Map aMerged, + Map aPersistent, List aProcessed) { + if (aMerged.size() != aPersistent.size()) { + throw new IllegalArgumentException("Sizes differ " + + aMerged.size() + " " + aPersistent.size()); + } + + Set> entries = aMerged.entrySet(); + + for (Entry entry : entries) { + Key key = entry.getKey(); + if (!aPersistent.containsKey(key)) { + throw new IllegalArgumentException("Key '" + key + + "' not found"); + } + + Value mergedValue = entry.getValue(); + Object persistentValue = aPersistent.get(key); + + processPersistent(mergedValue, persistentValue, aProcessed); + } + } + + /** + * This class provided an equality operation based on the object reference + * of the wrapped object. This is required because we cannto assume that the + * equals operation has any meaning for different types of persistent + * objects. This allows us to use the standard collection classes for + * detecting cyclic dependences and avoiding recursion. + */ + private static final class ObjectElem { + private Object object; + + public ObjectElem(Object aObject) { + object = aObject; + } + + public boolean equals(Object aObj) { + if (aObj == null) { + return false; + } + if (!(aObj instanceof ObjectElem)) { + return false; + } + return ((ObjectElem) aObj).object == object; + } + + public int hashCode() { + return object.hashCode(); + } + } +} diff --git a/support/general/src/main/java/org/wamblee/persistence/Persistent.java b/support/general/src/main/java/org/wamblee/persistence/Persistent.java index 57faf95e..8eac4565 100644 --- a/support/general/src/main/java/org/wamblee/persistence/Persistent.java +++ b/support/general/src/main/java/org/wamblee/persistence/Persistent.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,46 +13,54 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.persistence; import java.io.Serializable; /** - * Interface for persistent objects. This defines required functionality for all objects - * that are persisted. + * Interface for persistent objects. This defines required functionality for all + * objects that are persisted. * - * Objects that implement this interface and which implement - * {@link java.lang.Object#equals(java.lang.Object)} - * should exclude the primary key and version from determining equality. + * Objects that implement this interface and which implement + * {@link java.lang.Object#equals(java.lang.Object)} should exclude the primary + * key and version from determining equality. */ public interface Persistent { - /** - * Gets the primary key. + * Gets the primary key. + * * @return Primary key. - * @see #setPrimaryKey(Serializable) + * + * @see #setPrimaryKey(Serializable) */ - Serializable getPrimaryKey(); - + Serializable getPrimaryKey(); + /** - * Sets the primary key. - * @param aKey Primary key. - * @see #getPrimaryKey() + * Sets the primary key. + * + * @param aKey + * Primary key. + * + * @see #getPrimaryKey() */ - void setPrimaryKey(Serializable aKey); - + void setPrimaryKey(Serializable aKey); + /** - * Gets the version. - * @return Version. + * Gets the version. + * + * @return Version. + * * @see #setPersistedVersion(int) */ - int getPersistedVersion(); - + Number getPersistedVersion(); + /** - * Sets the version. - * @param aVersion Version. + * Sets the version. + * + * @param aVersion + * Version. + * * @see #getPersistedVersion() */ - void setPersistedVersion(int aVersion); + void setPersistedVersion(Number aVersion); } diff --git a/support/general/src/main/java/org/wamblee/persistence/PersistentFactory.java b/support/general/src/main/java/org/wamblee/persistence/PersistentFactory.java new file mode 100644 index 00000000..c633f955 --- /dev/null +++ b/support/general/src/main/java/org/wamblee/persistence/PersistentFactory.java @@ -0,0 +1,274 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.persistence; + +import java.io.Serializable; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.persistence.Id; +import javax.persistence.Version; + +import org.wamblee.reflection.ReflectionUtils; + +/** + * Factory which creates a {@link Persistent} object for a given entity for + * interfacing with the primary key and version of the entity. + * + * This utility only treats primary keys and fields that are annotated with @Id + * and @Version. In case ORM files are used for the definition of primary key + * and or version, then those fields are ignored. + * + * @author Erik Brakkee + * + */ +public class PersistentFactory { + + /** + * Cache of a mapping of class names to entity accessors. + */ + private static Map CACHE = new ConcurrentHashMap(); + + static interface Accessor { + void set(Object aEntity, T aValue); + + T get(Object aEntity); + } + + static class FieldAccessor implements Accessor { + private Field field; + + public FieldAccessor(Field aField) { + field = aField; + field.setAccessible(true); + } + + @Override + public T get(Object aEntity) { + try { + T value = (T) field.get(aEntity); + return value; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void set(Object aEntity, T aValue) { + try { + field.set(aEntity, aValue); + } catch (IllegalAccessException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + public Field getField() { + return field; + } + } + + static class PropertyAccessor implements Accessor { + private Method getter; + private Method setter; + + public PropertyAccessor(Method aGetter, Method aSetter) { + getter = aGetter; + setter = aSetter; + getter.setAccessible(true); + setter.setAccessible(true); + } + + @Override + public T get(Object aEntity) { + try { + return (T) getter.invoke(aEntity); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void set(Object aEntity, T aValue) { + try { + setter.invoke(aEntity, aValue); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public Method getGetter() { + return getter; + } + + public Method getSetter() { + return setter; + } + } + + static class EntityAccessor { + private Accessor pk; + private Accessor version; + + public EntityAccessor(Accessor aPk, Accessor aVersion) { + pk = aPk; + version = aVersion; + } + + public Accessor getPk() { + return pk; + } + + public Accessor getVersion() { + return version; + } + } + + public static class EntityObjectAccessor implements Persistent { + private EntityAccessor accessor; + private Object entity; + + public EntityObjectAccessor(Object aEntity, EntityAccessor aAccessor) { + accessor = aAccessor; + entity = aEntity; + } + + public EntityAccessor getAccessor() { + return accessor; + }; + + @Override + public Serializable getPrimaryKey() { + if (accessor == null || accessor.getPk() == null) { + return null; + } + return (Serializable) accessor.getPk().get(entity); + } + + @Override + public void setPrimaryKey(Serializable aKey) { + if (accessor == null || accessor.getPk() == null) { + return; + } + accessor.getPk().set(entity, aKey); + } + + @Override + public Number getPersistedVersion() { + if (accessor == null || accessor.getVersion() == null) { + return null; + } + return (Number) accessor.getVersion().get(entity); + } + + @Override + public void setPersistedVersion(Number aVersion) { + if (accessor == null || accessor.getVersion() == null) { + return; + } + accessor.getVersion().set(entity, aVersion); + } + } + + /** + * Create the entity accessor for a given class or returns a cached instance + * if one already exists. + * + * @param aClass + * Class. + * @return Entity accessor for the given class or null of the given object + * is not an entity. + */ + public static EntityAccessor createEntityAccessor(Class aClass) { + EntityAccessor accessor = CACHE.get(aClass.getName()); + if (accessor == null) { + accessor = analyse(aClass); + if (accessor != null) { + CACHE.put(aClass.getName(), accessor); + } + } + return accessor; + } + + private static EntityAccessor analyse(Class aClass) { + Accessor pk = analyse(aClass, Id.class); + Accessor version = analyse(aClass, Version.class); + if (pk != null || version != null) { + return new EntityAccessor(pk, version); + } + return null; + } + + /** + * Returns the accessor for a given annotation. + * + * @param aClass + * Class to analyse. + * @param aAnnotation + * Annotation that must be present. + * @return Accessor to use or null if the annotation is not present. + */ + private static Accessor analyse(Class aClass, + Class aAnnotation) { + List fields = ReflectionUtils.getAllFields(aClass); + for (Field field : fields) { + if (field.isAnnotationPresent(aAnnotation)) { + return new FieldAccessor(field); + } + } + List methods = ReflectionUtils.getAllMethods(aClass, + Object.class); + for (Method method : methods) { + if (method.isAnnotationPresent(aAnnotation)) { + String setterName = null; + if (method.getName().startsWith("get")) { + setterName = method.getName().replaceFirst("get", "set"); + } else if (method.getName().startsWith("is")) { + setterName = method.getName().replaceFirst("is", "set"); + } + try { + Class returnType = method.getReturnType(); + Method setter = method.getDeclaringClass() + .getDeclaredMethod(setterName, returnType); + return new PropertyAccessor(method, setter); + } catch (NoSuchMethodException e) { + throw new RuntimeException("Error obtaining setter for " + + method.getName() + " in class " + aClass.getName(), e); + } + } + } + return null; + } + + /** + * Creates the {@link Persistent} wrapper for interfacing with primary key + * and version of the entity. + * + * @param aEntity + * Entity to use. + * @return Persistent object or null if this is not an entity. + */ + public static Persistent create(Object aEntity) { + EntityAccessor accessor = createEntityAccessor(aEntity.getClass()); + if (accessor == null) { + return null; + } + return new EntityObjectAccessor(aEntity, accessor); + } +} diff --git a/support/general/src/main/java/org/wamblee/reflection/ReflectionUtils.java b/support/general/src/main/java/org/wamblee/reflection/ReflectionUtils.java index a1fa5522..4c706b15 100644 --- a/support/general/src/main/java/org/wamblee/reflection/ReflectionUtils.java +++ b/support/general/src/main/java/org/wamblee/reflection/ReflectionUtils.java @@ -1,5 +1,21 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.reflection; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -8,72 +24,116 @@ import java.util.List; import java.util.Map; public class ReflectionUtils { + /** + * Wraps a type by the corresponding wrapper type if it is a primitive type. + * + * @param aClass + * Type to wrap. + * @return Wrapped type for primitives or the provided argument value. + */ + public static Class wrapIfNeeded(Class aClass) { + if (aClass == boolean.class) { + return Boolean.class; + } - /** - * Wraps a type by the corresponding wrapper type if it is a primitive - * type. - * @param aClass Type to wrap. - * @return Wrapped type for primitives or the provided argument value. - */ - public static Class wrapIfNeeded(Class aClass) { - - if (aClass == boolean.class) { - return Boolean.class; - } - if (aClass == byte.class) { - return Byte.class; - } - if (aClass == char.class) { - return Character.class; - } - if (aClass == short.class) { - return Short.class; - } - if (aClass == int.class) { - return Integer.class; - } - if (aClass == long.class) { - return Long.class; - } - if (aClass == float.class) { - return Float.class; - } - if (aClass == double.class) { - return Double.class; - } - if (aClass == void.class) { - return Void.class; - } - return aClass; - } - - - public static List getAllMethods(Class aClass) { - - Map found = new HashMap(); - getAllMethods(aClass, found); - return new ArrayList(found.values()); - } - - private static void getAllMethods(Class aClass, Map aFound) { - List declared = Arrays.asList(aClass.getDeclaredMethods()); - for (Method method: declared) { - Method superMethod = aFound.get(method.getName()); - if ( superMethod == null ) { - // no superclass method - aFound.put(method.getName(), method); - } - else { - // super class method. Check for override. - if ( !Arrays.equals(superMethod.getParameterTypes(), method.getParameterTypes())) { - // parameters differ so this is a new method. - aFound.put(method.getName(), method); - } - } - } - Class superClass = aClass.getSuperclass(); - if (superClass != null) { - getAllMethods(superClass, aFound); - } - } + if (aClass == byte.class) { + return Byte.class; + } + + if (aClass == char.class) { + return Character.class; + } + + if (aClass == short.class) { + return Short.class; + } + + if (aClass == int.class) { + return Integer.class; + } + + if (aClass == long.class) { + return Long.class; + } + + if (aClass == float.class) { + return Float.class; + } + + if (aClass == double.class) { + return Double.class; + } + + if (aClass == void.class) { + return Void.class; + } + + return aClass; + } + + public static List getAllMethods(Class aClass, + Class... aExcludedClasses) { + if (aClass.isInterface()) { + throw new IllegalArgumentException(aClass.getName() + + " is not an interface."); + } + Map found = new HashMap(); + getAllMethods(aClass, found, Arrays.asList(aExcludedClasses)); + + return new ArrayList(found.values()); + } + + private static void getAllMethods(Class aClass, Map aFound, + List aExcludedClasses) { + List declared = Arrays.asList(aClass.getDeclaredMethods()); + + for (Method method : declared) { + Method superMethod = aFound.get(method.getName()); + + if (superMethod == null) { + // no subclass method + aFound.put(method.getName(), method); + } else { + // subclass method. Check for override. + if (!Arrays.equals(superMethod.getParameterTypes(), method + .getParameterTypes())) { + // parameters differ so this is a new method. + aFound.put(method.getName(), method); + } + } + } + + Class superClass = aClass.getSuperclass(); + + if (superClass != null && !aExcludedClasses.contains(superClass)) { + getAllMethods(superClass, aFound, aExcludedClasses); + } + } + + public static List getAllFields(Class aClass, + Class... aExcludedClasses) { + if (aClass.isInterface()) { + throw new IllegalArgumentException(aClass.getName() + + " is an interface."); + } + List found = new ArrayList(); + getAllFields(aClass, found, Arrays.asList(aExcludedClasses)); + + return found; + } + + private static void getAllFields(Class aClass, List aFound, + List aExcludedClasses) { + List declared = Arrays.asList(aClass.getDeclaredFields()); + + for (Field field : declared) { + aFound.add(field); + } + + Class superClass = aClass.getSuperclass(); + + if (superClass != null && !aExcludedClasses.contains(superClass)) { + getAllFields(superClass, aFound, aExcludedClasses); + } + } } diff --git a/support/general/src/main/java/org/wamblee/xml/ClasspathUriResolver.java b/support/general/src/main/java/org/wamblee/xml/ClasspathUriResolver.java index ba2d875c..1d53d7dc 100644 --- a/support/general/src/main/java/org/wamblee/xml/ClasspathUriResolver.java +++ b/support/general/src/main/java/org/wamblee/xml/ClasspathUriResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,10 +12,12 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.xml; +import org.wamblee.io.ClassPathResource; +import org.wamblee.io.InputResource; + import java.io.IOException; import javax.xml.transform.Source; @@ -23,14 +25,10 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; -import org.wamblee.io.ClassPathResource; -import org.wamblee.io.InputResource; - /** * URI resolver that resolves stylesheets through the classpath. */ public class ClasspathUriResolver implements URIResolver { - /** * Constructs the resolver. * @@ -43,18 +41,18 @@ public class ClasspathUriResolver implements URIResolver { * (non-Javadoc) * * @see javax.xml.transform.URIResolver#resolve(java.lang.String, - * java.lang.String) + * java.lang.String) */ public Source resolve(String aHref, String aBase) - throws TransformerException { + throws TransformerException { InputResource xslt = new ClassPathResource(aHref); + try { return new StreamSource(xslt.getInputStream()); } catch (IOException e) { throw new TransformerException( - "Could not get XSLT style sheet in classpath '" + aHref - + "'", e); + "Could not get XSLT style sheet in classpath '" + aHref + "'", + e); } } - } diff --git a/support/general/src/main/java/org/wamblee/xml/DomUtils.java b/support/general/src/main/java/org/wamblee/xml/DomUtils.java index 3825bacd..356fd342 100644 --- a/support/general/src/main/java/org/wamblee/xml/DomUtils.java +++ b/support/general/src/main/java/org/wamblee/xml/DomUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,15 +12,35 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.xml; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; + +import org.dom4j.DocumentException; + +import org.dom4j.io.DOMReader; +import org.dom4j.io.DOMWriter; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.xml.sax.SAXException; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; + import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -34,28 +54,12 @@ import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.XMLSerializer; -import org.dom4j.DocumentException; -import org.dom4j.io.DOMReader; -import org.dom4j.io.DOMWriter; -import org.w3c.dom.Attr; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.SAXException; - /** * Some basic XML utilities for common reoccuring tasks for DOM documents. - * + * * @author Erik Brakkee */ public final class DomUtils { - private static final Log LOG = LogFactory.getLog(DomUtils.class); /** @@ -71,10 +75,13 @@ public final class DomUtils { * * @param aDocument * document. + * * @return + * */ public static Document read(String aDocument) throws XMLException { ByteArrayInputStream is = new ByteArrayInputStream(aDocument.getBytes()); + return read(is); } @@ -83,14 +90,17 @@ public final class DomUtils { * * @param aIs * Input stream. + * * @return + * */ public static Document read(InputStream aIs) throws XMLException { try { DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); + .newDocumentBuilder(); + return builder.parse(aIs); - } catch (SAXException e) { + } catch (SAXException e) { throw new XMLException(e.getMessage(), e); } catch (IOException e) { throw new XMLException(e.getMessage(), e); @@ -112,17 +122,19 @@ public final class DomUtils { * Input stream. * @param aSchema * Schema. + * * @return Parsed and validated document. + * */ public static Document readAndValidate(InputStream aIs, InputStream aSchema) - throws XMLException { - + throws XMLException { try { final Schema schema = SchemaFactory.newInstance( - XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema( - new StreamSource(aSchema)); + XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema( + new StreamSource(aSchema)); - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); factory.setValidating(true); factory.setNamespaceAware(true); factory.setSchema(schema); @@ -140,13 +152,13 @@ public final class DomUtils { } catch (Exception e) { LOG.warn("Error closing schema", e); } + try { aIs.close(); } catch (Exception e) { LOG.warn("Error closing XML file", e); } } - } /** @@ -156,9 +168,10 @@ public final class DomUtils { * Document to serialize. * @param aOs * Output stream. + * */ public static void serialize(Document aDocument, OutputStream aOs) - throws IOException { + throws IOException { XMLSerializer serializer = new XMLSerializer(aOs, new OutputFormat()); serializer.serialize(aDocument); } @@ -168,11 +181,14 @@ public final class DomUtils { * * @param aDocument * Document to serialize. + * * @return Serialized document. + * */ public static String serialize(Document aDocument) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); serialize(aDocument, os); + return os.toString(); } @@ -181,10 +197,12 @@ public final class DomUtils { * * @param aDocument * Document to convert. + * * @return W3C DOM document. + * */ public static Document convert(org.dom4j.Document aDocument) - throws DocumentException { + throws DocumentException { return new DOMWriter().write(aDocument); } @@ -193,6 +211,7 @@ public final class DomUtils { * * @param aDocument * Document to convert. + * * @return Dom4j document. */ public static org.dom4j.Document convert(Document aDocument) { @@ -210,8 +229,10 @@ public final class DomUtils { */ public static void removeDuplicateAttributes(Node aNode) { NodeList list = aNode.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { Node node = list.item(i); + if (node instanceof Element) { removeDuplicateAttributes((Element) node); removeDuplicateAttributes(node); @@ -229,19 +250,24 @@ public final class DomUtils { NamedNodeMap attributes = aElement.getAttributes(); Map uniqueAttributes = new TreeMap(); List attlist = new ArrayList(); + for (int i = 0; i < attributes.getLength(); i++) { Attr attribute = (Attr) attributes.item(i); + if (uniqueAttributes.containsKey(attribute.getNodeName())) { - LOG.info("Detected duplicate attribute (will be removed)'" - + attribute.getNodeName() + "'"); + LOG.info("Detected duplicate attribute (will be removed)'" + + attribute.getNodeName() + "'"); } + uniqueAttributes.put(attribute.getNodeName(), attribute); attlist.add(attribute); } + // Remove all attributes from the element. for (Attr att : attlist) { aElement.removeAttributeNode(att); } + // Add the unique attributes back to the element. for (Attr att : uniqueAttributes.values()) { aElement.setAttributeNode(att); diff --git a/support/general/src/main/java/org/wamblee/xml/XMLException.java b/support/general/src/main/java/org/wamblee/xml/XMLException.java index 06363c42..1d54669e 100644 --- a/support/general/src/main/java/org/wamblee/xml/XMLException.java +++ b/support/general/src/main/java/org/wamblee/xml/XMLException.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,21 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.xml; /** - * Exception thrown in case of XML parsing problems. - * + * Exception thrown in case of XML parsing problems. + * * @author Erik Brakkee */ public class XMLException extends Exception { - - public XMLException(String aMsg) { - super(aMsg); + /** + * Creates a new XMLException object. + * + */ + public XMLException(String aMsg) { + super(aMsg); } - - public XMLException(String aMsg, Throwable aCause) { + + /** + * Creates a new XMLException object. + * + */ + public XMLException(String aMsg, Throwable aCause) { super(aMsg, aCause); } } diff --git a/support/general/src/main/java/org/wamblee/xml/XslTransformer.java b/support/general/src/main/java/org/wamblee/xml/XslTransformer.java index fb3d3052..78be8a56 100644 --- a/support/general/src/main/java/org/wamblee/xml/XslTransformer.java +++ b/support/general/src/main/java/org/wamblee/xml/XslTransformer.java @@ -1,21 +1,24 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * - * 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 + * 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 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wamblee.xml; +import org.w3c.dom.Document; + +import org.wamblee.io.FileResource; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -33,17 +36,13 @@ import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import org.w3c.dom.Document; -import org.wamblee.io.FileResource; - /** * XSL transformer for simplified usage of XSL transformations. - * + * * @author Erik Brakkee */ public class XslTransformer { - - private TransformerFactory _factory; + private TransformerFactory factory; /** * Constructs the URL resolver. @@ -52,8 +51,8 @@ public class XslTransformer { * URI resolver to use. */ public XslTransformer(URIResolver aResolver) { - _factory = TransformerFactory.newInstance(); - _factory.setURIResolver(aResolver); + factory = TransformerFactory.newInstance(); + factory.setURIResolver(aResolver); } /** @@ -61,29 +60,36 @@ public class XslTransformer { * */ public XslTransformer() { - _factory = TransformerFactory.newInstance(); + factory = TransformerFactory.newInstance(); } /** - * Resolves an XSLT based on URI. - * @param aXslt XSLT to resolve, + * Resolves an XSLT based on URI. + * + * @param aXslt + * XSLT to resolve, + * * @return Source for the XSLT - * @throws TransformerException In case the XSLT cannot be found. + * + * @throws TransformerException + * In case the XSLT cannot be found. */ public Source resolve(String aXslt) throws TransformerException { - URIResolver resolver = _factory.getURIResolver(); + URIResolver resolver = factory.getURIResolver(); + if (resolver == null) { if (new File(aXslt).canRead()) { try { return new StreamSource(new FileResource(new File(aXslt)) - .getInputStream()); + .getInputStream()); } catch (IOException e) { throw new TransformerException(e.getMessage(), e); } } else { - throw new TransformerException("Cannot read '" + aXslt + "'"); + throw new TransformerException("Cannot read '" + aXslt + "'"); } } + return resolver.resolve(aXslt, ""); } @@ -95,17 +101,20 @@ public class XslTransformer { * Document to transform. * @param aXslt * XSLT to use. + * * @return Transformed document. + * * @throws IOException * In case of problems reading resources. * @throws TransformerException * In case transformation fails. */ public Document transform(Document aDocument, Source aXslt) - throws IOException, TransformerException { + throws IOException, TransformerException { Source source = new DOMSource(aDocument); DOMResult result = new DOMResult(); transform(source, result, aXslt); + return (Document) result.getNode(); } @@ -116,17 +125,20 @@ public class XslTransformer { * Document to transform. * @param aXslt * XSLT to use. + * * @return Transformed document. + * * @throws IOException * In case of problems reading resources. * @throws TransformerException * In case transformation fails. */ public Document transform(byte[] aDocument, Source aXslt) - throws IOException, TransformerException { + throws IOException, TransformerException { Source source = new StreamSource(new ByteArrayInputStream(aDocument)); DOMResult result = new DOMResult(); transform(source, result, aXslt); + return (Document) result.getNode(); } @@ -138,14 +150,17 @@ public class XslTransformer { * Document to transform. * @param aXslt * XSL transformation. + * * @return Transformed document. + * */ public String textTransform(byte[] aDocument, Source aXslt) - throws IOException, TransformerException { + throws IOException, TransformerException { Source source = new StreamSource(new ByteArrayInputStream(aDocument)); ByteArrayOutputStream os = new ByteArrayOutputStream(); StreamResult result = new StreamResult(os); transform(source, result, aXslt); + return new String(os.toByteArray()); } @@ -158,19 +173,20 @@ public class XslTransformer { * Result of the transformation. * @param aXslt * XSLT to use. + * * @throws IOException * In case of problems reading resources. * @throws TransformerException * In case transformation fails. */ public void transform(Source aSource, Result aResult, Source aXslt) - throws IOException, TransformerException { + throws IOException, TransformerException { try { - Transformer transformer = _factory.newTransformer(aXslt); + Transformer transformer = factory.newTransformer(aXslt); transformer.transform(aSource, aResult); } catch (TransformerConfigurationException e) { throw new TransformerException( - "Configuration problem of XSLT transformation", e); + "Configuration problem of XSLT transformation", e); } } } diff --git a/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java b/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java index da6e1be6..955a7114 100644 --- a/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java +++ b/support/general/src/test/java/org/wamblee/cache/CachedObjectTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,164 +13,169 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.cache; -import java.io.IOException; - import junit.framework.TestCase; + import net.sf.ehcache.CacheException; import org.wamblee.io.TestResource; + import org.wamblee.test.TimingUtils; +import java.io.IOException; + /** - * Cached object test. - * + * Cached object test. + * * @author Erik Brakkee */ public class CachedObjectTest extends TestCase { - - /** - * - */ private static final String EHCACHE_CONFIG = "ehcache.xml"; + private static final int OBJECT_KEY = 10; + private CachedObject.Computation computation; + private int ncomputations; - private static final int OBJECT_KEY = 10; - - private CachedObject.Computation _computation; - private int _ncomputations; - - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { super.setUp(); - _computation = new CachedObject.Computation() { + computation = new CachedObject.Computation() { public Integer getObject(Integer aObjectKey) { - _ncomputations++; + ncomputations++; + return compute(aObjectKey); }; }; - _ncomputations = 0; + ncomputations = 0; } - - private int compute(int aValue) { + + private int compute(int aValue) { return aValue + 10; } - - private CachedObject createCached(Cache aCache) { - return new CachedObject(aCache, OBJECT_KEY, _computation); + + private CachedObject createCached( + Cache aCache) { + return new CachedObject(aCache, OBJECT_KEY, + computation); } /** - * Verifies that upon first use, the cached object uses the computation to - * retrieve the object. - * + * Verifies that upon first use, the cached object uses the computation to + * retrieve the object. + * */ - public void testComputation() { - CachedObject cached = createCached(new ZeroCache()); + public void testComputation() { + CachedObject cached = createCached(new ZeroCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); + assertEquals(1, ncomputations); } - - public void testInvalidateCache() { - CachedObject cached = createCached(new ForeverCache()); + + public void testInvalidateCache() { + CachedObject cached = createCached(new ForeverCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - cached.invalidate(); + assertEquals(1, ncomputations); + cached.invalidate(); value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, _ncomputations); + assertEquals(2, ncomputations); } - + public void testBehaviorEhCache() throws CacheException, IOException { - Cache cache = new EhCache(new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "test"); + Cache cache = new EhCache( + new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "test"); CachedObject cached = createCached(cache); - - assertTrue( cache == cached.getCache()); + + assertTrue(cache == cached.getCache()); + int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - // The value must still be cached. - value = cached.get(); + assertEquals(1, ncomputations); + // The value must still be cached. + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - - // Cache expiry. - TimingUtils.sleep(6000); - value = cached.get(); + assertEquals(1, ncomputations); + + // Cache expiry. + TimingUtils.sleep(6000); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, _ncomputations); - + assertEquals(2, ncomputations); + // Should still be cached now. - value = cached.get(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, _ncomputations); - + assertEquals(2, ncomputations); + // explicit invalidation. - cached.invalidate(); - value = cached.get(); + cached.invalidate(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(3, _ncomputations); - + assertEquals(3, ncomputations); } - + public void testBehaviorEhCacheDefault() throws CacheException, IOException { - Cache cache = new EhCache(new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), "undefined"); + Cache cache = new EhCache( + new TestResource(CachedObjectTest.class, EHCACHE_CONFIG), + "undefined"); CachedObject cached = createCached(cache); - - assertTrue( cache == cached.getCache()); + + assertTrue(cache == cached.getCache()); + int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - // The value must still be cached. - value = cached.get(); + assertEquals(1, ncomputations); + // The value must still be cached. + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - - // Cache expiry. - TimingUtils.sleep(6000); - value = cached.get(); + assertEquals(1, ncomputations); + + // Cache expiry. + TimingUtils.sleep(6000); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, _ncomputations); - + assertEquals(2, ncomputations); + // Should still be cached now. - value = cached.get(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(2, _ncomputations); - + assertEquals(2, ncomputations); } - - - public void testBehaviorForeverCache() { - CachedObject cached = createCached(new ForeverCache()); + + public void testBehaviorForeverCache() { + CachedObject cached = createCached(new ForeverCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - for (int ncomp = 2; ncomp <= 100; ncomp++) { - value = cached.get(); + assertEquals(1, ncomputations); + + for (int ncomp = 2; ncomp <= 100; ncomp++) { + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); + assertEquals(1, ncomputations); } } - - public void testBehaviorZeroCache() { - CachedObject cached = createCached(new ZeroCache()); + + public void testBehaviorZeroCache() { + CachedObject cached = createCached(new ZeroCache()); int value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(1, _ncomputations); - for (int ncomp = 2; ncomp <= 100; ncomp++) { - value = cached.get(); + assertEquals(1, ncomputations); + + for (int ncomp = 2; ncomp <= 100; ncomp++) { + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(ncomp, _ncomputations); + assertEquals(ncomp, ncomputations); } - cached.invalidate(); - value = cached.get(); + + cached.invalidate(); + value = cached.get(); assertEquals(compute(OBJECT_KEY), value); - assertEquals(101, _ncomputations); + assertEquals(101, ncomputations); } } diff --git a/support/general/src/test/java/org/wamblee/collections/CollectionFilterTest.java b/support/general/src/test/java/org/wamblee/collections/CollectionFilterTest.java index 1e56eac1..d2cc2560 100644 --- a/support/general/src/test/java/org/wamblee/collections/CollectionFilterTest.java +++ b/support/general/src/test/java/org/wamblee/collections/CollectionFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,28 +15,27 @@ */ package org.wamblee.collections; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import junit.framework.TestCase; import org.wamblee.conditions.Condition; + import org.wamblee.test.AssertionUtils; -import junit.framework.TestCase; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class CollectionFilterTest extends TestCase { - - public void testFilter() { - List list = Arrays.asList(new String[] { "x", "y", "z", "y" }); - List result = new ArrayList(); - CollectionFilter.filter(list, result, - new Condition() { - @Override - public boolean matches(String aObject) { - return aObject.equals("y"); - } - }); - AssertionUtils.assertEquals(new String[] { "y", "y" }, result.toArray()); - } - + public void testFilter() { + List list = Arrays.asList(new String[] { "x", "y", "z", "y" }); + List result = new ArrayList(); + CollectionFilter.filter(list, result, new Condition() { + @Override + public boolean matches(String aObject) { + return aObject.equals("y"); + } + }); + AssertionUtils + .assertEquals(new String[] { "y", "y" }, result.toArray()); + } } diff --git a/support/general/src/test/java/org/wamblee/concurrency/AbstractLockTestCase.java b/support/general/src/test/java/org/wamblee/concurrency/AbstractLockTestCase.java index 39cec11a..a4143c0b 100644 --- a/support/general/src/test/java/org/wamblee/concurrency/AbstractLockTestCase.java +++ b/support/general/src/test/java/org/wamblee/concurrency/AbstractLockTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,31 +12,25 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.concurrency; +import junit.framework.TestCase; + import org.wamblee.test.EventTracker; import org.wamblee.test.TimingUtils; -import junit.framework.TestCase; - /** * Tests for the JVMLock. - * + * * @author Erik Brakkee */ public abstract class AbstractLockTestCase extends TestCase { - protected static final int SLEEP_TIME = 1000; - protected static final String STARTED = "started"; - protected static final String ACQUIRED = "acquired"; - protected static final String RELEASED = "released"; - - private EventTracker _tracker; + private EventTracker tracker; /* * (non-Javadoc) @@ -45,19 +39,19 @@ public abstract class AbstractLockTestCase extends TestCase { */ @Override protected void setUp() throws Exception { - _tracker = new EventTracker(); + tracker = new EventTracker(); } - - protected EventTracker getTracker() { - return _tracker; + + protected EventTracker getTracker() { + return tracker; } /** - * Must be implemented to generate the events - * {@link #STARTED}, {@link #ACQUIRED}, and {@link #RELEASED} in - * that order. The lock should be acquired for - * the time specified by {@link #SLEEP_TIME}. - * @return Thread which does the work. + * Must be implemented to generate the events {@link #STARTED}, + * {@link #ACQUIRED}, and {@link #RELEASED} in that order. The lock should + * be acquired for the time specified by {@link #SLEEP_TIME}. + * + * @return Thread which does the work. */ protected abstract Thread runThread(); @@ -69,23 +63,29 @@ public abstract class AbstractLockTestCase extends TestCase { Thread t2 = runThread(); TimingUtils.sleep(SLEEP_TIME / 10); // give threads a chance to start // up. - assertEquals(2, _tracker.getEventCount(STARTED)); // both threads + + assertEquals(2, tracker.getEventCount(STARTED)); // both threads // should have // started. - assertEquals(1, _tracker.getEventCount(ACQUIRED)); // one thread has - // acquired the - // lock. + + assertEquals(1, tracker.getEventCount(ACQUIRED)); // one thread has + // acquired the + // lock. + TimingUtils.sleep(SLEEP_TIME); - assertEquals(2, _tracker.getEventCount(ACQUIRED)); // now the other - // thread could also - // acquire the lock - assertEquals(1, _tracker.getEventCount(RELEASED)); // and the first - // thread has - // released it. + assertEquals(2, tracker.getEventCount(ACQUIRED)); // now the other + // thread could also + // acquire the lock + + assertEquals(1, tracker.getEventCount(RELEASED)); // and the first + // thread has + // released it. + TimingUtils.sleep(SLEEP_TIME); - assertEquals(2, _tracker.getEventCount(RELEASED)); // both threads - // should be - // finished. + assertEquals(2, tracker.getEventCount(RELEASED)); // both threads + // should be + // finished. + t1.join(); t2.join(); } diff --git a/support/general/src/test/java/org/wamblee/concurrency/JvmLockTest.java b/support/general/src/test/java/org/wamblee/concurrency/JvmLockTest.java index e14ca9ba..bc8cad3d 100644 --- a/support/general/src/test/java/org/wamblee/concurrency/JvmLockTest.java +++ b/support/general/src/test/java/org/wamblee/concurrency/JvmLockTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,21 +12,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.concurrency; import org.wamblee.test.TimingUtils; /** * Tests for the JVMLock. - * + * * @author Erik Brakkee */ public class JvmLockTest extends AbstractLockTestCase { + private JvmLock lock; - private JvmLock _lock; - /* * (non-Javadoc) * @@ -35,21 +33,22 @@ public class JvmLockTest extends AbstractLockTestCase { @Override protected void setUp() throws Exception { super.setUp(); - _lock = new JvmLock(); + lock = new JvmLock(); } protected Thread runThread() { Thread t = new Thread(new Runnable() { public void run() { getTracker().eventOccurred(STARTED); - _lock.acquire(); + lock.acquire(); getTracker().eventOccurred(ACQUIRED); TimingUtils.sleep(SLEEP_TIME); - _lock.release(); + lock.release(); getTracker().eventOccurred(RELEASED); }; }); t.start(); + return t; } } diff --git a/support/general/src/test/java/org/wamblee/concurrency/ReadWriteLockTest.java b/support/general/src/test/java/org/wamblee/concurrency/ReadWriteLockTest.java index 40302f76..273abd0e 100644 --- a/support/general/src/test/java/org/wamblee/concurrency/ReadWriteLockTest.java +++ b/support/general/src/test/java/org/wamblee/concurrency/ReadWriteLockTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,36 +15,27 @@ */ package org.wamblee.concurrency; -import junit.framework.Assert; import junit.framework.TestCase; - /** * Testing the read-write lock class. Note: in case of problems, test cases * could hang. - * + * * @see ReadWriteLock */ public class ReadWriteLockTest extends TestCase { - /** - * - */ private static final int HALF_SECOND = 500; - /** - * - */ + private static final int ONE_SECOND = 1000; - /** - * - */ + private static final int TWO_SECONDS = 2000; - private ReadWriteLock _lock; - private int _nReaders; - private int _nWriters; + private ReadWriteLock lock; + private int nReaders; + private int nWriters; /** * Constructor for ReadWriteLockTest. - * + * * @param aName */ public ReadWriteLockTest(String aName) { @@ -52,27 +43,27 @@ public class ReadWriteLockTest extends TestCase { } private synchronized int getReaderCount() { - return _nReaders; + return nReaders; } private synchronized int getWriterCount() { - return _nWriters; + return nWriters; } synchronized void incrementReaderCount() { - _nReaders++; + nReaders++; } synchronized void incrementWriterCount() { - _nWriters++; + nWriters++; } synchronized void decrementReaderCount() { - _nReaders--; + nReaders--; } synchronized void decrementWriterCount() { - _nWriters--; + nWriters--; } /* @@ -80,14 +71,14 @@ public class ReadWriteLockTest extends TestCase { */ protected void setUp() throws Exception { super.setUp(); - _lock = new ReadWriteLock(); + lock = new ReadWriteLock(); } /* * @see TestCase#tearDown() */ protected void tearDown() throws Exception { - _lock = null; + lock = null; super.tearDown(); } @@ -95,27 +86,28 @@ public class ReadWriteLockTest extends TestCase { * Acquire and release a read lock. */ public void testRead() { - _lock.acquireRead(); - _lock.releaseRead(); + lock.acquireRead(); + lock.releaseRead(); } /** * Acquire and release a write lock. */ public void testWrite() { - _lock.acquireWrite(); - _lock.releaseWrite(); + lock.acquireWrite(); + lock.releaseWrite(); } /** * Verify concurrent access by multiple readers is possible. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testMultipleReaders() throws InterruptedException { - Runnable runnable = new ReadLocker(_lock, this, TWO_SECONDS); + Runnable runnable = new ReadLocker(lock, this, TWO_SECONDS); - Thread t1 = new Thread(runnable); + Thread t1 = new Thread(runnable); t1.start(); Thread t2 = new Thread(runnable); @@ -128,13 +120,14 @@ public class ReadWriteLockTest extends TestCase { /** * Verify that only one writer at a time can acquire the write lock. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testSingleWriter() throws InterruptedException { - WriteLocker writer = new WriteLocker(_lock, this, ONE_SECOND); - Thread t1 = new Thread(writer); - Thread t2 = new Thread(writer); + WriteLocker writer = new WriteLocker(lock, this, ONE_SECOND); + Thread t1 = new Thread(writer); + Thread t2 = new Thread(writer); t1.start(); t2.start(); @@ -147,14 +140,16 @@ public class ReadWriteLockTest extends TestCase { /** * Verify that multiple writers cannot acquire the write lock concurrently. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testMultipleWriters() throws InterruptedException { - WriteLocker writer1 = new WriteLocker(_lock, this, HALF_SECOND + ONE_SECOND); - WriteLocker writer2 = new WriteLocker(_lock, this, ONE_SECOND); - Thread t1 = new Thread(writer1); - Thread t2 = new Thread(writer2); + WriteLocker writer1 = new WriteLocker(lock, this, HALF_SECOND + + ONE_SECOND); + WriteLocker writer2 = new WriteLocker(lock, this, ONE_SECOND); + Thread t1 = new Thread(writer1); + Thread t2 = new Thread(writer2); t1.start(); Thread.sleep(HALF_SECOND); @@ -167,23 +162,24 @@ public class ReadWriteLockTest extends TestCase { Thread.sleep(ONE_SECOND); // at t = 2, the second writer still must have - // a lock. + // a lock. assertTrue(getWriterCount() == 1); t1.join(); t2.join(); } /** - * Verify that after the first reader acquires a lock, a subsequent writer + * Verify that after the first reader acquires a lock, a subsequent writer * can only acquire the lock after the reader has released it. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testReadWrite1() throws InterruptedException { - ReadLocker readLocker = new ReadLocker(_lock, this, TWO_SECONDS); - Thread t1 = new Thread(readLocker); - WriteLocker writeLocker = new WriteLocker(_lock, this, TWO_SECONDS); - Thread t2 = new Thread(writeLocker); + ReadLocker readLocker = new ReadLocker(lock, this, TWO_SECONDS); + Thread t1 = new Thread(readLocker); + WriteLocker writeLocker = new WriteLocker(lock, this, TWO_SECONDS); + Thread t2 = new Thread(writeLocker); t1.start(); // acquire read lock Thread.sleep(HALF_SECOND); @@ -192,13 +188,13 @@ public class ReadWriteLockTest extends TestCase { Thread.sleep(HALF_SECOND); // 1 second underway, reader still holding the - // lock so write lock cannot be acquired. + // lock so write lock cannot be acquired. assertTrue(getReaderCount() == 1); assertTrue(getWriterCount() == 0); Thread.sleep(ONE_SECOND + HALF_SECOND); - // 2.5 seconds underway, read lock released and - // write lock must be acquired. + // 2.5 seconds underway, read lock released and + // write lock must be acquired. assertTrue("Wrong no. of readers: " + getReaderCount(), getReaderCount() == 0); assertTrue(getWriterCount() == 1); @@ -209,16 +205,19 @@ public class ReadWriteLockTest extends TestCase { /** * Verify that when multiple readers have acquired a read lock, the writer * can only acquire the lock after all readers have released it. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testReadWrite2() throws InterruptedException { - ReadLocker readLocker1 = new ReadLocker(_lock, this, TWO_SECONDS + HALF_SECOND); - ReadLocker readLocker2 = new ReadLocker(_lock, this, TWO_SECONDS + HALF_SECOND); - Thread t1 = new Thread(readLocker1); - Thread t2 = new Thread(readLocker2); - WriteLocker writeLocker = new WriteLocker(_lock, this, TWO_SECONDS); - Thread t3 = new Thread(writeLocker); + ReadLocker readLocker1 = new ReadLocker(lock, this, TWO_SECONDS + + HALF_SECOND); + ReadLocker readLocker2 = new ReadLocker(lock, this, TWO_SECONDS + + HALF_SECOND); + Thread t1 = new Thread(readLocker1); + Thread t2 = new Thread(readLocker2); + WriteLocker writeLocker = new WriteLocker(lock, this, TWO_SECONDS); + Thread t3 = new Thread(writeLocker); t1.start(); // acquire read lock [0, 2.5] Thread.sleep(ONE_SECOND); @@ -228,10 +227,10 @@ public class ReadWriteLockTest extends TestCase { Thread.sleep(HALF_SECOND); // t = 1.5 assertTrue(getReaderCount() == 2); - t3.start(); // write lock + t3.start(); // write lock Thread.sleep(HALF_SECOND); - // 2 seconds, + // 2 seconds, assertTrue(getReaderCount() == 2); assertTrue(getWriterCount() == 0); Thread.sleep(ONE_SECOND); @@ -242,8 +241,8 @@ public class ReadWriteLockTest extends TestCase { assertTrue(getWriterCount() == 0); Thread.sleep(ONE_SECOND); - // 4 seconds underway, write lock must have - // been acquired. + // 4 seconds underway, write lock must have + // been acquired. assertTrue(getReaderCount() == 0); assertTrue(getWriterCount() == 1); @@ -253,16 +252,17 @@ public class ReadWriteLockTest extends TestCase { } /** - * Verify that after a writer acquires a lock, a subsequent reader can - * only acquire the lock after the writer has released it. - * - * @throws InterruptedException May not occur. + * Verify that after a writer acquires a lock, a subsequent reader can only + * acquire the lock after the writer has released it. + * + * @throws InterruptedException + * May not occur. */ public void testReadWrite3() throws InterruptedException { - ReadLocker readLocker = new ReadLocker(_lock, this, TWO_SECONDS); - Thread t1 = new Thread(readLocker); - WriteLocker writeLocker = new WriteLocker(_lock, this, TWO_SECONDS); - Thread t2 = new Thread(writeLocker); + ReadLocker readLocker = new ReadLocker(lock, this, TWO_SECONDS); + Thread t1 = new Thread(readLocker); + WriteLocker writeLocker = new WriteLocker(lock, this, TWO_SECONDS); + Thread t2 = new Thread(writeLocker); t2.start(); // acquire write lock Thread.sleep(HALF_SECOND); @@ -271,13 +271,13 @@ public class ReadWriteLockTest extends TestCase { Thread.sleep(HALF_SECOND); // 1 second underway, writer still holding the - // lock so read lock cannot be acquired. + // lock so read lock cannot be acquired. assertTrue(getWriterCount() == 1); assertTrue(getReaderCount() == 0); Thread.sleep(ONE_SECOND + HALF_SECOND); - // 2.5 seconds underway, write lock released and - // read lock must be acquired. + // 2.5 seconds underway, write lock released and + // read lock must be acquired. assertTrue("Wrong no. of writers: " + getReaderCount(), getWriterCount() == 0); assertTrue(getReaderCount() == 1); @@ -286,32 +286,32 @@ public class ReadWriteLockTest extends TestCase { } /* - * The following test cases are for testing whether or not - * the read write lock checks the locking correctly. - * Strictly speaking, these checks wouldn't be necessary - * because it involves the contract of the ReadWriteLock which - * must be obeyed by users of the ReadWriteLock. Nevertheless, - * this is tested anyway to be absolutely sure. + * The following test cases are for testing whether or not the read write + * lock checks the locking correctly. Strictly speaking, these checks + * wouldn't be necessary because it involves the contract of the + * ReadWriteLock which must be obeyed by users of the ReadWriteLock. + * Nevertheless, this is tested anyway to be absolutely sure. */ /** - * Acquire a read lock from one thread, release it from another. Verify - * that a RuntimeException is thrown. - * - * @throws InterruptedException May not occur. + * Acquire a read lock from one thread, release it from another. Verify that + * a RuntimeException is thrown. + * + * @throws InterruptedException + * May not occur. */ public void testReleaseReadFromWrongThread() throws InterruptedException { Thread t1 = null; try { t1 = new Thread(new Runnable() { - public void run() { - ReadWriteLockTest.this._lock.acquireRead(); - } - }); + public void run() { + ReadWriteLockTest.this.lock.acquireRead(); + } + }); t1.start(); Thread.sleep(ONE_SECOND); // wait until thread is started - _lock.releaseRead(); // release lock from wrong thread. + lock.releaseRead(); // release lock from wrong thread. } catch (RuntimeException e) { return; // ok } finally { @@ -324,21 +324,22 @@ public class ReadWriteLockTest extends TestCase { /** * Acquire a write lock from one thread, release it from another. Verify * that a RuntimeException is thrown. - * - * @throws InterruptedException May not occur. + * + * @throws InterruptedException + * May not occur. */ public void testReleaseWriteFromWrongThread() throws InterruptedException { Thread t1 = null; try { t1 = new Thread(new Runnable() { - public void run() { - ReadWriteLockTest.this._lock.acquireWrite(); - } - }); + public void run() { + ReadWriteLockTest.this.lock.acquireWrite(); + } + }); t1.start(); Thread.sleep(ONE_SECOND); // wait until thread is started - _lock.releaseWrite(); // release lock from wrong thread. + lock.releaseWrite(); // release lock from wrong thread. } catch (RuntimeException e) { return; // ok } finally { @@ -349,13 +350,13 @@ public class ReadWriteLockTest extends TestCase { } /** - * Try to acquire a read lock multiple times. Verify that a - * RuntimeException is thrown. + * Try to acquire a read lock multiple times. Verify that a RuntimeException + * is thrown. */ public void testAcquireReadTwice() { try { - _lock.acquireRead(); - _lock.acquireRead(); + lock.acquireRead(); + lock.acquireRead(); } catch (RuntimeException e) { // ok return; @@ -370,8 +371,8 @@ public class ReadWriteLockTest extends TestCase { */ public void testAcquireWriteTwice() { try { - _lock.acquireWrite(); - _lock.acquireWrite(); + lock.acquireWrite(); + lock.acquireWrite(); } catch (RuntimeException e) { return; // ok } @@ -385,8 +386,8 @@ public class ReadWriteLockTest extends TestCase { */ public void testAcquireReadFollowedByWrite() { try { - _lock.acquireRead(); - _lock.acquireWrite(); + lock.acquireRead(); + lock.acquireWrite(); } catch (RuntimeException e) { return; // ok } @@ -400,8 +401,8 @@ public class ReadWriteLockTest extends TestCase { */ public void testAcquireWriteFollowedByRead() { try { - _lock.acquireWrite(); - _lock.acquireRead(); + lock.acquireWrite(); + lock.acquireRead(); } catch (RuntimeException e) { return; // ok } @@ -415,8 +416,8 @@ public class ReadWriteLockTest extends TestCase { */ public void testAcquireReadFollowedByReleaseaWrite() { try { - _lock.acquireRead(); - _lock.releaseWrite(); + lock.acquireRead(); + lock.releaseWrite(); } catch (RuntimeException e) { return; // ok } @@ -430,8 +431,8 @@ public class ReadWriteLockTest extends TestCase { */ public void testAcquireWriteFollowedByReleaseRead() { try { - _lock.acquireWrite(); - _lock.releaseRead(); + lock.acquireWrite(); + lock.releaseRead(); } catch (RuntimeException e) { return; // ok } @@ -440,70 +441,68 @@ public class ReadWriteLockTest extends TestCase { } } - /** - * ReadLocker acquires a read lock and performs a callback when the lock as - * been acquired, sleeps for a designated amount of time, releases the read - * lock, and performs a callback after the lock has been released. + * ReadLocker acquires a read lock and performs a callback when the lock as been + * acquired, sleeps for a designated amount of time, releases the read lock, and + * performs a callback after the lock has been released. */ class ReadLocker implements Runnable { - private ReadWriteLock _lock; - private ReadWriteLockTest _lockTest; - private int _sleepTime; + private ReadWriteLock lock; + private ReadWriteLockTest lockTest; + private int sleepTime; public ReadLocker(ReadWriteLock aLock, ReadWriteLockTest aLockTest, int aSleepTime) { - _lock = aLock; - _lockTest = aLockTest; - _sleepTime = aSleepTime; + lock = aLock; + lockTest = aLockTest; + sleepTime = aSleepTime; } public void run() { - _lock.acquireRead(); - _lockTest.incrementReaderCount(); + lock.acquireRead(); + lockTest.incrementReaderCount(); try { - Thread.sleep(_sleepTime); + Thread.sleep(sleepTime); } catch (InterruptedException e) { - Assert.fail("ReadLocker thread was interrupted." - + Thread.currentThread()); + throw new RuntimeException("ReadLocker thread was interrupted." + + Thread.currentThread()); } - _lock.releaseRead(); - _lockTest.decrementReaderCount(); + lock.releaseRead(); + lockTest.decrementReaderCount(); } } - /** - * WriteLocker acquires a write lock and performs a callback when the lock as + * WriteLocker acquires a write lock and performs a callback when the lock as * been acquired, sleeps for a designated amount of time, releases the write * lock, and performs a callback after the lock has been released. */ class WriteLocker implements Runnable { - private ReadWriteLock _lock; - private ReadWriteLockTest _lockTest; - private int _sleepTime; + private ReadWriteLock lock; + private ReadWriteLockTest lockTest; + private int sleepTime; public WriteLocker(ReadWriteLock aLock, ReadWriteLockTest aLockTest, int aSleepTime) { - _lock = aLock; - _lockTest = aLockTest; - _sleepTime = aSleepTime; + lock = aLock; + lockTest = aLockTest; + sleepTime = aSleepTime; } public void run() { - _lock.acquireWrite(); - _lockTest.incrementWriterCount(); + lock.acquireWrite(); + lockTest.incrementWriterCount(); try { - Thread.sleep(_sleepTime); + Thread.sleep(sleepTime); } catch (InterruptedException e) { - Assert.fail("WriteLocker thread was interrupted: " - + Thread.currentThread()); + throw new RuntimeException("WriteLocker thread was interrupted: " + + Thread.currentThread()); } - _lock.releaseWrite(); - _lockTest.decrementWriterCount(); + lock.releaseWrite(); + lockTest.decrementWriterCount(); } } diff --git a/support/general/src/test/java/org/wamblee/conditions/AndConditionTest.java b/support/general/src/test/java/org/wamblee/conditions/AndConditionTest.java index 81c4e4ed..f9faa729 100644 --- a/support/general/src/test/java/org/wamblee/conditions/AndConditionTest.java +++ b/support/general/src/test/java/org/wamblee/conditions/AndConditionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,52 +13,53 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; +import junit.framework.TestCase; + import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - /** - * Tests the Or Condition. - * + * Tests the Or Condition. + * * @author Erik Brakkee */ public class AndConditionTest extends TestCase { - - public void checkResult(boolean aFirst, boolean aSecond, boolean aResult) { - AndCondition and = new AndCondition(new FixedCondition(aFirst), - new FixedCondition(aSecond)); + public void checkResult(boolean aFirst, boolean aSecond, boolean aResult) { + AndCondition and = new AndCondition( + new FixedCondition(aFirst), new FixedCondition( + aSecond)); assertEquals(aResult, and.matches(0)); } - - public void checkResult(boolean[] aValues, boolean aResult) { + + public void checkResult(boolean[] aValues, boolean aResult) { List> conditions = new ArrayList>(); - for (boolean value: aValues) { - conditions.add(new FixedCondition(value)); + + for (boolean value : aValues) { + conditions.add(new FixedCondition(value)); } + AndCondition and = new AndCondition(conditions); - assertEquals(aResult, and.matches(new Integer(0))); + assertEquals(aResult, and.matches(Integer.valueOf(0))); } /** - * Checks all combinations of two conditions. - * + * Checks all combinations of two conditions. + * */ - public void testTwoConditions() { + public void testTwoConditions() { checkResult(false, false, false); checkResult(true, false, false); - checkResult(false, true, false); + checkResult(false, true, false); checkResult(true, true, true); } - - public void testMultipleConditions() { - checkResult(new boolean[]{ false, false, false} , false); - checkResult(new boolean[]{ true, false, false }, false); - checkResult(new boolean[]{ false, true, false }, false); - checkResult(new boolean[]{ false, false, true }, false); - checkResult(new boolean[]{ true, true, true }, true); + + public void testMultipleConditions() { + checkResult(new boolean[] { false, false, false }, false); + checkResult(new boolean[] { true, false, false }, false); + checkResult(new boolean[] { false, true, false }, false); + checkResult(new boolean[] { false, false, true }, false); + checkResult(new boolean[] { true, true, true }, true); } } diff --git a/support/general/src/test/java/org/wamblee/conditions/GreaterThanCondition.java b/support/general/src/test/java/org/wamblee/conditions/GreaterThanCondition.java index bdb95897..a94a1615 100644 --- a/support/general/src/test/java/org/wamblee/conditions/GreaterThanCondition.java +++ b/support/general/src/test/java/org/wamblee/conditions/GreaterThanCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; /** - * Test condition object. - * + * Test condition object. + * * @author Erik Brakkee */ public class GreaterThanCondition implements Condition { - - private int _value; - - public GreaterThanCondition(int aValue) { - _value = aValue; + private int value; + + public GreaterThanCondition(int aValue) { + value = aValue; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.conditions.Condition#matches(T) */ public boolean matches(Integer aObject) { - return aObject > _value; + return aObject > value; } - } diff --git a/support/general/src/test/java/org/wamblee/conditions/LessThanCondition.java b/support/general/src/test/java/org/wamblee/conditions/LessThanCondition.java index 06ab192a..b112cff2 100644 --- a/support/general/src/test/java/org/wamblee/conditions/LessThanCondition.java +++ b/support/general/src/test/java/org/wamblee/conditions/LessThanCondition.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; /** - * Test condition object. - * + * Test condition object. + * * @author Erik Brakkee */ public class LessThanCondition implements Condition { - - private int _value; - - public LessThanCondition(int aValue) { - _value = aValue; + private int value; + + public LessThanCondition(int aValue) { + value = aValue; } - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see org.wamblee.conditions.Condition#matches(T) */ public boolean matches(Integer aObject) { - return aObject < _value; + return aObject < value; } - } diff --git a/support/general/src/test/java/org/wamblee/conditions/OrConditionTest.java b/support/general/src/test/java/org/wamblee/conditions/OrConditionTest.java index c3f7df1e..9afadfee 100644 --- a/support/general/src/test/java/org/wamblee/conditions/OrConditionTest.java +++ b/support/general/src/test/java/org/wamblee/conditions/OrConditionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,52 +13,53 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; +import junit.framework.TestCase; + import java.util.ArrayList; import java.util.List; -import junit.framework.TestCase; - /** - * Tests the Or Condition. - * + * Tests the Or Condition. + * * @author Erik Brakkee */ public class OrConditionTest extends TestCase { - - public void checkResult(boolean aFirst, boolean aSecond, boolean aResult) { - OrCondition or = new OrCondition(new FixedCondition(aFirst), - new FixedCondition(aSecond)); + public void checkResult(boolean aFirst, boolean aSecond, boolean aResult) { + OrCondition or = new OrCondition( + new FixedCondition(aFirst), new FixedCondition( + aSecond)); assertEquals(aResult, or.matches(0)); } - - public void checkResult(boolean[] aValues, boolean aResult) { + + public void checkResult(boolean[] aValues, boolean aResult) { List> conditions = new ArrayList>(); - for (boolean value: aValues) { - conditions.add(new FixedCondition(value)); + + for (boolean value : aValues) { + conditions.add(new FixedCondition(value)); } + OrCondition or = new OrCondition(conditions); - assertEquals(aResult, or.matches(new Integer(0))); + assertEquals(aResult, or.matches(Integer.valueOf(0))); } /** - * Checks all combinations of two conditions. - * + * Checks all combinations of two conditions. + * */ - public void testTwoConditions() { + public void testTwoConditions() { checkResult(false, false, false); checkResult(true, false, true); - checkResult(false, true, true); + checkResult(false, true, true); checkResult(true, true, true); } - - public void testMultipleConditions() { - checkResult(new boolean[]{ false, false, false} , false); - checkResult(new boolean[]{ true, false, false }, true); - checkResult(new boolean[]{ false, true, false }, true); - checkResult(new boolean[]{ false, false, true }, true); - checkResult(new boolean[]{ true, true, true }, true); + + public void testMultipleConditions() { + checkResult(new boolean[] { false, false, false }, false); + checkResult(new boolean[] { true, false, false }, true); + checkResult(new boolean[] { false, true, false }, true); + checkResult(new boolean[] { false, false, true }, true); + checkResult(new boolean[] { true, true, true }, true); } } diff --git a/support/general/src/test/java/org/wamblee/conditions/PropertyRegexConditionTest.java b/support/general/src/test/java/org/wamblee/conditions/PropertyRegexConditionTest.java index 9f494fb6..f69a1e33 100644 --- a/support/general/src/test/java/org/wamblee/conditions/PropertyRegexConditionTest.java +++ b/support/general/src/test/java/org/wamblee/conditions/PropertyRegexConditionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,67 +13,75 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; import junit.framework.TestCase; /** - * Tests {@link org.wamblee.conditions.PropertyRegexCondition}. - * + * Tests {@link org.wamblee.conditions.PropertyRegexCondition}. + * * @author Erik Brakkee */ public class PropertyRegexConditionTest extends TestCase { - - private boolean match(String aProperty, String aRegex, boolean aToLower, TestBean aBean) { - PropertyRegexCondition condition = new PropertyRegexCondition(aProperty, aRegex, aToLower ); + private boolean match(String aProperty, String aRegex, boolean aToLower, + TestBean aBean) { + PropertyRegexCondition condition = new PropertyRegexCondition( + aProperty, aRegex, aToLower); + return condition.matches(aBean); } - - private void checkMatch(String aProperty, String aRegex, boolean aToLower, TestBean aBean, boolean aResult) { - assertEquals( aResult, match(aProperty, aRegex, aToLower, aBean)); + + private void checkMatch(String aProperty, String aRegex, boolean aToLower, + TestBean aBean, boolean aResult) { + assertEquals(aResult, match(aProperty, aRegex, aToLower, aBean)); } - + /** - * Verifies correct matching behavior for several cases. - * + * Verifies correct matching behavior for several cases. + * */ public void testMatchProperty() { - TestBean bean = new TestBean("Hallo"); - checkMatch("value", "Hallo", false, bean, true); + TestBean bean = new TestBean("Hallo"); + checkMatch("value", "Hallo", false, bean, true); checkMatch("value", "all", false, bean, false); checkMatch("value", ".a.*o", false, bean, true); - checkMatch("value", "hallo", false, bean, false); // no match when not converting to lower case. + checkMatch("value", "hallo", false, bean, false); // no match when not + // converting to lower + // case. checkMatch("value", "hallo", true, bean, true); // match! } - + /** - * Uses property regex condition for non-existing property. - * Verifies that a runtime exception is thrown. - * + * Uses property regex condition for non-existing property. Verifies that a + * runtime exception is thrown. + * */ - public void testWrongProperty() { + public void testWrongProperty() { TestBean bean = new TestBean("Hallo"); - try { - match("bla", ".*", false, bean); - } catch (RuntimeException e) { - return; // ok + + try { + match("bla", ".*", false, bean); + } catch (RuntimeException e) { + return; // ok } + fail(); } - + /** - * Applies condition to a private property. Verifies that a runtime - * exception is thrown. - * + * Applies condition to a private property. Verifies that a runtime + * exception is thrown. + * */ - public void testPrivateProperty() { + public void testPrivateProperty() { TestBean bean = new TestBean("Hallo"); - try { - match("privateValue", ".*", false, bean); - } catch (RuntimeException e) { - return; // ok + + try { + match("privateValue", ".*", false, bean); + } catch (RuntimeException e) { + return; // ok } + fail(); } } diff --git a/support/general/src/test/java/org/wamblee/conditions/TestBean.java b/support/general/src/test/java/org/wamblee/conditions/TestBean.java index 7bcd6d20..0b3461e6 100644 --- a/support/general/src/test/java/org/wamblee/conditions/TestBean.java +++ b/support/general/src/test/java/org/wamblee/conditions/TestBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,27 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.conditions; /** * - * + * * @author Erik Brakkee */ public class TestBean { + private String value; - private String _value; - - public TestBean(String aValue) { - _value = aValue; + public TestBean(String aValue) { + value = aValue; } - - public String getValue() { - return _value; + + public String getValue() { + return value; } - - private String getPrivateValue() { - return _value; + + private String getPrivateValue() { + return value; } } diff --git a/support/general/src/test/java/org/wamblee/general/BeanKernelTest.java b/support/general/src/test/java/org/wamblee/general/BeanKernelTest.java index 2c9f898f..35b5af50 100644 --- a/support/general/src/test/java/org/wamblee/general/BeanKernelTest.java +++ b/support/general/src/test/java/org/wamblee/general/BeanKernelTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.general; import junit.framework.TestCase; @@ -22,11 +21,10 @@ import junit.framework.TestCase; * Tests the bean kernel. The lookup of the bean factory itself can be tested * only partially. Using a global property file for all test cases would tie all * test cases together therefore no global property file is used. - * + * * @author Erik Brakkee */ public class BeanKernelTest extends TestCase { - /** * Loads the bean factory based on a property file configuration. Verifies * the correct bean factory is loaded. @@ -34,41 +32,41 @@ public class BeanKernelTest extends TestCase { */ public void testLoadBeanFactoryFromProperties() { BeanFactory factory = BeanKernel - .lookupBeanFactory("org/wamblee/general/beankernel.properties"); + .lookupBeanFactory("org/wamblee/general/beankernel.properties"); assertTrue(factory instanceof TestBeanFactory); } /** - * Loads the bean factory based on a non-existing property file. - * Verifies that BeanFactoryException is thrown. + * Loads the bean factory based on a non-existing property file. Verifies + * that BeanFactoryException is thrown. * */ public void testNonExistentPropertyFile() { try { BeanKernel - .lookupBeanFactory("org/wamblee/general/beankernel-nonexistent.properties"); + .lookupBeanFactory("org/wamblee/general/beankernel-nonexistent.properties"); } catch (BeanFactoryException e) { return; // ok } + fail(); } - + /** - * Loads the bean factory based on a property file with a non-existing - * bean factory defined in it. - * Verifies that BeanFactoryException is thrown. + * Loads the bean factory based on a property file with a non-existing bean + * factory defined in it. Verifies that BeanFactoryException is thrown. * */ public void testNonExistentBeanFactory() { try { BeanKernel - .lookupBeanFactory("org/wamblee/general/beankernel-wrong.properties"); + .lookupBeanFactory("org/wamblee/general/beankernel-wrong.properties"); } catch (BeanFactoryException e) { return; // ok } + fail(); } - /** * Retrieves a bean factory throug the bean kernel. Verifies that beans can @@ -77,12 +75,12 @@ public class BeanKernelTest extends TestCase { */ public void testRetrieveFactory() { BeanKernel.overrideBeanFactory(new TestBeanFactory()); // bypass - // default - // property - // lookup + // default + // property + // lookup + BeanFactory factory = BeanKernel.getBeanFactory(); assertNotNull(factory); assertEquals("hello", factory.find(String.class)); } - } diff --git a/support/general/src/test/java/org/wamblee/general/PairTest.java b/support/general/src/test/java/org/wamblee/general/PairTest.java index dcb6f614..9dad7030 100644 --- a/support/general/src/test/java/org/wamblee/general/PairTest.java +++ b/support/general/src/test/java/org/wamblee/general/PairTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,25 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.general; import junit.framework.TestCase; /** - * Tests the pair class. + * Tests the pair class. */ public class PairTest extends TestCase { - - public void testPair() { - Pair pair = new Pair(10, "hello"); - assertEquals(new Integer(10), pair.getFirst()); + public void testPair() { + Pair pair = new Pair(10, "hello"); + assertEquals(Integer.valueOf(10), pair.getFirst()); assertEquals("hello", pair.getSecond()); - + Pair pair2 = new Pair(pair); - assertEquals(new Integer(10), pair2.getFirst()); + assertEquals(Integer.valueOf(10), pair2.getFirst()); assertEquals("hello", pair2.getSecond()); - - } } diff --git a/support/general/src/test/java/org/wamblee/general/TestBeanFactory.java b/support/general/src/test/java/org/wamblee/general/TestBeanFactory.java index 6198e9ba..5c22caf1 100644 --- a/support/general/src/test/java/org/wamblee/general/TestBeanFactory.java +++ b/support/general/src/test/java/org/wamblee/general/TestBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +16,22 @@ package org.wamblee.general; public class TestBeanFactory implements BeanFactory { + @Override + public Object find(String aId) { + return null; + } - @Override - public Object find(String aId) { - return null; - } + @Override + public T find(Class aClass) { + if (aClass.equals(String.class)) { + return (T) "hello"; + } - @Override - public T find(Class aClass) { - if ( aClass.equals(String.class)) { - return (T)"hello"; - } - return null; - } - - @Override - public T find(String aId, Class aClass) { - return null; - } + return null; + } + @Override + public T find(String aId, Class aClass) { + return null; + } } diff --git a/support/general/src/test/java/org/wamblee/io/ClassPathResourceTest.java b/support/general/src/test/java/org/wamblee/io/ClassPathResourceTest.java index 70b05ab5..6baf1f86 100644 --- a/support/general/src/test/java/org/wamblee/io/ClassPathResourceTest.java +++ b/support/general/src/test/java/org/wamblee/io/ClassPathResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,28 +12,25 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.io; +import junit.framework.TestCase; + import java.io.IOException; import java.io.InputStream; - -import junit.framework.TestCase; - /** * Tests for the classpath resource. */ public class ClassPathResourceTest extends TestCase { - /** * Loads an existing resource from the class path. Verifies it is found. * */ public void testResourceFound() throws IOException { ClassPathResource resource = new ClassPathResource( - "org/wamblee/io/myresource.txt"); + "org/wamblee/io/myresource.txt"); InputStream is = resource.getInputStream(); String data = FileSystemUtils.read(is); assertEquals("This is my resource", data); @@ -47,11 +44,12 @@ public class ClassPathResourceTest extends TestCase { public void testResourceNotFound() { try { ClassPathResource resource = new ClassPathResource( - "org/wamblee/io/myresource-nonexistent.txt"); - InputStream is = resource.getInputStream(); + "org/wamblee/io/myresource-nonexistent.txt"); + resource.getInputStream(); } catch (IOException e) { return; // ok } + fail(); } } diff --git a/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTest.java b/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTest.java index 12db916e..2e0068fc 100644 --- a/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTest.java +++ b/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,111 +12,107 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; -import static org.mockito.Mockito.*; import junit.framework.TestCase; import org.apache.oro.io.AwkFilenameFilter; +import static org.mockito.Mockito.*; public class DirectoryMonitorTest extends TestCase { - - private static final String REGEX = "^.*\\.txt$"; - private static final String FILE1 = "file1.txt"; - - private TestData _data; - private DirectoryMonitor.Listener _listener; - - private DirectoryMonitor _monitor; - - @Override - protected void setUp() throws Exception { - super.setUp(); - _data = new TestData(this); - _data.clean(); - _listener = mock(DirectoryMonitor.Listener.class); - _monitor = new DirectoryMonitor(_data.getRoot(), new AwkFilenameFilter( - REGEX), _listener); - } - - public void testEmptyDir() { - // Nothing is expected to be called. - for (int i = 0; i < 10; i++) { - _monitor.poll(); - verifyNoMoreInteractions(_listener); - } - } - - public void testFileCreated() { - _data.createFile(FILE1, "hello"); - _monitor.poll(); - verify(_listener).fileCreated(_data.getFile(FILE1)); - } - - public void testFileDeleted() { - _data.createFile(FILE1, "hello"); - _monitor.poll(); - reset(_listener); - - _data.deleteFile(FILE1); - _monitor.poll(); - - verify(_listener).fileDeleted(_data.getFile(FILE1)); - verifyNoMoreInteractions(_listener); - } - - public void testFileChanged() throws InterruptedException { - _data.createFile(FILE1, "hello"); - _monitor.poll(); - reset(_listener); - - Thread.sleep(2000); - _data.deleteFile(FILE1); - _data.createFile(FILE1, "bla"); - - _monitor.poll(); - verify(_listener).fileChanged(_data.getFile(FILE1)); - verifyNoMoreInteractions(_listener); - } - - public void testFileFilterIsUsed() { - _monitor.poll(); - - _data.createFile("file.xml", "hello"); - _monitor.poll(); - verifyNoMoreInteractions(_listener); - } - - public void testDirectoryIsIgnored() { - _monitor.poll(); - _data.createDir(FILE1); - _monitor.poll(); - verifyNoMoreInteractions(_listener); - } - - public void testExceptionsWIllLeadToRepeatedNotifications() { - _monitor.poll(); - _data.createFile(FILE1, "hello"); - - stubVoid(_listener).toThrow(new RuntimeException()).on(). - fileCreated(_data.getFile(FILE1)); - - try { - _monitor.poll(); - } catch (RuntimeException e) { - reset(_listener); - - // polling again should lead to the same filecreated call. - // this time no exception is thrown. - - _monitor.poll(); - verify(_listener).fileCreated(_data.getFile(FILE1)); - verifyNoMoreInteractions(_listener); - return; - } - fail(); // should not get here. - - - } + private static final String REGEX = "^.*\\.txt$"; + private static final String FILE1 = "file1.txt"; + private TestData data; + private DirectoryMonitor.Listener listener; + private DirectoryMonitor monitor; + + @Override + protected void setUp() throws Exception { + super.setUp(); + data = new TestData(this); + data.clean(); + listener = mock(DirectoryMonitor.Listener.class); + monitor = new DirectoryMonitor(data.getRoot(), new AwkFilenameFilter( + REGEX), listener); + } + + public void testEmptyDir() { + // Nothing is expected to be called. + for (int i = 0; i < 10; i++) { + monitor.poll(); + verifyNoMoreInteractions(listener); + } + } + + public void testFileCreated() { + data.createFile(FILE1, "hello"); + monitor.poll(); + verify(listener).fileCreated(data.getFile(FILE1)); + } + + public void testFileDeleted() { + data.createFile(FILE1, "hello"); + monitor.poll(); + reset(listener); + + data.deleteFile(FILE1); + monitor.poll(); + + verify(listener).fileDeleted(data.getFile(FILE1)); + verifyNoMoreInteractions(listener); + } + + public void testFileChanged() throws InterruptedException { + data.createFile(FILE1, "hello"); + monitor.poll(); + reset(listener); + + Thread.sleep(2000); + data.deleteFile(FILE1); + data.createFile(FILE1, "bla"); + + monitor.poll(); + verify(listener).fileChanged(data.getFile(FILE1)); + verifyNoMoreInteractions(listener); + } + + public void testFileFilterIsUsed() { + monitor.poll(); + + data.createFile("file.xml", "hello"); + monitor.poll(); + verifyNoMoreInteractions(listener); + } + + public void testDirectoryIsIgnored() { + monitor.poll(); + data.createDir(FILE1); + monitor.poll(); + verifyNoMoreInteractions(listener); + } + + public void testExceptionsWIllLeadToRepeatedNotifications() { + monitor.poll(); + data.createFile(FILE1, "hello"); + + stubVoid(listener).toThrow(new RuntimeException()).on().fileCreated( + data.getFile(FILE1)); + + try { + monitor.poll(); + } catch (RuntimeException e) { + reset(listener); + + // polling again should lead to the same filecreated call. + // this time no exception is thrown. + monitor.poll(); + verify(listener).fileCreated(data.getFile(FILE1)); + verifyNoMoreInteractions(listener); + + return; + } + + fail(); // should not get here. + } } diff --git a/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTestProgram.java b/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTestProgram.java index 4f301cf7..a28b5968 100644 --- a/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTestProgram.java +++ b/support/general/src/test/java/org/wamblee/io/DirectoryMonitorTestProgram.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,39 +13,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.io; -import java.io.File; - import org.apache.oro.io.AwkFilenameFilter; +import java.io.File; + /** * - * + * * @author Erik Brakkee */ public class DirectoryMonitorTestProgram { - - public static void main(String[] aArgs) throws Exception { - - DirectoryMonitor monitor = new DirectoryMonitor(new File("."), - new AwkFilenameFilter(".*\\.txt"), new DirectoryMonitor.Listener() { - public void fileChanged(File aFile) { - System.out.println("changed " + aFile); - } - public void fileCreated(File aFile) { - System.out.println("created " + aFile); - } - public void fileDeleted(File aFile) { - System.out.println("deleted " + aFile); - } - }); - - for (;;) { + public static void main(String[] aArgs) throws Exception { + DirectoryMonitor monitor = new DirectoryMonitor(new File("."), + new AwkFilenameFilter(".*\\.txt"), new DirectoryMonitor.Listener() { + public void fileChanged(File aFile) { + System.out.println("changed " + aFile); + } + + public void fileCreated(File aFile) { + System.out.println("created " + aFile); + } + + public void fileDeleted(File aFile) { + System.out.println("deleted " + aFile); + } + }); + + for (;;) { monitor.poll(); Thread.sleep(1000); } } - } diff --git a/support/general/src/test/java/org/wamblee/io/FileResourceTest.java b/support/general/src/test/java/org/wamblee/io/FileResourceTest.java index c1564f04..92b0c644 100644 --- a/support/general/src/test/java/org/wamblee/io/FileResourceTest.java +++ b/support/general/src/test/java/org/wamblee/io/FileResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,50 +13,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.io; +import junit.framework.TestCase; + import java.io.File; import java.io.IOException; import java.io.InputStream; - -import junit.framework.TestCase; - /** - * Tests the file resource. - * + * Tests the file resource. + * * @author Erik Brakkee */ public class FileResourceTest extends TestCase { - /** * Loads an existing resource. Verifies it is found. * */ public void testResourceFound() throws IOException { - FileResource resource = new FileResource( new File( - FileSystemUtils.getTestInputDir(FileResourceTest.class), - "myresource.txt")); + FileResource resource = new FileResource(new File(FileSystemUtils + .getTestInputDir(FileResourceTest.class), "myresource.txt")); InputStream is = resource.getInputStream(); String data = FileSystemUtils.read(is); assertEquals("This is my resource", data); } /** - * Loads a non-existing resource. Verifies that an IO - * exception is thrown. + * Loads a non-existing resource. Verifies that an IO exception is thrown. * */ public void testResourceNotFound() { try { - FileResource resource = new FileResource( new File( - FileSystemUtils.getTestInputDir(FileResourceTest.class), - "myresource-nonexistent.txt")); - InputStream is = resource.getInputStream(); + FileResource resource = new FileResource(new File(FileSystemUtils + .getTestInputDir(FileResourceTest.class), + "myresource-nonexistent.txt")); + resource.getInputStream(); } catch (IOException e) { return; // ok } + fail(); } } diff --git a/support/general/src/test/java/org/wamblee/io/FileSystemUtils.java b/support/general/src/test/java/org/wamblee/io/FileSystemUtils.java index ad3b4e20..4be787e7 100644 --- a/support/general/src/test/java/org/wamblee/io/FileSystemUtils.java +++ b/support/general/src/test/java/org/wamblee/io/FileSystemUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,9 +12,15 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -22,17 +28,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; + import java.net.URL; import java.net.URLDecoder; + import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; -import java.security.CodeSource; - -import junit.framework.Assert; -import junit.framework.TestCase; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import java.security.CodeSource; /** * File system utilities. @@ -40,330 +43,352 @@ import org.apache.commons.logging.LogFactory; * @author Erik Brakkee */ public final class FileSystemUtils { - - private static final Log LOG = LogFactory.getLog(FileSystemUtils.class); - - /** - * Test output directory relative to the sub project. - */ - private static final String TEST_OUTPUT_DIR = "../target/testoutput"; - - /** - * Test input directory relative to the sub project. - */ - private static final String TEST_INPUT_DIR = "../src/test/resources"; - - /* - * Disabled. - * - */ - private FileSystemUtils() { - // Empty - } - - /** - * Deletes a directory recursively. The test case will fail if the directory - * does not exist or if deletion fails. - * - * @param aDir - * Directory to delete. - */ - public static void deleteDirRecursively(String aDir) { - deleteDirRecursively(new File(aDir)); - } - - /** - * Deletes a directory recursively. See {@link #deleteDirRecursively}. - * - * @param aDir - * Directory. - */ - public static void deleteDirRecursively(File aDir) { - TestCase.assertTrue(aDir.isDirectory()); - - for (File file : aDir.listFiles()) { - if (file.isDirectory()) { - deleteDirRecursively(file); - } else { - delete(file); - } - } - - delete(aDir); - } - - /** - * Deletes a file or directory. The test case will fail if the file or - * directory does not exist or if deletion fails. Deletion of a non-empty - * directory will always fail. - * - * @param aFile - * File or directory to delete. - */ - public static void delete(File aFile) { - TestCase.assertTrue(aFile.delete()); - } - - /** - * Gets a path relative to a sub project. This utility should be used to - * easily access file paths within a subproject without requiring any - * specific Eclipse configuration. - * - * @param aRelativePath - * Relative path. - * @param aTestClass - * Test class. - */ - public static File getPath(String aRelativePath, Class aTestClass) { - CodeSource source = aTestClass.getProtectionDomain().getCodeSource(); - if (source == null) { - LOG.warn("Could not obtain path for '" + aRelativePath - + "' for class " + aTestClass - + ", using relative path as is"); - return new File(aRelativePath); - } - URL location = source.getLocation(); - String protocol = location.getProtocol(); - if (!protocol.equals("file")) { - LOG.warn("protocol is not 'file': " + location); - return new File(aRelativePath); - } - - String path = location.getPath(); - try { - path = URLDecoder.decode(location.getPath(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - // ignore it.. just don't decode - LOG.warn("Decoding path failed: '" + location.getPath() + "'", e); - } - - return new File(new File(path).getParentFile(), aRelativePath); - } - - /** - * Ensures that a directory hierarchy exists (recursively if needed). If it - * is not possible to create the directory, then the test case will fail. - * - * @param aDir - * Directory to create. - */ - public static void createDir(File aDir) { - if (aDir.exists() && !aDir.isDirectory()) { - TestCase.fail("'" + aDir - + "' already exists and is not a directory"); - } - if (aDir.exists()) { - return; - } - createDir(aDir.getParentFile()); - TestCase.assertTrue("Could not create '" + aDir + "'", aDir.mkdir()); - } - - /** - * Creates a file in a directory. - * @param aDir Directory path. Will be created if it does not exist. - * @param aName Filename. - * @param aContents Contents. - */ - public static void createFile(File aDir, String aName, InputStream aContents) { - createDir(aDir); - try { - OutputStream os = new FileOutputStream(new File(aDir, aName)); - copyStream(aContents, os); - } catch (IOException e) { - e.printStackTrace(); - TestCase.fail(e.getMessage()); - } - } - - /** - * Gets the test output directory for a specific test class. - * - * @param aTestClass - * Test class. - * @return Test output directory. - */ - public static File getTestOutputDir(Class aTestClass) { - File file = getPath(TEST_OUTPUT_DIR, aTestClass); - String className = aTestClass.getName(); - String classRelPath = className.replaceAll("\\.", "/"); - return new File(file, classRelPath); - } - - /** - * Gets the test input directory for a specific test class. - * - * @param aTestClass - * Test class. - * @return Test input directory. - */ - public static File getTestInputDir(Class aTestClass) { - File file = getPath(TEST_INPUT_DIR, aTestClass); - String packageName = aTestClass.getPackage().getName(); - String packagePath = packageName.replaceAll("\\.", "/"); - return new File(file, packagePath); - } - - /** - * Creates a directory hierarchy for the output directory of a test class if - * needed. - * - * @param aTestClass - * Test class - * @return Test directory. - */ - public static File createTestOutputDir(Class aTestClass) { - File file = getTestOutputDir(aTestClass); - createDir(file); - return file; - } - - /** - * Gets a test output file name. This returns a File object representing the - * output file and ensures that the directory where the file will be created - * already exists. - * - * @param aName - * Name of the file. - * @param aTestClass - * Test class. - * @return File. - */ - public static File getTestOutputFile(String aName, Class aTestClass) { - File file = new File(getTestOutputDir(aTestClass), aName); - createDir(file.getParentFile()); - return file; - } - - public static String read(InputStream aIs) throws IOException { - try { - StringBuffer buffer = new StringBuffer(); - int c; - while ((c = aIs.read()) != -1) { - buffer.append((char) c); - } - return buffer.toString(); - } finally { - aIs.close(); - } - } - - /** - * Copies an input stream to an output stream. - * - * @param aIs - * Input stream. - * @param aOs - * Output stream. - */ - public static void copyStream(InputStream aIs, OutputStream aOs) { - try { - int c; - while ((c = aIs.read()) != -1) { - aOs.write(c); - } - aIs.close(); - aOs.close(); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail(e.getMessage()); - } - } - - /** - * Recursively copy a directory. - * - * @param aSrc - * Source directory - * @param aTarget - * Target directory. - */ - public static void copyDir(File aSrc, File aTarget) { - Assert.assertTrue(aSrc.isDirectory()); - Assert.assertTrue(!aTarget.exists()); - - aTarget.mkdirs(); - - File[] files = aSrc.listFiles(); - for (int i = 0; i < files.length; i++) { - File file = files[i]; - if (file.isDirectory()) { - if (!file.getName().equals(".svn")) { - copyDir(new File(aSrc, file.getName()), new File(aTarget, - file.getName())); - } - } else { - copyFile(file, new File(aTarget, file.getName())); - } - } - } - - /** - * Copy a file. If copying fails then the testcase will fail. - * - * @param aSrc - * Source file. - * @param aTarget - * Target file. - */ - public static void copyFile(File aSrc, File aTarget) { - - try { - FileInputStream fis = new FileInputStream(aSrc); - FileOutputStream fos = new FileOutputStream(aTarget); - FileChannel fcin = fis.getChannel(); - FileChannel fcout = fos.getChannel(); - - // map input file - - MappedByteBuffer mbb = fcin.map(FileChannel.MapMode.READ_ONLY, 0, - fcin.size()); - - // do the file copy - fcout.write(mbb); - - // finish up - - fcin.close(); - fcout.close(); - fis.close(); - fos.close(); - } catch (IOException e) { - Assert.assertTrue("Copying file " + aSrc.getPath() + " to " - + aTarget.getPath() + " failed.", false); - } - } - - /** - * Remove all files within a given directory including the directory itself. - * This only attempts to remove regular files and not directories within the - * directory. If the directory contains a nested directory, the deletion - * will fail. The test case will fail if this fails. - * - * @param aDir - * Directory to remove. - */ - public static void deleteDir(File aDir) { - cleanDir(aDir); - delete(aDir); - } - - /** - * Remove all regular files within a given directory. - * - * @param outputDirName - */ - public static void cleanDir(File aDir) { - if (!aDir.exists()) { - return; // nothing to do. - } - File[] entries = aDir.listFiles(); - for (int i = 0; i < entries.length; i++) { - File file = entries[i]; - if (file.isFile()) { - Assert.assertTrue("Could not delete " + entries[i].getPath(), - entries[i].delete()); - } - } - } + private static final Log LOG = LogFactory.getLog(FileSystemUtils.class); + + /** + * Test output directory relative to the sub project. + */ + private static final String TEST_OUTPUT_DIR = "../target/testoutput"; + + /** + * Test input directory relative to the sub project. + */ + private static final String TEST_INPUT_DIR = "../src/test/resources"; + + /* + * Disabled. + */ + private FileSystemUtils() { + // Empty + } + + /** + * Deletes a directory recursively. The test case will fail if the directory + * does not exist or if deletion fails. + * + * @param aDir + * Directory to delete. + */ + public static void deleteDirRecursively(String aDir) { + deleteDirRecursively(new File(aDir)); + } + + /** + * Deletes a directory recursively. See {@link #deleteDirRecursively}. + * + * @param aDir + * Directory. + */ + public static void deleteDirRecursively(File aDir) { + TestCase.assertTrue(aDir.isDirectory()); + + for (File file : aDir.listFiles()) { + if (file.isDirectory()) { + deleteDirRecursively(file); + } else { + delete(file); + } + } + + delete(aDir); + } + + /** + * Deletes a file or directory. The test case will fail if the file or + * directory does not exist or if deletion fails. Deletion of a non-empty + * directory will always fail. + * + * @param aFile + * File or directory to delete. + */ + public static void delete(File aFile) { + TestCase.assertTrue(aFile.delete()); + } + + /** + * Gets a path relative to a sub project. This utility should be used to + * easily access file paths within a subproject without requiring any + * specific Eclipse configuration. + * + * @param aRelativePath + * Relative path. + * @param aTestClass + * Test class. + */ + public static File getPath(String aRelativePath, Class aTestClass) { + CodeSource source = aTestClass.getProtectionDomain().getCodeSource(); + + if (source == null) { + LOG.warn("Could not obtain path for '" + aRelativePath + + "' for class " + aTestClass + ", using relative path as is"); + + return new File(aRelativePath); + } + + URL location = source.getLocation(); + String protocol = location.getProtocol(); + + if (!protocol.equals("file")) { + LOG.warn("protocol is not 'file': " + location); + + return new File(aRelativePath); + } + + String path = location.getPath(); + + try { + path = URLDecoder.decode(location.getPath(), "UTF-8"); + } catch (UnsupportedEncodingException e) { + // ignore it.. just don't decode + LOG.warn("Decoding path failed: '" + location.getPath() + "'", e); + } + + return new File(new File(path).getParentFile(), aRelativePath); + } + + /** + * Ensures that a directory hierarchy exists (recursively if needed). If it + * is not possible to create the directory, then the test case will fail. + * + * @param aDir + * Directory to create. + */ + public static void createDir(File aDir) { + if (aDir.exists() && !aDir.isDirectory()) { + TestCase.fail("'" + aDir + + "' already exists and is not a directory"); + } + + if (aDir.exists()) { + return; + } + + createDir(aDir.getParentFile()); + TestCase.assertTrue("Could not create '" + aDir + "'", aDir.mkdir()); + } + + /** + * Creates a file in a directory. + * + * @param aDir + * Directory path. Will be created if it does not exist. + * @param aName + * Filename. + * @param aContents + * Contents. + */ + public static void createFile(File aDir, String aName, InputStream aContents) { + createDir(aDir); + + try { + OutputStream os = new FileOutputStream(new File(aDir, aName)); + copyStream(aContents, os); + } catch (IOException e) { + e.printStackTrace(); + TestCase.fail(e.getMessage()); + } + } + + /** + * Gets the test output directory for a specific test class. + * + * @param aTestClass + * Test class. + * @return Test output directory. + */ + public static File getTestOutputDir(Class aTestClass) { + File file = getPath(TEST_OUTPUT_DIR, aTestClass); + String className = aTestClass.getName(); + String classRelPath = className.replaceAll("\\.", "/"); + + return new File(file, classRelPath); + } + + /** + * Gets the test input directory for a specific test class. + * + * @param aTestClass + * Test class. + * @return Test input directory. + */ + public static File getTestInputDir(Class aTestClass) { + File file = getPath(TEST_INPUT_DIR, aTestClass); + String packageName = aTestClass.getPackage().getName(); + String packagePath = packageName.replaceAll("\\.", "/"); + + return new File(file, packagePath); + } + + /** + * Creates a directory hierarchy for the output directory of a test class if + * needed. + * + * @param aTestClass + * Test class + * @return Test directory. + */ + public static File createTestOutputDir(Class aTestClass) { + File file = getTestOutputDir(aTestClass); + createDir(file); + + return file; + } + + /** + * Gets a test output file name. This returns a File object representing the + * output file and ensures that the directory where the file will be created + * already exists. + * + * @param aName + * Name of the file. + * @param aTestClass + * Test class. + * @return File. + */ + public static File getTestOutputFile(String aName, Class aTestClass) { + File file = new File(getTestOutputDir(aTestClass), aName); + createDir(file.getParentFile()); + + return file; + } + + public static String read(InputStream aIs) throws IOException { + try { + StringBuffer buffer = new StringBuffer(); + int c; + + while ((c = aIs.read()) != -1) { + buffer.append((char) c); + } + + return buffer.toString(); + } finally { + aIs.close(); + } + } + + /** + * Copies an input stream to an output stream. + * + * @param aIs + * Input stream. + * @param aOs + * Output stream. + */ + public static void copyStream(InputStream aIs, OutputStream aOs) { + try { + int c; + + while ((c = aIs.read()) != -1) { + aOs.write(c); + } + + aIs.close(); + aOs.close(); + } catch (IOException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + + /** + * Recursively copy a directory. + * + * @param aSrc + * Source directory + * @param aTarget + * Target directory. + */ + public static void copyDir(File aSrc, File aTarget) { + Assert.assertTrue(aSrc.isDirectory()); + Assert.assertTrue(!aTarget.exists()); + + if (!aTarget.mkdirs()) { + Assert.fail("Could not create target directory '" + aTarget + "'"); + } + + File[] files = aSrc.listFiles(); + + for (int i = 0; i < files.length; i++) { + File file = files[i]; + + if (file.isDirectory()) { + if (!file.getName().equals(".svn")) { + copyDir(new File(aSrc, file.getName()), new File(aTarget, + file.getName())); + } + } else { + copyFile(file, new File(aTarget, file.getName())); + } + } + } + + /** + * Copy a file. If copying fails then the testcase will fail. + * + * @param aSrc + * Source file. + * @param aTarget + * Target file. + */ + public static void copyFile(File aSrc, File aTarget) { + try { + FileInputStream fis = new FileInputStream(aSrc); + FileOutputStream fos = new FileOutputStream(aTarget); + FileChannel fcin = fis.getChannel(); + FileChannel fcout = fos.getChannel(); + + // map input file + MappedByteBuffer mbb = fcin.map(FileChannel.MapMode.READ_ONLY, 0, + fcin.size()); + + // do the file copy + fcout.write(mbb); + + // finish up + fcin.close(); + fcout.close(); + fis.close(); + fos.close(); + } catch (IOException e) { + Assert.assertTrue("Copying file " + aSrc.getPath() + " to " + + aTarget.getPath() + " failed.", false); + } + } + + /** + * Remove all files within a given directory including the directory itself. + * This only attempts to remove regular files and not directories within the + * directory. If the directory contains a nested directory, the deletion + * will fail. The test case will fail if this fails. + * + * @param aDir + * Directory to remove. + */ + public static void deleteDir(File aDir) { + cleanDir(aDir); + delete(aDir); + } + + /** + * Remove all regular files within a given directory. + * + * @param outputDirName + */ + public static void cleanDir(File aDir) { + if (!aDir.exists()) { + return; // nothing to do. + } + + File[] entries = aDir.listFiles(); + + for (int i = 0; i < entries.length; i++) { + File file = entries[i]; + + if (file.isFile()) { + Assert.assertTrue("Could not delete " + entries[i].getPath(), + entries[i].delete()); + } + } + } } diff --git a/support/general/src/test/java/org/wamblee/io/StreamResourceTest.java b/support/general/src/test/java/org/wamblee/io/StreamResourceTest.java index 1cf9478f..9bea518a 100644 --- a/support/general/src/test/java/org/wamblee/io/StreamResourceTest.java +++ b/support/general/src/test/java/org/wamblee/io/StreamResourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,38 +13,34 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.io; +import junit.framework.TestCase; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; - -import junit.framework.TestCase; - /** - * Tests the stream resource. - * + * Tests the stream resource. + * * @author Erik Brakkee */ public class StreamResourceTest extends TestCase { - /** * Loads an existing resource. Verifies it is found. * */ public void testResourceFound() throws IOException { - File file = new File( - FileSystemUtils.getTestInputDir(StreamResourceTest.class), - "myresource.txt"); - assertTrue(file.canRead()); + File file = new File(FileSystemUtils + .getTestInputDir(StreamResourceTest.class), "myresource.txt"); + assertTrue(file.canRead()); + InputStream fileIs = new FileInputStream(file); InputResource resource = new StreamResource(fileIs); InputStream is = resource.getInputStream(); String data = FileSystemUtils.read(is); assertEquals("This is my resource", data); } - } diff --git a/support/general/src/test/java/org/wamblee/io/TestData.java b/support/general/src/test/java/org/wamblee/io/TestData.java index 58bea68e..f7e4b3dc 100644 --- a/support/general/src/test/java/org/wamblee/io/TestData.java +++ b/support/general/src/test/java/org/wamblee/io/TestData.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,14 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.io; import java.io.ByteArrayInputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.OutputStream; -import java.nio.MappedByteBuffer; -import java.nio.channels.FileChannel; import junit.framework.Assert; @@ -33,159 +29,155 @@ import junit.framework.Assert; * @author Erik Brakkee */ public final class TestData { - - private Object _testcase; - private File _root; - - /** - * Test data to be constructed in the setUp of a test. {@link #clean()} must - * be called to make sure that this directory is empty before executing a - * test. - */ - public TestData(Object aTestcase) { - _testcase = aTestcase; - _root = getTestRootDir(aTestcase); - FileSystemUtils.createDir(_root); - } - - /** - * Obtain root directory of JUnit tests. - * - * @return Directory name. - */ - private static File getTestRootDir(Object aTestcase) { - return FileSystemUtils.getTestOutputDir(aTestcase.getClass()); - } - - public void createFile(String aRelative, String aFile, InputStream aContents) { - FileSystemUtils - .createFile(new File(_root, aRelative), aFile, aContents); - } - - public void createFile(String aFile, String aContents) { - createFile(".", aFile, aContents); - } - - public void createFile(String aRelative, String aFile, String aContents) { - InputStream is = new ByteArrayInputStream(aContents.getBytes()); - FileSystemUtils.createFile(new File(_root, aRelative), aFile, is); - } - - public void deleteFile(String aFile) { - deleteFile(".", aFile); - } - - public void deleteFile(String aRelative, String aFile) { - FileSystemUtils.delete(new File(_root, aFile)); - } - - /** - * Returns a temporary directory. - * - * @return Temporary directory. - */ - public File getTmpDir() { - return new File(_root, "tmpdir"); - } - - /** - * Cleans up the test output directory. - */ - public void clean() { - FileSystemUtils.deleteDirRecursively(_root); - FileSystemUtils.createDir(_root); - } - - /** - * Recursively copy a directory contents to the test output directory. - * - * @param sSrc - * Source directory to copy. - */ - public void copyDir(File aSrc) { - FileSystemUtils.copyDir(aSrc, _root); - } - - /** - * Copies a classpath resource to a relative path in the test output - * directory. - * - * @param aResource - * Resource to copy. - * @param aRelativePath - * Relative path. - */ - public void copyResource(String aResource, String aRelativePath) { - try { - InputStream is = new ClassPathResource(aResource).getInputStream(); - FileOutputStream fos = new FileOutputStream(new File(_root, - aRelativePath)); - FileSystemUtils.copyStream(is, fos); - } catch (IOException e) { - e.printStackTrace(); - Assert.fail(e.getMessage()); - } - } - - /** - * Copies a resource to the root directory of the test output. - * - * @param aResource - * Resource. - */ - public void copyResource(String aResource) { - String basename = new File(aResource).getName(); - copyResource(aResource, basename); - } - - public void createDir(String aRelative) { - FileSystemUtils.createDir(new File(_root, aRelative)); - } - - /** - * Deletes a file or directory relative to the test output root. - * - * @param aRelative - * Relative path. The testcase will fail if the file or directory - * cannot be removed. - */ - public void delete(String aRelative) { - FileSystemUtils.delete(new File(_root, aRelative)); - } - - /** - * Deletes a directory including its contents. - * - * @param aRelative - * Relative path. - */ - public void deleteDir(String aRelative) { - FileSystemUtils.deleteDir(new File(_root, aRelative)); - } - - /** - * Deletes a directory recursively. - * - * @param aRelative - * Relative path. - */ - public void deleteDirRecursively(String aRelative) { - FileSystemUtils.deleteDir(new File(_root, aRelative)); - } - - /** - * Gets the root of the test output directory. - * - * @return Root of the test output. - */ - public File getRoot() { - return _root; - } - - /** - * Gets a file object for a relative path. - */ - public File getFile(String aRelative) { - return new File(_root, aRelative); - } + private File root; + + /** + * Test data to be constructed in the setUp of a test. {@link #clean()} must + * be called to make sure that this directory is empty before executing a + * test. + */ + public TestData(Object aTestcase) { + root = getTestRootDir(aTestcase); + FileSystemUtils.createDir(root); + } + + /** + * Obtain root directory of JUnit tests. + * + * @return Directory name. + */ + private static File getTestRootDir(Object aTestcase) { + return FileSystemUtils.getTestOutputDir(aTestcase.getClass()); + } + + public void createFile(String aRelative, String aFile, InputStream aContents) { + FileSystemUtils.createFile(new File(root, aRelative), aFile, aContents); + } + + public void createFile(String aFile, String aContents) { + createFile(".", aFile, aContents); + } + + public void createFile(String aRelative, String aFile, String aContents) { + InputStream is = new ByteArrayInputStream(aContents.getBytes()); + FileSystemUtils.createFile(new File(root, aRelative), aFile, is); + } + + public void deleteFile(String aFile) { + deleteFile(".", aFile); + } + + public void deleteFile(String aRelative, String aFile) { + FileSystemUtils.delete(new File(root, aFile)); + } + + /** + * Returns a temporary directory. + * + * @return Temporary directory. + */ + public File getTmpDir() { + return new File(root, "tmpdir"); + } + + /** + * Cleans up the test output directory. + */ + public void clean() { + FileSystemUtils.deleteDirRecursively(root); + FileSystemUtils.createDir(root); + } + + /** + * Recursively copy a directory contents to the test output directory. + * + * @param sSrc + * Source directory to copy. + */ + public void copyDir(File aSrc) { + FileSystemUtils.copyDir(aSrc, root); + } + + /** + * Copies a classpath resource to a relative path in the test output + * directory. + * + * @param aResource + * Resource to copy. + * @param aRelativePath + * Relative path. + */ + public void copyResource(String aResource, String aRelativePath) { + try { + InputStream is = new ClassPathResource(aResource).getInputStream(); + FileOutputStream fos = new FileOutputStream(new File(root, + aRelativePath)); + FileSystemUtils.copyStream(is, fos); + } catch (IOException e) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + + /** + * Copies a resource to the root directory of the test output. + * + * @param aResource + * Resource. + */ + public void copyResource(String aResource) { + String basename = new File(aResource).getName(); + copyResource(aResource, basename); + } + + public void createDir(String aRelative) { + FileSystemUtils.createDir(new File(root, aRelative)); + } + + /** + * Deletes a file or directory relative to the test output root. + * + * @param aRelative + * Relative path. The testcase will fail if the file or directory + * cannot be removed. + */ + public void delete(String aRelative) { + FileSystemUtils.delete(new File(root, aRelative)); + } + + /** + * Deletes a directory including its contents. + * + * @param aRelative + * Relative path. + */ + public void deleteDir(String aRelative) { + FileSystemUtils.deleteDir(new File(root, aRelative)); + } + + /** + * Deletes a directory recursively. + * + * @param aRelative + * Relative path. + */ + public void deleteDirRecursively(String aRelative) { + FileSystemUtils.deleteDir(new File(root, aRelative)); + } + + /** + * Gets the root of the test output directory. + * + * @return Root of the test output. + */ + public File getRoot() { + return root; + } + + /** + * Gets a file object for a relative path. + */ + public File getFile(String aRelative) { + return new File(root, aRelative); + } } diff --git a/support/general/src/test/java/org/wamblee/io/TestResource.java b/support/general/src/test/java/org/wamblee/io/TestResource.java index ec28290f..fd9d5cf0 100644 --- a/support/general/src/test/java/org/wamblee/io/TestResource.java +++ b/support/general/src/test/java/org/wamblee/io/TestResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,35 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.io; import java.io.File; - /** * Test resource for locating resources in the classpath. */ public class TestResource extends FileResource { - /** - * Test class name. - * @param aTestClass Test class. - * @param aName Name of the file to look for. + * Test class name. + * + * @param aTestClass + * Test class. + * @param aName + * Name of the file to look for. */ public TestResource(Class aTestClass, String aName) { - super(getFile(aTestClass, aName)); + super(getFile(aTestClass, aName)); } - + /** - * Computes the file path of the file to look for. - * @param aClass Test class name. - * @param aName Name of the file. - * @return File. + * Computes the file path of the file to look for. + * + * @param aClass + * Test class name. + * @param aName + * Name of the file. + * @return File. */ - private static File getFile(Class aClass, String aName) { + private static File getFile(Class aClass, String aName) { File dir = FileSystemUtils.getTestInputDir(aClass); + return new File(dir, aName); } - } diff --git a/support/general/src/test/java/org/wamblee/observer/ObservableTest.java b/support/general/src/test/java/org/wamblee/observer/ObservableTest.java index 8a060e89..f2fc8d7d 100644 --- a/support/general/src/test/java/org/wamblee/observer/ObservableTest.java +++ b/support/general/src/test/java/org/wamblee/observer/ObservableTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,16 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.observer; -import static org.mockito.Mockito.*; - -import java.util.ArrayList; -import java.util.List; +import junit.framework.TestCase; import org.mockito.InOrder; +import static org.mockito.Mockito.*; -import junit.framework.TestCase; +import java.util.ArrayList; +import java.util.List; /** * Test of the observer pattern implementation. @@ -31,113 +29,116 @@ import junit.framework.TestCase; * @author Erik Brakkee */ public class ObservableTest extends TestCase { + private static final int SUBSCRIBER_COUNT = 100; + private static final String UPDATE = "send"; + private Integer observed; + private Observable observable; + + /* + * (non-Javadoc) + * + * @see junit.framework.TestCase#setUp() + */ + @Override + protected void setUp() throws Exception { + super.setUp(); + observed = Integer.valueOf(1); + observable = new Observable(observed, + new DefaultObserverNotifier()); + } + + /** + * Tests subscription and notification of one subscriber. + */ + public void testOneObserver() { + final Observer mockObserver = mock(Observer.class); + InOrder order = inOrder(mockObserver); + + long subscription = observable.subscribe(mockObserver); + + assertEquals(1, observable.getObserverCount()); + + final String message = "hallo"; + observable.send(message); + + order.verify(mockObserver).send(observed, message); + verifyNoMoreInteractions(mockObserver); + + observable.unsubscribe(subscription); + assertEquals(0, observable.getObserverCount()); + + observable.send(message); + verifyNoMoreInteractions(mockObserver); + } + + /** + * Subscribes many susbcribers and sends notifications to subscribers. + * Verifies that unique subscription number are returned. Also verifies that + * the correct subscribers are notfied. + */ + public void testManySubscribers() { + final int nsubscribers = SUBSCRIBER_COUNT; + final Observer[] mocks = new Observer[nsubscribers]; + final InOrder[] order = new InOrder[nsubscribers]; + + List subscriptions = new ArrayList(); + + for (int i = 0; i < nsubscribers; i++) { + mocks[i] = mock(Observer.class); + order[i] = inOrder(mocks[i]); + + long subscription = observable.subscribe(mocks[i]); + assertTrue(subscriptions.add(subscription)); + } + + assertEquals(nsubscribers, observable.getObserverCount()); + + final String message = "hallo"; + + observable.send(message); + + for (int i = 0; i < nsubscribers; i++) { + order[i].verify(mocks[i]).send(observed, message); + } + + for (int i = nsubscribers / 2; i < nsubscribers; i++) { + observable.unsubscribe(subscriptions.get(i)); + } + + assertEquals(nsubscribers - (nsubscribers - (nsubscribers / 2)), + observable.getObserverCount()); + + final String message2 = "blabla"; + + observable.send(message2); + + for (int i = 0; i < (nsubscribers / 2); i++) { + order[i].verify(mocks[i]).send(observed, message2); + } + + for (int i = nsubscribers / 2; i < nsubscribers; i++) { + verifyNoMoreInteractions(mocks[i]); + } + } + + /** + * Subscribes and then unsubscribes with a wrong id. Verifies that + * IllegalArgumentException is thrown. + * + */ + public void testUnsubscribeWithWrongSubscription() { + Observer observer = mock(Observer.class); + + long subscription = observable.subscribe(observer); + + assertEquals(1, observable.getObserverCount()); + + try { + observable.unsubscribe(subscription + 1); + } catch (IllegalArgumentException e) { + return; // ok + } - private static final int SUBSCRIBER_COUNT = 100; - - private static final String UPDATE = "send"; - - private Integer _observed; - private Observable _observable; - - /* - * (non-Javadoc) - * - * @see junit.framework.TestCase#setUp() - */ - @Override - protected void setUp() throws Exception { - super.setUp(); - _observed = new Integer(1); - _observable = new Observable(_observed, - new DefaultObserverNotifier()); - } - - /** - * Tests subscription and notification of one subscriber. - */ - public void testOneObserver() { - final Observer mockObserver = mock(Observer.class); - InOrder order = inOrder(mockObserver); - - long subscription = _observable.subscribe(mockObserver); - - assertEquals(1, _observable.getObserverCount()); - - final String message = "hallo"; - _observable.send(message); - - order.verify(mockObserver).send(_observed, message); - verifyNoMoreInteractions(mockObserver); - - _observable.unsubscribe(subscription); - assertEquals(0, _observable.getObserverCount()); - - _observable.send(message); - verifyNoMoreInteractions(mockObserver); - } - - /** - * Subscribes many susbcribers and sends notifications to subscribers. - * Verifies that unique subscription number are returned. Also verifies that - * the correct subscribers are notfied. - */ - public void testManySubscribers() { - final int nsubscribers = SUBSCRIBER_COUNT; - final Observer[] mocks = new Observer[nsubscribers]; - final InOrder[] order = new InOrder[nsubscribers]; - - List subscriptions = new ArrayList(); - for (int i = 0; i < nsubscribers; i++) { - mocks[i] = mock(Observer.class); - order[i] = inOrder(mocks[i]); - long subscription = _observable.subscribe(mocks[i]); - assertTrue(subscriptions.add(subscription)); - } - - assertEquals(nsubscribers, _observable.getObserverCount()); - - final String message = "hallo"; - - _observable.send(message); - for (int i = 0; i < nsubscribers; i++) { - order[i].verify(mocks[i]).send(_observed, message); - } - - for (int i = nsubscribers / 2; i < nsubscribers; i++) { - _observable.unsubscribe(subscriptions.get(i)); - } - assertEquals(nsubscribers - (nsubscribers - nsubscribers / 2), - _observable.getObserverCount()); - - final String message2 = "blabla"; - - _observable.send(message2); - for (int i = 0; i < nsubscribers / 2; i++) { - order[i].verify(mocks[i]).send(_observed, message2); - } - for (int i = nsubscribers/2; i < nsubscribers; i++) { - verifyNoMoreInteractions(mocks[i]); - } - - } - - /** - * Subscribes and then unsubscribes with a wrong id. Verifies that - * IllegalArgumentException is thrown. - * - */ - public void testUnsubscribeWithWrongSubscription() { - Observer observer = mock(Observer.class); - - long subscription = _observable.subscribe(observer); - - assertEquals(1, _observable.getObserverCount()); - - try { - _observable.unsubscribe(subscription + 1); - } catch (IllegalArgumentException e) { - return; // ok - } - fail(); - } + fail(); + } } diff --git a/support/general/src/test/java/org/wamblee/persistence/JpaMergeSupportTest.java b/support/general/src/test/java/org/wamblee/persistence/JpaMergeSupportTest.java new file mode 100644 index 00000000..c906fb19 --- /dev/null +++ b/support/general/src/test/java/org/wamblee/persistence/JpaMergeSupportTest.java @@ -0,0 +1,403 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.persistence; + +import static junit.framework.Assert.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.persistence.Id; +import javax.persistence.Version; + +import org.junit.Test; + +public class JpaMergeSupportTest { + + private static class X1 { + @Id + int id; + + @Version + int version; + + private String value; + + public X1() { + value = ""; + } + + public X1(String aValue) { + value = aValue; + } + + public String getValue() { + return value; + } + + @Override + public boolean equals(Object aObj) { + if (aObj == null) { + return false; + } + if (!(aObj instanceof X1)) { + return false; + } + return value.equals(((X1) aObj).getValue()); + } + } + + private static class X2 { + @Id + int id; + + private List list; + + public X2() { + list = new ArrayList(); + } + + public List getList() { + return list; + } + } + + private static class X3 { + @Id + int id; + + private Set set; + + public X3() { + set = new HashSet(); + } + + public Set getSet() { + return set; + } + } + + private static class X4 { + @Id + int id; + + private Map map; + + public X4() { + map = new HashMap(); + } + + public Map getMap() { + return map; + } + } + + private static class X5 { + @Id + int id; + + private X1[] array; + + public X5() { + // Empty. + } + + public void setArray(X1[] aArray) { + array = aArray; + } + + public X1[] getArray() { + return array; + } + } + + private static class X6 { + @Id + int id; + + public X1 getNotaGetter(String aMessage) { + return null; + } + + public void getNotaGetter2() { + + } + } + + private static class X7 { + @Id + int id; + + private void getX() { + fail("Private getters should not be used"); + } + } + + @Test + public void testSimple() { + X1 x = new X1(); + x.id = 10; + x.version = 20; + + X1 y = new X1(); + + JpaMergeSupport.merge(x, y); + + assertEquals(x.id, y.id); + assertEquals(x.version, y.version); + } + + @Test(expected = IllegalArgumentException.class) + public void testSimplePkMismatch() { + X1 x = new X1(); + x.id = 10; + x.version = 20; + + X1 y = new X1(); + y.id = 5; + JpaMergeSupport.merge(x, y); + } + + @Test + public void testTraverseList() { + X2 x = new X2(); + x.id = 10; + X1 a = new X1(); + a.id = 20; + a.version = 21; + X1 b = new X1(); + b.id = 30; + b.version = 31; + + x.getList().add(a); + x.getList().add(b); + + X2 y = new X2(); + y.getList().add(new X1()); + y.getList().add(new X1()); + + JpaMergeSupport.merge(x, y); + + assertEquals(x.id, y.id); + assertEquals(x.getList().get(0).id, y.getList().get(0).id); + assertEquals(x.getList().get(1).id, y.getList().get(1).id); + assertEquals(x.getList().get(0).version, y.getList().get(0).version); + assertEquals(x.getList().get(1).version, y.getList().get(1).version); + } + + @Test(expected = IllegalArgumentException.class) + public void testTraverseListWrongSize() { + X2 x = new X2(); + x.id = 10; + X1 a = new X1(); + a.id = 20; + a.version = 21; + X1 b = new X1(); + b.id = 30; + b.version = 31; + + x.getList().add(a); + x.getList().add(b); + + X2 y = new X2(); + y.getList().add(new X1()); + + JpaMergeSupport.merge(x, y); + } + + @Test + public void testTraverseSet() { + X3 x = new X3(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.getSet().add(a); + x.getSet().add(b); + + X3 y = new X3(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.getSet().add(ya); + y.getSet().add(yb); + JpaMergeSupport.merge(x, y); + assertEquals(x.id, y.id); + assertEquals(a.id, ya.id); + assertEquals(a.version, ya.version); + assertEquals(b.version, yb.version); + } + + @Test(expected = IllegalArgumentException.class) + public void testTraverseSetWrongSize() { + X3 x = new X3(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.getSet().add(a); + x.getSet().add(b); + + X3 y = new X3(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.getSet().add(ya); + JpaMergeSupport.merge(x, y); + } + + @Test + public void testTraverseMap() { + X4 x = new X4(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.getMap().put("a", a); + x.getMap().put("b", b); + + X4 y = new X4(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.getMap().put("a", ya); + y.getMap().put("b", yb); + JpaMergeSupport.merge(x, y); + assertEquals(x.id, y.id); + assertEquals(a.id, ya.id); + assertEquals(a.version, ya.version); + assertEquals(b.version, yb.version); + + } + + @Test(expected = IllegalArgumentException.class) + public void testTraverseMapWrongKey() { + X4 x = new X4(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.getMap().put("a", a); + x.getMap().put("b", b); + + X4 y = new X4(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.getMap().put("a", ya); + y.getMap().put("c", yb); + JpaMergeSupport.merge(x, y); + } + + @Test(expected = IllegalArgumentException.class) + public void testTraverseMapWrongSize() { + X4 x = new X4(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.getMap().put("a", a); + x.getMap().put("b", b); + + X4 y = new X4(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.getMap().put("a", ya); + JpaMergeSupport.merge(x, y); + } + + @Test + public void testTraverseArray() { + X5 x = new X5(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.setArray(new X1[] { a, b }); + + X5 y = new X5(); + X1 ya = new X1("a"); + X1 yb = new X1("b"); + + y.setArray(new X1[] { ya, yb }); + JpaMergeSupport.merge(x, y); + assertEquals(x.id, y.id); + assertEquals(a.id, ya.id); + assertEquals(a.version, ya.version); + assertEquals(b.version, yb.version); + } + + @Test(expected = IllegalArgumentException.class) + public void testTraverseArrayWrongSize() { + X5 x = new X5(); + x.id = 10; + X1 a = new X1("a"); + a.id = 20; + a.version = 21; + X1 b = new X1("b"); + b.id = 30; + b.version = 21; + x.setArray(new X1[] { a, b }); + + X5 y = new X5(); + X1 ya = new X1("a"); + + y.setArray(new X1[] { ya }); + JpaMergeSupport.merge(x, y); + } + + @Test + public void testNotAGetter() { + X6 x = new X6(); + x.id = 100; + X6 y = new X6(); + + JpaMergeSupport.merge(x,y); + assertEquals(x.id, y.id); + } + + @Test + public void testPrivateGetter() { + X7 x = new X7(); + x.id = 100; + X7 y = new X7(); + JpaMergeSupport.merge(x,y); + assertEquals(x.id, y.id); + } +} diff --git a/support/general/src/test/java/org/wamblee/persistence/PersistentFactoryTest.java b/support/general/src/test/java/org/wamblee/persistence/PersistentFactoryTest.java new file mode 100644 index 00000000..16979de7 --- /dev/null +++ b/support/general/src/test/java/org/wamblee/persistence/PersistentFactoryTest.java @@ -0,0 +1,282 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.persistence; + +import static junit.framework.Assert.*; + +import javax.persistence.Id; +import javax.persistence.Version; + +import org.junit.Test; +import org.wamblee.persistence.PersistentFactory.Accessor; +import org.wamblee.persistence.PersistentFactory.EntityAccessor; +import org.wamblee.persistence.PersistentFactory.EntityObjectAccessor; +import org.wamblee.persistence.PersistentFactory.FieldAccessor; +import org.wamblee.persistence.PersistentFactory.PropertyAccessor; + +public class PersistentFactoryTest { + + public static class X1 { + @Id + private int pk; + + public int getPk() { + return pk; + } + + public void setPk(int aPk) { + pk = aPk; + } + + private void privateSetter(int aPk) { + pk = aPk; + } + + private int privateGetter() { + return pk; + } + } + + public static class X2 { + private int pk; + + @Id + public int getPk() { + return pk; + } + + public void setPk(int aPk) { + pk = aPk; + } + } + + public static class X3 { + private int pk; + + @Id + private int getPk() { + return pk; + } + + private void setPk(int aPk) { + pk = aPk; + } + } + + public static class X4 { + @Version + private int version; + + public int getVersion() { + return version; + } + + public void setVersion(int aVersion) { + version = aVersion; + } + + private void privateSetter(int aVersion) { + version = aVersion; + } + + private int privateGetter() { + return version; + } + } + + public static class X5 { + private int version; + + @Version + public int getVersion() { + return version; + } + + public void setVersion(int aVersion) { + version = aVersion; + } + } + + public static class X6 { + private int version; + + @Version + private int getVersion() { + return version; + } + + private void setVersion(int aVersion) { + version = aVersion; + } + } + + public static class X7 { + @Id + public int id; + + @Version + public int version; + } + + // FieldAccessor test + + @Test + public void testFieldAccessorSet() throws Exception { + Accessor accessor = new FieldAccessor(X1.class + .getDeclaredField("pk")); + X1 x1 = new X1(); + assertEquals(0, x1.getPk()); + accessor.set(x1, 10); + assertEquals(10, x1.getPk()); + } + + // PropertyAccessor test + @Test + public void testPropertyAccessorSet() throws Exception { + Accessor accessor = new PropertyAccessor(X1.class + .getDeclaredMethod("getPk"), X1.class.getDeclaredMethod("setPk", + int.class)); + X1 x1 = new X1(); + assertEquals(0, x1.getPk()); + accessor.set(x1, 10); + assertEquals(10, x1.getPk()); + } + + @Test + public void testPropertyAccessorPrivate() throws Exception { + Accessor accessor = new PropertyAccessor(X1.class + .getDeclaredMethod("privateGetter"), X1.class.getDeclaredMethod("privateSetter", + int.class)); + X1 x1 = new X1(); + assertEquals(0, x1.getPk()); + accessor.set(x1, 10); + assertEquals((Integer)10, accessor.get(x1)); + + } + + // EntityAccessor test + + @Test + public void testEntityAccessorPkField() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X1.class); + assertNotNull(accessor); + assertTrue(accessor.getPk() instanceof FieldAccessor); + assertNull(accessor.getVersion()); + assertEquals("pk", ((FieldAccessor) accessor.getPk()).getField() + .getName()); + } + + @Test + public void testEntityAccessorPkProperty() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X2.class); + assertNotNull(accessor); + assertNotNull(accessor.getPk()); + assertTrue(accessor.getPk() instanceof PropertyAccessor); + assertNull(accessor.getVersion()); + PropertyAccessor property = (PropertyAccessor) accessor.getPk(); + assertEquals("getPk", property.getGetter().getName()); + assertEquals("setPk", property.getSetter().getName()); + } + + @Test + public void testEntityAccessorPkPropertyPrivate() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X3.class); + assertNotNull(accessor); + assertNotNull(accessor.getPk()); + assertTrue(accessor.getPk() instanceof PropertyAccessor); + assertNull(accessor.getVersion()); + PropertyAccessor property = (PropertyAccessor) accessor.getPk(); + assertEquals("getPk", property.getGetter().getName()); + assertEquals("setPk", property.getSetter().getName()); + } + + @Test + public void testEntityAccessorVersionField() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X4.class); + assertNotNull(accessor); + assertTrue(accessor.getVersion() instanceof FieldAccessor); + assertNull(accessor.getPk()); + assertEquals("version", ((FieldAccessor) accessor.getVersion()).getField() + .getName()); + } + + @Test + public void testEntityAccessorVersionProperty() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X5.class); + assertNotNull(accessor); + assertNotNull(accessor.getVersion()); + assertTrue(accessor.getVersion() instanceof PropertyAccessor); + assertNull(accessor.getPk()); + PropertyAccessor property = (PropertyAccessor) accessor.getVersion(); + assertEquals("getVersion", property.getGetter().getName()); + assertEquals("setVersion", property.getSetter().getName()); + } + + @Test + public void testEntityAccessorVersionPropertyPrivate() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X6.class); + assertNotNull(accessor); + assertNotNull(accessor.getVersion()); + assertTrue(accessor.getVersion() instanceof PropertyAccessor); + assertNull(accessor.getPk()); + PropertyAccessor property = (PropertyAccessor) accessor.getVersion(); + assertEquals("getVersion", property.getGetter().getName()); + assertEquals("setVersion", property.getSetter().getName()); + } + + @Test + public void testNoVersionAndNoPk() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(String.class); + assertNull(accessor); + } + + @Test + public void testPkAndVersion() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X7.class); + assertNotNull(accessor.getPk()); + assertNotNull(accessor.getVersion()); + + X7 x = new X7(); + assertEquals(0, x.id); + assertEquals(0, x.version); + + accessor.getPk().set(x, 10); + accessor.getVersion().set(x, 20); + + assertEquals(10, x.id); + assertEquals(20, x.version); + } + + @Test + public void testEntityAccessorCache() { + EntityAccessor accessor = PersistentFactory.createEntityAccessor(X1.class); + EntityAccessor accessor2 = PersistentFactory.createEntityAccessor(X1.class); + + assertSame(accessor, accessor2); + } + + // EntityObjectAccessor test for undefined pk and/or version. + @Test + public void testEntityObjectAccessorRobustness() { + EntityObjectAccessor accessor = new EntityObjectAccessor("hello world", + new EntityAccessor(null, null)); + assertNull(accessor.getPrimaryKey()); + assertNull(accessor.getPersistedVersion()); + accessor.setPrimaryKey("bla"); + accessor.setPersistedVersion(100); + + } +} diff --git a/support/general/src/test/java/org/wamblee/reflection/ReflectionUtilsTest.java b/support/general/src/test/java/org/wamblee/reflection/ReflectionUtilsTest.java new file mode 100644 index 00000000..1cc6e4b0 --- /dev/null +++ b/support/general/src/test/java/org/wamblee/reflection/ReflectionUtilsTest.java @@ -0,0 +1,90 @@ +package org.wamblee.reflection; + +import static junit.framework.Assert.*; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.List; + +import org.junit.Test; + +public class ReflectionUtilsTest { + + public static interface X { + void x(); + } + + public static class X2 { + private int bla; + + public void x() { + + } + + private void y() { + + } + } + + public static class X3 extends X2 { + public void z() { + + } + } + + public static class X4 extends X2 { + public void x() { + + } + } + + public static class X5 extends X2 { + private String field; + private int g; + } + + @Test(expected = IllegalArgumentException.class) + public void testGetAllMethodsInterface() { + ReflectionUtils.getAllMethods(X.class); + } + + @Test + public void testBasicClass() { + List res = ReflectionUtils.getAllMethods(X2.class, Object.class); + assertEquals(2, res.size()); + } + + @Test + public void testInheritanceAdditionalMethod() { + List res = ReflectionUtils.getAllMethods(X3.class, Object.class); + assertEquals(3, res.size()); + } + + @Test + public void testInheritanceOverriddenMethod() { + List res = ReflectionUtils.getAllMethods(X4.class, Object.class); + assertEquals(2, res.size()); + for (Method method : res) { + if (method.getName().equals("x")) { + assertEquals(X4.class, method.getDeclaringClass()); + } + } + } + + @Test(expected = IllegalArgumentException.class) + public void testGetAllFieldsInterface() { + ReflectionUtils.getAllFields(X.class); + } + + @Test + public void testFieldsFromBasicClass() { + List fields = ReflectionUtils.getAllFields(X2.class); + assertEquals(1, fields.size()); + assertEquals("bla", fields.get(0).getName()); + } + + public void testFieldsWithInheritance() { + List fields = ReflectionUtils.getAllFields(X5.class); + assertEquals(3, fields.size()); + } +} diff --git a/support/general/src/test/java/org/wamblee/test/AssertionUtils.java b/support/general/src/test/java/org/wamblee/test/AssertionUtils.java index a0216a8b..8c25fc13 100644 --- a/support/general/src/test/java/org/wamblee/test/AssertionUtils.java +++ b/support/general/src/test/java/org/wamblee/test/AssertionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,13 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.test; import java.util.Arrays; -import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import junit.framework.TestCase; @@ -27,12 +27,11 @@ import org.apache.commons.logging.LogFactory; /** * Useful assertions for use in test cases. - * + * * @author Erik Brakkee */ public final class AssertionUtils { - - private static final Log LOG = LogFactory.getLog(AssertionUtils.class); + private static final Log LOG = LogFactory.getLog(AssertionUtils.class); /** * Disabled constructor. @@ -41,7 +40,7 @@ public final class AssertionUtils { private AssertionUtils() { // Empty } - + /** * Asserts that two object arrays are equal. * @@ -53,7 +52,6 @@ public final class AssertionUtils { public static void assertEquals(T[] aExpected, T[] aActual) { assertEquals("", aExpected, aActual); } - /** * Asserts that two object arrays are equal. @@ -65,24 +63,21 @@ public final class AssertionUtils { * @param aActual * Actual array. */ - public static void assertEquals(String aMsg, T[] aExpected, - T[] aActual) { - TestCase.assertEquals(aMsg + " expected " + - Arrays.asList(aExpected) + ", actual " + - Arrays.asList(aActual) + ": Array lengths ", aExpected.length, - aActual.length); + public static void assertEquals(String aMsg, T[] aExpected, T[] aActual) { + TestCase.assertEquals(aMsg + " expected " + Arrays.asList(aExpected) + + ", actual " + Arrays.asList(aActual) + ": Array lengths ", + aExpected.length, aActual.length); for (int i = 0; i < aExpected.length; i++) { TestCase.assertEquals(aMsg + ": Element " + i, aExpected[i], - aActual[i]); + aActual[i]); } } - - /** +/** * Asserts that two objects are equal, and in case the object is an Object[] * delegates to {@link #assertEquals(String, Object[], Object[]). - * + * * @param aMsg * Message. * @param aExpected @@ -90,11 +85,10 @@ public final class AssertionUtils { * @param aActual * Actual result. */ - public static void assertEquals(String aMsg, T aExpected, - T aActual) { + public static void assertEquals(String aMsg, T aExpected, T aActual) { if (aExpected instanceof Object[]) { AssertionUtils.assertEquals(aMsg, (Object[]) aExpected, - (Object[]) aActual); + (Object[]) aActual); return; } @@ -113,44 +107,47 @@ public final class AssertionUtils { * @param aActual * Actual result. */ - public static void assertEquals(String aMsg, - Map aExpectedMap, Map aActual) { + public static void assertEquals(String aMsg, + Map aExpectedMap, Map aActual) { TestCase.assertEquals("Map sizes differ", aExpectedMap.size(), aActual - .size()); + .size()); - Set keys = aExpectedMap.keySet(); + Set> expectedEntries = aExpectedMap.entrySet(); - for (Iterator i = keys.iterator(); i.hasNext();) { - String key = (String) i.next(); + for (Entry entry: expectedEntries) { + Key key = entry.getKey(); TestCase.assertTrue("Map does not containg entry for key:" + key, - aActual.containsKey(key)); + aActual.containsKey(key)); AssertionUtils.assertEquals("Value of key " + key + " of map", - aExpectedMap.get(key), aActual.get(key)); + entry.getValue(), aActual.get(key)); } } - - public static interface ErroneousCode { - void run() throws Exception; - } - - /** + + /** * Asserts that an exception occurs. - * @param aRunnable Test cases should create a subclass of this which contains the - * code that should throw an exception. - * @param aType Type of exception that is expected. + * + * @param aRunnable + * Test cases should create a subclass of this which contains the + * code that should throw an exception. + * @param aType + * Type of exception that is expected. */ - public static void assertException(ErroneousCode aObject, Class aType) { - try { - aObject.run(); - throw new RuntimeException("No exception occurred"); - } catch (Throwable t) { - if ( aType.isInstance(t)) { - LOG.info("Expected exception occured " + t.getMessage()); - return; // ok - } - else { - throw new RuntimeException(t); - } - } + public static void assertException(ErroneousCode aObject, Class aType) { + try { + aObject.run(); + throw new RuntimeException("No exception occurred"); + } catch (Throwable t) { + if (aType.isInstance(t)) { + LOG.info("Expected exception occured " + t.getMessage()); + + return; // ok + } else { + throw new RuntimeException(t); + } + } + } + + public static interface ErroneousCode { + void run() throws Exception; } } diff --git a/support/general/src/test/java/org/wamblee/test/EventTracker.java b/support/general/src/test/java/org/wamblee/test/EventTracker.java index 333da1e7..e66d0147 100644 --- a/support/general/src/test/java/org/wamblee/test/EventTracker.java +++ b/support/general/src/test/java/org/wamblee/test/EventTracker.java @@ -1,5 +1,5 @@ /* - * Copyright 2006 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,18 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.test; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * Tracks the occurence of certain events in a test environment. Threads in a * test environment tell the event tracker of the occurrence of certain events @@ -37,17 +37,16 @@ import org.apache.commons.logging.LogFactory; * Type of event sent from test code. Usually String will be * sufficient. The event type must provide a sensible implementation * of {@link java.lang.Object#equals(java.lang.Object)}. - * + * * @author Erik Brakkee */ public class EventTracker { - private static final Log LOG = LogFactory.getLog(EventTracker.class); /** * Map of Thread object to a list of events. */ - private Map> _events; + private Map> events; /** * Constructs the event tracker. @@ -57,9 +56,9 @@ public class EventTracker { clear(); } - public void clear() { - _events = new HashMap>(); - } + public synchronized void clear() { + events = new HashMap>(); + } /** * Called by a thread to inform that an event has occurred. @@ -69,13 +68,16 @@ public class EventTracker { */ public synchronized void eventOccurred(Event aEvent) { LOG.info("Event '" + aEvent + "' sent."); + Thread current = Thread.currentThread(); - List events = _events.get(current); - if (events == null) { - events = new ArrayList(); - _events.put(current, events); + List eventList = events.get(current); + + if (eventList == null) { + eventList = new ArrayList(); + events.put(current, eventList); } - events.add(aEvent); + + eventList.add(aEvent); } /** @@ -88,11 +90,13 @@ public class EventTracker { * @return Whether or not the event was sent. */ public synchronized boolean isEventSent(Thread aThread, Event aEvent) { - List events = _events.get(aThread); - if (events == null) { + List eventList = events.get(aThread); + + if (eventList == null) { return false; } - return events.contains(aEvent); + + return eventList.contains(aEvent); } /** @@ -104,16 +108,17 @@ public class EventTracker { * events were sent. */ public synchronized List getEvents(Thread aThread) { - List events = _events.get(aThread); - if (events == null) { - events = Collections.emptyList(); + List eventList = events.get(aThread); + + if (eventList == null) { + eventList = Collections.emptyList(); } - return Collections.unmodifiableList(events); + + return Collections.unmodifiableList(eventList); } /** - * Gets the number of times an event was sent summed up - * over all threads. + * Gets the number of times an event was sent summed up over all threads. * * @param aEvent * Event to check. @@ -121,26 +126,32 @@ public class EventTracker { */ public synchronized int getEventCount(Event aEvent) { int count = 0; - for (Thread thread : _events.keySet()) { - List events = _events.get(thread); - for (Event event : events) { + + for (Thread thread : events.keySet()) { + List eventList = events.get(thread); + + for (Event event : eventList) { if (event.equals(aEvent)) { count++; } } } + return count; } - + /** - * Gets the total event count over all threads. + * Gets the total event count over all threads. + * * @return */ - public synchronized int getEventCount() { - int count = 0; - for (Thread thread: _events.keySet()) { - count += _events.get(thread).size(); - } - return count; + public synchronized int getEventCount() { + int count = 0; + + for (Thread thread : events.keySet()) { + count += events.get(thread).size(); + } + + return count; } } diff --git a/support/general/src/test/java/org/wamblee/test/TimingUtils.java b/support/general/src/test/java/org/wamblee/test/TimingUtils.java index 82d3c0e8..343d564d 100644 --- a/support/general/src/test/java/org/wamblee/test/TimingUtils.java +++ b/support/general/src/test/java/org/wamblee/test/TimingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,37 +12,36 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.test; import junit.framework.TestCase; /** * Timing utilities. - * + * * @author Erik Brakkee */ public final class TimingUtils { - /** * Disabled constructor. - * + * */ private TimingUtils() { // Empty } - + /** - * Sleeps for a time. - * @param aMillis Number of milliseconds to sleep. + * Sleeps for a time. + * + * @param aMillis + * Number of milliseconds to sleep. */ - public static void sleep(int aMillis) { - try { + public static void sleep(int aMillis) { + try { Thread.sleep(aMillis); - } catch (InterruptedException e) { + } catch (InterruptedException e) { TestCase.fail("Who interrupted my sleep?"); } } - } diff --git a/support/general/src/test/java/org/wamblee/xml/ClasspathUriResolverTest.java b/support/general/src/test/java/org/wamblee/xml/ClasspathUriResolverTest.java index 39280c60..97e71758 100644 --- a/support/general/src/test/java/org/wamblee/xml/ClasspathUriResolverTest.java +++ b/support/general/src/test/java/org/wamblee/xml/ClasspathUriResolverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.xml; +import junit.framework.TestCase; + +import org.wamblee.io.ClassPathResource; +import org.wamblee.io.FileSystemUtils; + import java.io.IOException; import javax.xml.transform.Source; @@ -23,54 +27,58 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.URIResolver; import javax.xml.transform.stream.StreamSource; -import junit.framework.TestCase; - - -import org.wamblee.io.ClassPathResource; -import org.wamblee.io.FileSystemUtils; - /** * Tests for {@link org.wamblee.xml.ClasspathUriResolver}. - * + * * @author Erik Brakkee */ public class ClasspathUriResolverTest extends TestCase { - - private URIResolver _resolver; - - /* (non-Javadoc) + private URIResolver resolver; + + /* + * (non-Javadoc) + * * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { - _resolver = new ClasspathUriResolver(); + resolver = new ClasspathUriResolver(); } /** - * Resolves an existing file. Verifies the file is resolved correctly. - * @throws TransformerException + * Resolves an existing file. Verifies the file is resolved correctly. + * + * @throws TransformerException * @throws IOException */ - public void testResolveExistingFile() throws TransformerException, IOException { - Source source = _resolver.resolve("org/wamblee/xml/reportToHtml.xsl", ""); + public void testResolveExistingFile() throws TransformerException, + IOException { + Source source = resolver + .resolve("org/wamblee/xml/reportToHtml.xsl", ""); assertTrue(source instanceof StreamSource); - String resolved = FileSystemUtils.read(((StreamSource)source).getInputStream()); - - ClassPathResource resource = new ClassPathResource("org/wamblee/xml/reportToHtml.xsl"); + + String resolved = FileSystemUtils.read(((StreamSource) source) + .getInputStream()); + + ClassPathResource resource = new ClassPathResource( + "org/wamblee/xml/reportToHtml.xsl"); String expected = FileSystemUtils.read(resource.getInputStream()); assertEquals(expected, resolved); } - + /** - * Resolves a non-existing file. Verifies that a TransformerException is thrown. - * + * Resolves a non-existing file. Verifies that a TransformerException is + * thrown. + * */ public void testResolveNonExistingFile() { - try { - Source source = _resolver.resolve("org/wamblee/xml/reportToHtml-nonexisting.xsl", ""); - } catch (TransformerException e) { + try { + resolver.resolve( + "org/wamblee/xml/reportToHtml-nonexisting.xsl", ""); + } catch (TransformerException e) { return; // ok } + fail(); } } diff --git a/support/general/src/test/java/org/wamblee/xml/XmlUtils.java b/support/general/src/test/java/org/wamblee/xml/XmlUtils.java index fc894251..5f9755e4 100644 --- a/support/general/src/test/java/org/wamblee/xml/XmlUtils.java +++ b/support/general/src/test/java/org/wamblee/xml/XmlUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.xml; +import java.io.Serializable; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -30,11 +30,10 @@ import org.dom4j.Element; /** * XML test support utilities. - * + * * @author Erik Brakkee */ public final class XmlUtils { - /** * Disabled constructor. * @@ -46,60 +45,62 @@ public final class XmlUtils { /** * Checks equality of two XML documents excluding comment and processing * nodes and trimming the text of the elements. In case of problems, it - * provides an xpath-like expression describing where the problem is. + * provides an xpath-like expression describing where the problem is. * * @param aMsg * @param aExpected * @param aActual */ public static void assertEquals(String aMsg, - org.w3c.dom.Document aExpected, org.w3c.dom.Document aActual) { + org.w3c.dom.Document aExpected, org.w3c.dom.Document aActual) { assertEquals(aMsg, DomUtils.convert(aExpected), DomUtils - .convert(aActual)); + .convert(aActual)); } /** * Checks equality of two XML documents excluding comment and processing - * nodes and trimming the text of the elements. In case of problems, it - * provides an xpath-like expression describing where the problem is. + * nodes and trimming the text of the elements. In case of problems, it + * provides an xpath-like expression describing where the problem is. * * @param aMsg * @param aExpected * @param aActual */ public static void assertEquals(String aMsg, Document aExpected, - Document aActual) { - assertEquals(aMsg + "/" + aExpected.getRootElement().getName(), aExpected.getRootElement(), aActual.getRootElement()); + Document aActual) { + assertEquals(aMsg + "/" + aExpected.getRootElement().getName(), + aExpected.getRootElement(), aActual.getRootElement()); } /** * Checks equality of two XML elements excluding comment and processing * nodes and trimming the text of the elements. In case of problems, it - * provides an xpath-like expression describing where the problem is. + * provides an xpath-like expression describing where the problem is. * * @param aMsg * @param aExpected * @param aActual */ public static void assertEquals(String aMsg, Element aExpected, - Element aActual) { - + Element aActual) { // Name. TestCase.assertEquals(aMsg + "/name()", aExpected.getName(), aActual - .getName()); + .getName()); // Text TestCase.assertEquals(aMsg + "/text()", aExpected.getTextTrim(), - aActual.getTextTrim()); + aActual.getTextTrim()); // Attributes List expectedAttrs = aExpected.attributes(); Collections.sort(expectedAttrs, new AttributeComparator()); + List actualAttrs = aActual.attributes(); Collections.sort(actualAttrs, new AttributeComparator()); TestCase.assertEquals("count(" + aMsg + "/@*)", expectedAttrs.size(), - actualAttrs.size()); + actualAttrs.size()); + for (int i = 0; i < expectedAttrs.size(); i++) { String msg = aMsg + "/@" + expectedAttrs.get(i).getName(); assertEquals(msg, expectedAttrs.get(i), actualAttrs.get(i)); @@ -109,47 +110,55 @@ public final class XmlUtils { List expectedElems = aExpected.elements(); List actualElems = aActual.elements(); TestCase.assertEquals("count(" + aMsg + "/*)", expectedElems.size(), - actualElems.size()); + actualElems.size()); + // determine the how-manyth element of the given name we are at. // Maps element name to the last used index (or null if not yet used) Map elementIndex = new TreeMap(); + for (int i = 0; i < expectedElems.size(); i++) { String elemName = expectedElems.get(i).getName(); Integer index = elementIndex.get(elemName); + if (index == null) { index = 1; } else { index++; } + elementIndex.put(elemName, index); - String msg = aMsg + "/" + expectedElems.get(i).getName() + "[" - + index + "]"; + + String msg = aMsg + "/" + expectedElems.get(i).getName() + "[" + + index + "]"; assertEquals(msg, expectedElems.get(i), actualElems.get(i)); } } /** - * Checks equality of two attributes. In case of problems, it - * provides an xpath-like expression describing where the problem is. + * Checks equality of two attributes. In case of problems, it provides an + * xpath-like expression describing where the problem is. * * @param aMsg * @param aExpected * @param aActual */ public static void assertEquals(String aMsg, Attribute aExpected, - Attribute aActual) { + Attribute aActual) { TestCase.assertEquals(aMsg + ":name", aExpected.getName(), aActual - .getName()); + .getName()); TestCase.assertEquals(aMsg + ":value", aExpected.getValue(), aActual - .getValue()); + .getValue()); } /** * Comparator which compares attributes by name. */ private static final class AttributeComparator implements - Comparator { + Comparator, Serializable { + + private static final long serialVersionUID = 7897287273519886301L; + /* * (non-Javadoc) * diff --git a/support/general/src/test/java/org/wamblee/xml/XslTransformerTest.java b/support/general/src/test/java/org/wamblee/xml/XslTransformerTest.java index d30e60a6..bf46528d 100644 --- a/support/general/src/test/java/org/wamblee/xml/XslTransformerTest.java +++ b/support/general/src/test/java/org/wamblee/xml/XslTransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,12 +12,10 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.xml; import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import javax.xml.parsers.DocumentBuilder; @@ -29,35 +27,29 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import junit.framework.TestCase; + +import org.w3c.dom.Document; import org.wamblee.io.ClassPathResource; import org.wamblee.io.FileSystemUtils; import org.wamblee.io.InputResource; -import org.w3c.dom.Document; - /** * Tests the XSL transformer. - * + * * @author Erik Brakkee */ public class XslTransformerTest extends TestCase { - private static final String INCLUDED_XSL_FILE = "utilities.xsl"; - - private static final String REPORT_XML = "report.xml"; - + private static final String REPORT_XML = "report.xml"; private static final String REPORT_TO_HTML_XSLT = "reportToHtml.xsl"; - private static final String REPORT_TO_HTML2_XSLT = "reportToHtml2.xsl"; - private static final String REPORT_TO_HTML_INVALID_XSLT = "reportToHtml-invalid.xsl"; - private static final String REPORT_TO_HTML_NONWELLFORMED_XSLT = "reportToHtml-nonwellformed.xsl"; - private static final String REPORT_TO_TEXT_XSLT = "reportToText.xsl"; - private String getResourcePath(String aResource) { - return getClass().getPackage().getName().replaceAll("\\.", "/") + "/" + aResource; + private String getResourcePath(String aResource) { + return getClass().getPackage().getName().replaceAll("\\.", "/") + "/" + + aResource; } /** @@ -68,43 +60,48 @@ public class XslTransformerTest extends TestCase { public void testTransformUsingDefaultResolver() throws Exception { XslTransformer transformer = new XslTransformer(); - InputResource xmlResource = new ClassPathResource(getResourcePath(REPORT_XML)); - - Source xslt = new StreamSource(new ClassPathResource(getResourcePath( - REPORT_TO_HTML_XSLT)).getInputStream()); + InputResource xmlResource = new ClassPathResource( + getResourcePath(REPORT_XML)); + + Source xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_XSLT)).getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); + .read(xmlResource.getInputStream()).getBytes(); DocumentBuilder builder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); + .newDocumentBuilder(); Document document = builder.parse(xmlResource.getInputStream()); Source documentSource = new StreamSource(xmlResource.getInputStream()); - Document expected = DomUtils.read(new ClassPathResource(getResourcePath( - "output-reportToHtml-report.xml")).getInputStream()); + Document expected = DomUtils + .read(new ClassPathResource( + getResourcePath("output-reportToHtml-report.xml")) + .getInputStream()); Document output1 = transformer.transform(documentData, xslt); XmlUtils.assertEquals("byte[] transform", expected, output1); - xslt = new StreamSource(new ClassPathResource(getResourcePath( - REPORT_TO_HTML_XSLT)).getInputStream()); + xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_XSLT)).getInputStream()); + Document output2 = transformer.transform(document, xslt); XmlUtils.assertEquals("document transform", expected, output2); ByteArrayOutputStream os = new ByteArrayOutputStream(); Result output = new StreamResult(os); - - xslt = new StreamSource(new ClassPathResource(getResourcePath( - REPORT_TO_HTML_XSLT)).getInputStream()); + + xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_XSLT)).getInputStream()); transformer.transform(documentSource, output, xslt); XmlUtils.assertEquals("document source transform", expected, DomUtils - .read(os.toString())); + .read(os.toString())); + + xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_XSLT)).getInputStream()); - xslt = new StreamSource(new ClassPathResource(getResourcePath( - REPORT_TO_HTML_XSLT)).getInputStream()); String result = transformer.textTransform(documentData, xslt); XmlUtils - .assertEquals("text transform", expected, DomUtils.read(result)); + .assertEquals("text transform", expected, DomUtils.read(result)); } /** @@ -115,19 +112,20 @@ public class XslTransformerTest extends TestCase { public void testTransformUsingDefaultResolverFails() throws IOException { XslTransformer transformer = new XslTransformer(); - InputResource xmlResource = - new ClassPathResource(getResourcePath(REPORT_XML)); - Source xslt = new StreamSource( - new ClassPathResource(getResourcePath( - REPORT_TO_HTML2_XSLT)).getInputStream()); + InputResource xmlResource = new ClassPathResource( + getResourcePath(REPORT_XML)); + Source xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML2_XSLT)).getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); + .read(xmlResource.getInputStream()).getBytes(); + try { - Document output1 = transformer.transform(documentData, xslt); + transformer.transform(documentData, xslt); } catch (TransformerException e) { return; // ok } + fail(); } @@ -140,17 +138,19 @@ public class XslTransformerTest extends TestCase { XslTransformer transformer = new XslTransformer(); InputResource xmlResource = new ClassPathResource( - getResourcePath(REPORT_XML)); - Source xslt = new StreamSource( - new ClassPathResource(getResourcePath(REPORT_TO_HTML_INVALID_XSLT)).getInputStream()); + getResourcePath(REPORT_XML)); + Source xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_INVALID_XSLT)).getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); + .read(xmlResource.getInputStream()).getBytes(); + try { - Document output1 = transformer.transform(documentData, xslt); + transformer.transform(documentData, xslt); } catch (TransformerException e) { return; // ok } + fail(); } @@ -163,18 +163,20 @@ public class XslTransformerTest extends TestCase { XslTransformer transformer = new XslTransformer(); InputResource xmlResource = new ClassPathResource( - getResourcePath(REPORT_XML)); - Source xslt = new StreamSource( - new ClassPathResource(getResourcePath( - REPORT_TO_HTML_NONWELLFORMED_XSLT)).getInputStream()); + getResourcePath(REPORT_XML)); + Source xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_HTML_NONWELLFORMED_XSLT)) + .getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); + .read(xmlResource.getInputStream()).getBytes(); + try { - Document output1 = transformer.transform(documentData, xslt); + transformer.transform(documentData, xslt); } catch (TransformerException e) { return; // ok } + fail(); } @@ -183,19 +185,21 @@ public class XslTransformerTest extends TestCase { * */ public void testTransformUsingClassPathResolver() throws Exception { - XslTransformer transformer = new XslTransformer(new ClasspathUriResolver()); + XslTransformer transformer = new XslTransformer( + new ClasspathUriResolver()); - InputResource xmlResource = new ClassPathResource(getResourcePath( - REPORT_XML)); + InputResource xmlResource = new ClassPathResource( + getResourcePath(REPORT_XML)); Source xslt = new StreamSource(new ClassPathResource( - getResourcePath(REPORT_TO_HTML2_XSLT)).getInputStream()); + getResourcePath(REPORT_TO_HTML2_XSLT)).getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); - + .read(xmlResource.getInputStream()).getBytes(); + Document output1 = transformer.transform(documentData, xslt); - Document expected = DomUtils.read(new ClassPathResource( - getResourcePath("output-reportToHtml-report.xml")) + Document expected = DomUtils + .read(new ClassPathResource( + getResourcePath("output-reportToHtml-report.xml")) .getInputStream()); XmlUtils.assertEquals("doc", expected, output1); } @@ -206,52 +210,55 @@ public class XslTransformerTest extends TestCase { * */ public void testTransformToTextOutput() throws Exception { - XslTransformer transformer = new XslTransformer(new ClasspathUriResolver()); + XslTransformer transformer = new XslTransformer( + new ClasspathUriResolver()); InputResource xmlResource = new ClassPathResource( - getResourcePath(REPORT_XML)); - Source xslt = new StreamSource( - new ClassPathResource(getResourcePath(REPORT_TO_TEXT_XSLT)).getInputStream()); + getResourcePath(REPORT_XML)); + Source xslt = new StreamSource(new ClassPathResource( + getResourcePath(REPORT_TO_TEXT_XSLT)).getInputStream()); byte[] documentData = FileSystemUtils - .read(xmlResource.getInputStream()).getBytes(); - + .read(xmlResource.getInputStream()).getBytes(); + String result = transformer.textTransform(documentData, xslt); String expected = "Hello world!"; assertEquals("text transform", expected, result); } - + /** - * Tests resolving a file using {@link XslTransformer#resolve(String)} with the - * default resolver where the file does not exist. - * + * Tests resolving a file using {@link XslTransformer#resolve(String)} with + * the default resolver where the file does not exist. + * */ - public void testResolveWithDefaultResolverFileNotFound() { + public void testResolveWithDefaultResolverFileNotFound() { XslTransformer transformer = new XslTransformer(); - try { - Source source = transformer.resolve("org/wamblee/xml/utilities-nonexistent.xsl"); - } catch (TransformerException e) { + + try { + transformer + .resolve("org/wamblee/xml/utilities-nonexistent.xsl"); + } catch (TransformerException e) { return; // ok } + fail(); } - - + /** - * Tests resolving a file using {@link XslTransformer#resolve(String)} with the - * default resolver. - * + * Tests resolving a file using {@link XslTransformer#resolve(String)} with + * the default resolver. + * */ - public void testResolveWithClasspathResolver() throws Exception { - XslTransformer transformer = new XslTransformer(new ClasspathUriResolver()); + public void testResolveWithClasspathResolver() throws Exception { + XslTransformer transformer = new XslTransformer( + new ClasspathUriResolver()); Source source = transformer.resolve(getResourcePath(INCLUDED_XSL_FILE)); - assert(source instanceof StreamSource); - StreamSource ssource = (StreamSource)source; + assert (source instanceof StreamSource); + + StreamSource ssource = (StreamSource) source; String data = FileSystemUtils.read(ssource.getInputStream()); - String expected = FileSystemUtils.read(new ClassPathResource(getResourcePath(INCLUDED_XSL_FILE)).getInputStream()); + String expected = FileSystemUtils.read(new ClassPathResource( + getResourcePath(INCLUDED_XSL_FILE)).getInputStream()); assertEquals(expected, data); } - } - - diff --git a/support/spring/pom.xml b/support/spring/pom.xml index 8dab6cf2..05126cc7 100644 --- a/support/spring/pom.xml +++ b/support/spring/pom.xml @@ -38,11 +38,6 @@ hibernate - - - org.wamblee - wamblee-hibernate-jpa - 0.2.2 org.springframework diff --git a/support/spring/src/main/java/org/wamblee/concurrency/spring/LockAdvice.java b/support/spring/src/main/java/org/wamblee/concurrency/spring/LockAdvice.java index 61bd98ae..3ec8e8f7 100644 --- a/support/spring/src/main/java/org/wamblee/concurrency/spring/LockAdvice.java +++ b/support/spring/src/main/java/org/wamblee/concurrency/spring/LockAdvice.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,43 +13,48 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.concurrency.spring; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.wamblee.concurrency.Lock; /** - * Locking advice. This automatically synchronized an object using a given lock. - * + * Locking advice. This automatically synchronized an object using a given lock. + * * @author Erik Brakkee */ public class LockAdvice implements MethodInterceptor { - /** - * Lock to use. + * Lock to use. */ - private Lock _lock; - + private Lock lock; + /** - * Constructs lock advice. - * @param aLock Lock to use. + * Constructs lock advice. + * + * @param aLock + * Lock to use. */ - public LockAdvice(Lock aLock) { - _lock = aLock; + public LockAdvice(Lock aLock) { + lock = aLock; } - - /* (non-Javadoc) - * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) + + /* + * (non-Javadoc) + * + * @see + * org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept + * .MethodInvocation) */ public Object invoke(MethodInvocation aInvocation) throws Throwable { - _lock.acquire(); - try { - return aInvocation.proceed(); - } finally { - _lock.release(); + lock.acquire(); + + try { + return aInvocation.proceed(); + } finally { + lock.release(); } } - } diff --git a/support/spring/src/main/java/org/wamblee/general/spring/SpringBeanFactory.java b/support/spring/src/main/java/org/wamblee/general/spring/SpringBeanFactory.java index e01f0865..4ffb43ed 100644 --- a/support/spring/src/main/java/org/wamblee/general/spring/SpringBeanFactory.java +++ b/support/spring/src/main/java/org/wamblee/general/spring/SpringBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.general.spring; import org.springframework.beans.BeansException; @@ -21,7 +21,6 @@ import org.springframework.beans.factory.access.BeanFactoryReference; import org.springframework.context.access.ContextSingletonBeanFactoryLocator; import org.wamblee.general.BeanFactory; import org.wamblee.general.BeanFactoryException; -import org.wamblee.general.BeanKernel; /** * Bean factory which uses Spring. This bean factory cannot be configured @@ -30,8 +29,7 @@ import org.wamblee.general.BeanKernel; * it must tbe subclassed to provide a default constructor. */ public class SpringBeanFactory implements BeanFactory { - - private BeanFactoryReference _factoryReference; + private BeanFactoryReference factoryReference; /** * Constructs the bean factory. @@ -44,12 +42,12 @@ public class SpringBeanFactory implements BeanFactory { public SpringBeanFactory(String aSelector, String aFactoryName) { try { BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator - .getInstance(aSelector); - _factoryReference = locator.useBeanFactory(aFactoryName); + .getInstance(aSelector); + factoryReference = locator.useBeanFactory(aFactoryName); } catch (BeansException e) { throw new BeanFactoryException( - "Could not load bean factory: selector = '" + aSelector - + "', factory = '" + aFactoryName + "'", e); + "Could not load bean factory: selector = '" + aSelector + + "', factory = '" + aFactoryName + "'", e); } } @@ -75,24 +73,25 @@ public class SpringBeanFactory implements BeanFactory { * (non-Javadoc) * * @see org.wamblee.general.BeanFactory#find(java.lang.String, - * java.lang.Class) + * java.lang.Class) */ public T find(String aId, Class aClass) { try { - Object obj = _factoryReference.getFactory().getBean(aId, aClass); + Object obj = factoryReference.getFactory().getBean(aId, aClass); assert obj != null; + return aClass.cast(obj); } catch (BeansException e) { throw new BeanFactoryException(e.getMessage(), e); } } - + /** - * Gets the spring bean factory. - * @return Spring bean factory. + * Gets the spring bean factory. + * + * @return Spring bean factory. */ - public org.springframework.beans.factory.BeanFactory getSpringBeanFactory() { - return _factoryReference.getFactory(); + public org.springframework.beans.factory.BeanFactory getSpringBeanFactory() { + return factoryReference.getFactory(); } - } diff --git a/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateMappingFiles.java b/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateMappingFiles.java index 003395d3..d3ceb99c 100644 --- a/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateMappingFiles.java +++ b/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateMappingFiles.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,34 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.persistence.hibernate; import java.util.ArrayList; import java.util.Arrays; /** - * Hibernate mapping files to use. - * + * Hibernate mapping files to use. + * * @author Erik Brakkee */ public class HibernateMappingFiles extends ArrayList { - /** - * Constructs an empty list of hibernate mapping files. - * + * Constructs an empty list of hibernate mapping files. + * */ - public HibernateMappingFiles() { - super(); + public HibernateMappingFiles() { + super(); } - + /** - * Constructs the list of Spring config files. - * @param aFiles Files. + * Constructs the list of Spring config files. + * + * @param aFiles + * Files. */ - public HibernateMappingFiles(String[] aFiles) { - super(); + public HibernateMappingFiles(String[] aFiles) { + super(); addAll(Arrays.asList(aFiles)); } - } diff --git a/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateSupport.java b/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateSupport.java index 8425facd..52dbc352 100644 --- a/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateSupport.java +++ b/support/spring/src/main/java/org/wamblee/persistence/hibernate/HibernateSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.persistence.hibernate; import java.lang.reflect.InvocationTargetException; @@ -22,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Map.Entry; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -32,37 +32,12 @@ import org.wamblee.persistence.Persistent; /** * Extension of * {@link org.springframework.orm.hibernate.support.HibernateDaoSupport}. - * + * * @author Erik Brakkee */ public class HibernateSupport extends HibernateDaoSupport { - private static final Log LOG = LogFactory.getLog(HibernateSupport.class); - /** - * This class provided an equality operation based on the object reference - * of the wrapped object. This is required because we cannto assume that the - * equals operation has any meaning for different types of persistent - * objects. This allows us to use the standard collection classes for - * detecting cyclic dependences and avoiding recursion. - * - */ - private static final class ObjectElem { - private Object _object; - - public ObjectElem(Object aObject) { - _object = aObject; - } - - public boolean equals(Object aObj) { - return ((ObjectElem) aObj)._object == _object; - } - - public int hashCode() { - return _object.hashCode(); - } - } - /** * Constructs the object. * @@ -72,14 +47,13 @@ public class HibernateSupport extends HibernateDaoSupport { } /** - * Performes a hibernate Session.merge() and updates the - * object with the correct primary key and version. This is an extension to - * the hibernate merge operation because hibernate itself leaves the object - * passed to merge untouched. - * - * Use this method with extreme caution since it will recursively load all - * objects that the current object has relations with and for which - * cascade="merge" was specified in the Hibernate mapping file. + * Performes a hibernate Session.merge() and updates the object + * with the correct primary key and version. This is an extension to the + * hibernate merge operation because hibernate itself leaves the object + * passed to merge untouched. Use this method with extreme caution since it + * will recursively load all objects that the current object has relations + * with and for which cascade="merge" was specified in the Hibernate mapping + * file. * * @param aPersistent * Object to merge. @@ -116,34 +90,40 @@ public class HibernateSupport extends HibernateDaoSupport { * @param aProcessed * List of already processed Persistent objects of the persistent * part. + * */ public static void processPersistent(Persistent aPersistent, - Persistent aMerged, List aProcessed) { - if (aPersistent == null && aMerged == null) { + Persistent aMerged, List aProcessed) { + if ((aPersistent == null) && (aMerged == null)) { return; } - if (aPersistent == null || aMerged == null) { - throw new RuntimeException("persistent or merged object is null '" - + aPersistent + "'" + " '" + aMerged + "'"); + + if ((aPersistent == null) || (aMerged == null)) { + throw new RuntimeException("persistent or merged object is null '" + + aPersistent + "'" + " '" + aMerged + "'"); } + ObjectElem elem = new ObjectElem(aPersistent); + if (aProcessed.contains(elem)) { return; // already processed. } + aProcessed.add(elem); LOG.debug("Setting pk/version on " + aPersistent + " from " + aMerged); - if (aPersistent.getPrimaryKey() != null - && !aMerged.getPrimaryKey().equals(aPersistent.getPrimaryKey())) { - LOG.error("Mismatch between primary key values: " + aPersistent - + " " + aMerged); + if ((aPersistent.getPrimaryKey() != null) && + !aMerged.getPrimaryKey().equals(aPersistent.getPrimaryKey())) { + LOG.error("Mismatch between primary key values: " + aPersistent + + " " + aMerged); } else { aPersistent.setPersistedVersion(aMerged.getPersistedVersion()); aPersistent.setPrimaryKey(aMerged.getPrimaryKey()); } Method[] methods = aPersistent.getClass().getMethods(); + for (Method getter : methods) { if (getter.getName().startsWith("get")) { Class returnType = getter.getReturnType(); @@ -164,18 +144,19 @@ public class HibernateSupport extends HibernateDaoSupport { } else if (Persistent.class.isAssignableFrom(returnType)) { Persistent merged = (Persistent) getter.invoke(aMerged); Persistent persistent = (Persistent) getter - .invoke(aPersistent); + .invoke(aPersistent); processPersistent(persistent, merged, aProcessed); - } else if (returnType.isArray() - && Persistent.class.isAssignableFrom(returnType - .getComponentType())) { + } else if (returnType.isArray() && + Persistent.class.isAssignableFrom(returnType + .getComponentType())) { Persistent[] merged = (Persistent[]) getter - .invoke(aMerged); + .invoke(aMerged); Persistent[] persistent = (Persistent[]) getter - .invoke(aPersistent); + .invoke(aPersistent); + for (int i = 0; i < persistent.length; i++) { processPersistent(persistent[i], merged[i], - aProcessed); + aProcessed); } } } catch (InvocationTargetException e) { @@ -185,7 +166,6 @@ public class HibernateSupport extends HibernateDaoSupport { } } } - } /** @@ -197,20 +177,24 @@ public class HibernateSupport extends HibernateDaoSupport { * Collection as a result of the merge. * @param aProcessed * List of processed persistent objects. + * */ public static void processList(List aPersistent, List aMerged, - List aProcessed) { + List aProcessed) { Object[] merged = aMerged.toArray(); Object[] persistent = aPersistent.toArray(); + if (merged.length != persistent.length) { - throw new RuntimeException("Array sizes differ " + merged.length - + " " + persistent.length); + throw new RuntimeException("Array sizes differ " + merged.length + + " " + persistent.length); } + for (int i = 0; i < merged.length; i++) { assert merged[i].equals(persistent[i]); + if (merged[i] instanceof Persistent) { processPersistent((Persistent) persistent[i], - (Persistent) merged[i], aProcessed); + (Persistent) merged[i], aProcessed); } } } @@ -224,19 +208,22 @@ public class HibernateSupport extends HibernateDaoSupport { * Collection as a result of the merge. * @param aProcessed * List of processed persistent objects. + * */ public static void processSet(Set aPersistent, Set aMerged, - List aProcessed) { + List aProcessed) { if (aMerged.size() != aPersistent.size()) { - throw new RuntimeException("Array sizes differ " + aMerged.size() - + " " + aPersistent.size()); + throw new RuntimeException("Array sizes differ " + aMerged.size() + + " " + aPersistent.size()); } + for (Object merged : aMerged) { // Find the object that equals the merged[i] for (Object persistent : aPersistent) { if (persistent.equals(merged)) { processPersistent((Persistent) persistent, - (Persistent) merged, aProcessed); + (Persistent) merged, aProcessed); + break; } } @@ -252,30 +239,64 @@ public class HibernateSupport extends HibernateDaoSupport { * Collection as a result of the merge. * @param aProcessed * List of processed persistent objects. + * */ - public static void processMap(Map aPersistent, Map aMerged, - List aProcessed) { + public static void processMap(Map aPersistent, Map aMerged, + List aProcessed) { if (aMerged.size() != aPersistent.size()) { - throw new RuntimeException("Sizes differ " + aMerged.size() + " " - + aPersistent.size()); + throw new RuntimeException("Sizes differ " + aMerged.size() + " " + + aPersistent.size()); } - Set keys = aMerged.keySet(); - for (Object key : keys) { + + Set> entries = aMerged.entrySet(); + + for (Entry entry : entries) { + Key key = entry.getKey(); if (!aPersistent.containsKey(key)) { throw new RuntimeException("Key '" + key + "' not found"); } - Object mergedValue = aMerged.get(key); + + Value mergedValue = entry.getValue(); Object persistentValue = aPersistent.get(key); + if (mergedValue instanceof Persistent) { if (persistentValue instanceof Persistent) { processPersistent((Persistent) persistentValue, - (Persistent) mergedValue, aProcessed); + (Persistent) mergedValue, aProcessed); } else { throw new RuntimeException( - "Value in original object is null, whereas merged object contains a value"); + "Value in original object is null, whereas merged object contains a value"); } } } } + /** + * This class provided an equality operation based on the object reference + * of the wrapped object. This is required because we cannto assume that the + * equals operation has any meaning for different types of persistent + * objects. This allows us to use the standard collection classes for + * detecting cyclic dependences and avoiding recursion. + */ + private static final class ObjectElem { + private Object object; + + public ObjectElem(Object aObject) { + object = aObject; + } + + public boolean equals(Object aObj) { + if (aObj == null) { + return false; + } + if (!(aObj instanceof ObjectElem)) { + return false; + } + return ((ObjectElem) aObj).object == object; + } + + public int hashCode() { + return object.hashCode(); + } + } } diff --git a/support/spring/src/test/java/org/wamblee/concurrency/spring/LockAdviceTest.java b/support/spring/src/test/java/org/wamblee/concurrency/spring/LockAdviceTest.java index b56beacd..e2fc216e 100644 --- a/support/spring/src/test/java/org/wamblee/concurrency/spring/LockAdviceTest.java +++ b/support/spring/src/test/java/org/wamblee/concurrency/spring/LockAdviceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,31 +12,23 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.concurrency.spring; import org.springframework.aop.framework.ProxyFactoryBean; + import org.wamblee.concurrency.AbstractLockTestCase; import org.wamblee.concurrency.JvmLock; import org.wamblee.concurrency.spring.LockAdvice; + import org.wamblee.test.TimingUtils; /** * - * * @author Erik Brakkee */ public class LockAdviceTest extends AbstractLockTestCase { - - private class Runner implements Runnable { - public void run() { - LockAdviceTest.this.getTracker().eventOccurred(ACQUIRED); - TimingUtils.sleep(SLEEP_TIME); - } - } - - private Runnable _target; + private Runnable target; /* * (non-Javadoc) @@ -46,16 +38,15 @@ public class LockAdviceTest extends AbstractLockTestCase { @Override protected void setUp() throws Exception { super.setUp(); - + Runner runner = new Runner(); LockAdvice advice = new LockAdvice(new JvmLock()); - + ProxyFactoryBean support = new ProxyFactoryBean(); - support.setInterfaces(new Class[]{ Runnable.class }); + support.setInterfaces(new Class[] { Runnable.class }); support.setTarget(runner); support.addAdvice(advice); - _target = (Runnable)support.getObject(); - + target = (Runnable) support.getObject(); } /* @@ -69,7 +60,7 @@ public class LockAdviceTest extends AbstractLockTestCase { public void run() { try { getTracker().eventOccurred(STARTED); - _target.run(); + target.run(); getTracker().eventOccurred(RELEASED); } catch (Throwable e) { throw new RuntimeException(e); @@ -77,7 +68,14 @@ public class LockAdviceTest extends AbstractLockTestCase { }; }); t.start(); + return t; } + private class Runner implements Runnable { + public void run() { + LockAdviceTest.this.getTracker().eventOccurred(ACQUIRED); + TimingUtils.sleep(SLEEP_TIME); + } + } } diff --git a/support/spring/src/test/java/org/wamblee/general/spring/SpringBeanFactoryTest.java b/support/spring/src/test/java/org/wamblee/general/spring/SpringBeanFactoryTest.java index 21bf1957..e31309f7 100644 --- a/support/spring/src/test/java/org/wamblee/general/spring/SpringBeanFactoryTest.java +++ b/support/spring/src/test/java/org/wamblee/general/spring/SpringBeanFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,21 +12,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.general.spring; -import org.wamblee.general.BeanFactoryException; - import junit.framework.TestCase; +import org.wamblee.general.BeanFactoryException; + /** * Tests the spring bean factory. - * + * * @author Erik Brakkee */ public class SpringBeanFactoryTest extends TestCase { - /* * (non-Javadoc) * @@ -35,17 +33,18 @@ public class SpringBeanFactoryTest extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); - } public void testExistingBeanRefContext() { SpringBeanFactory factory = new SpringBeanFactory( - "org/wamblee/general/beanRefContext.xml", "test"); + "org/wamblee/general/beanRefContext.xml", "test"); String value1 = factory.find(String.class); assertEquals("hello", value1); + String value2 = (String) factory.find("java.lang.String"); assertEquals("hello", value2); + String value3 = factory.find("java.lang.String", String.class); assertEquals("hello", value3); @@ -54,16 +53,18 @@ public class SpringBeanFactoryTest extends TestCase { } catch (BeanFactoryException e) { return; // ok } + fail(); } public void testUnknownBeanFactory() { try { - new SpringBeanFactory( - "org/wamblee/general/beanRefContext.xml", "unknown"); + new SpringBeanFactory("org/wamblee/general/beanRefContext.xml", + "unknown"); } catch (BeanFactoryException e) { return; // ok } + fail(); } } diff --git a/support/spring/src/test/java/org/wamblee/general/spring/TestBeanFactory.java b/support/spring/src/test/java/org/wamblee/general/spring/TestBeanFactory.java index e5e566ce..cc4505ee 100644 --- a/support/spring/src/test/java/org/wamblee/general/spring/TestBeanFactory.java +++ b/support/spring/src/test/java/org/wamblee/general/spring/TestBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.general.spring; /** * Test bean factory. - * + * * @author Erik Brakkee */ public class TestBeanFactory extends SpringBeanFactory { - - - public TestBeanFactory() { + /** + * Creates a new TestBeanFactory object. + */ + public TestBeanFactory() { super("org/wamblee/general/beanRefContext.xml", "test"); } } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/HibernateExporter.java b/support/spring/src/test/java/org/wamblee/test/spring/HibernateExporter.java index aefe4185..a9dafe1d 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/HibernateExporter.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/HibernateExporter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,40 +13,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.wamblee.test.spring; -import java.io.File; -import java.io.IOException; - import org.hibernate.cfg.Configuration; + import org.hibernate.tool.hbm2ddl.SchemaExport; +import java.io.File; +import java.io.IOException; + /** - * Exporting the hibernate mapping. - * + * Exporting the hibernate mapping. + * * @author Erik Brakkee */ public final class HibernateExporter { - /** * Disabled constructor. - * + * */ - private HibernateExporter() { + private HibernateExporter() { // Empty } - + public static void main(String[] aArgs) throws IOException { String file = aArgs[0]; - File dir = new File(aArgs[1]); - + File dir = new File(aArgs[1]); + Configuration conf = HibernateUtils.getConfiguration(dir); - + SchemaExport export = new SchemaExport(conf); export.setDelimiter(";"); - export.setOutputFile(file); + export.setOutputFile(file); export.create(true, false); } - } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/HibernateUpdater.java b/support/spring/src/test/java/org/wamblee/test/spring/HibernateUpdater.java index 87219de0..f986cace 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/HibernateUpdater.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/HibernateUpdater.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,28 +12,27 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.test.spring; -import java.io.File; -import java.io.IOException; - import org.hibernate.cfg.Configuration; + import org.hibernate.tool.hbm2ddl.SchemaUpdate; +import java.io.File; +import java.io.IOException; + /** * Exporting the hibernate mapping. - * + * * @author Erik Brakkee */ public final class HibernateUpdater { - /** * Disabled constructor. - * + * */ - private HibernateUpdater() { + private HibernateUpdater() { // Empty } @@ -46,5 +45,4 @@ public final class HibernateUpdater { SchemaUpdate lSchemaUpdate = new SchemaUpdate(conf); lSchemaUpdate.execute(true, true); } - } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/HibernateUtils.java b/support/spring/src/test/java/org/wamblee/test/spring/HibernateUtils.java index 74a7ef7e..a370a404 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/HibernateUtils.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/HibernateUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,47 +12,52 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.test.spring; +import org.apache.oro.io.AwkFilenameFilter; + +import org.hibernate.cfg.Configuration; + +import org.wamblee.io.ClassPathResource; +import org.wamblee.io.InputResource; + import java.io.File; import java.io.FileFilter; import java.io.IOException; + import java.util.Map; import java.util.Properties; import java.util.TreeMap; -import org.apache.oro.io.AwkFilenameFilter; -import org.hibernate.cfg.Configuration; -import org.wamblee.io.ClassPathResource; -import org.wamblee.io.InputResource; - /** * Hibernate utilities. - * + * * @author Erik Brakkee */ public final class HibernateUtils { - private static final String DATABASE_PROPS = "test.database.properties"; /** * Disabled. - * + * */ - private HibernateUtils() { + private HibernateUtils() { // Empty } - + /** + * * @param aDir + * * @return + * */ public static Configuration getConfiguration(File aDir) throws IOException { Configuration conf = new Configuration(); File[] files = aDir.listFiles((FileFilter) (new AwkFilenameFilter( - ".*\\.hbm\\.xml"))); + ".*\\.hbm\\.xml"))); + for (File f : files) { System.out.println("Mapping file: " + f); conf.addFile(f); @@ -61,8 +66,8 @@ public final class HibernateUtils { Map dbProps = getHibernateProperties(); for (Map.Entry entry : dbProps.entrySet()) { - System.out.println("Property: " + entry.getKey() + "=" - + entry.getValue()); + System.out.println("Property: " + entry.getKey() + "=" + + entry.getValue()); conf.setProperty(entry.getKey(), entry.getValue()); } @@ -70,24 +75,23 @@ public final class HibernateUtils { } private static Map getHibernateProperties() - throws IOException { - + throws IOException { System.out.println("Reading properties file: " + DATABASE_PROPS); + InputResource lPropFile = new ClassPathResource(DATABASE_PROPS); Properties props = new Properties(); props.load(lPropFile.getInputStream()); Map result = new TreeMap(); result.put("hibernate.connection.driver_class", props - .getProperty("database.driver")); + .getProperty("database.driver")); result.put("hibernate.connection.url", props - .getProperty("database.url")); + .getProperty("database.url")); result.put("hibernate.connection.username", props - .getProperty("database.username")); + .getProperty("database.username")); result.put("hibernate.connection.password", props - .getProperty("database.password")); + .getProperty("database.password")); return result; } - } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/TestSpringBeanFactory.java b/support/spring/src/test/java/org/wamblee/test/spring/TestSpringBeanFactory.java index a7cc6fe6..2c2fc2a7 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/TestSpringBeanFactory.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/TestSpringBeanFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,48 +16,60 @@ package org.wamblee.test.spring; import org.springframework.beans.BeansException; + import org.springframework.context.ApplicationContext; + import org.wamblee.general.BeanFactory; import org.wamblee.general.BeanFactoryException; /** - * Bean factory which uses Spring. - * + * Bean factory which uses Spring. + * * @author Erik Brakkee */ public class TestSpringBeanFactory implements BeanFactory { - - private ApplicationContext _context; - + private ApplicationContext context; + + /** + * Creates a new TestSpringBeanFactory object. + * + */ public TestSpringBeanFactory(ApplicationContext aContext) { - _context = aContext; + context = aContext; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.general.BeanFactory#find(java.lang.String) */ public Object find(String aId) { - return find(aId, Object.class); + return find(aId, Object.class); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see org.wamblee.general.BeanFactory#find(java.lang.Class) */ public T find(Class aClass) { return find(aClass.getName(), aClass); } - /* (non-Javadoc) - * @see org.wamblee.general.BeanFactory#find(java.lang.String, java.lang.Class) + /* + * (non-Javadoc) + * + * @see org.wamblee.general.BeanFactory#find(java.lang.String, + * java.lang.Class) */ public T find(String aId, Class aClass) { try { - Object obj = _context.getBean(aId, aClass); - assert obj != null; - return aClass.cast(obj); - } catch (BeansException e) { + Object obj = context.getBean(aId, aClass); + assert obj != null; + + return aClass.cast(obj); + } catch (BeansException e) { throw new BeanFactoryException(e.getMessage(), e); } } - } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallback.java b/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallback.java index 37ea898b..f044ca38 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallback.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import java.util.Map; /** * Transaction callback for testing. The test will fail if any type of exception * is thrown. - * + * * @author Erik Brakkee */ public interface TestTransactionCallback { @@ -30,6 +30,7 @@ public interface TestTransactionCallback { * * @return A map containg the resuls of the execution. This is a convenient * method of returning multiple results from a call. + * */ Map execute() throws Exception; } diff --git a/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallbackWithoutResult.java b/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallbackWithoutResult.java index a5011e48..b3b2dd2b 100644 --- a/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallbackWithoutResult.java +++ b/support/spring/src/test/java/org/wamblee/test/spring/TestTransactionCallbackWithoutResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package org.wamblee.test.spring; /** * Transaction callback for testing. The test will fail if any type of exception * is thrown. - * + * * @author Erik Brakkee */ public interface TestTransactionCallbackWithoutResult { diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ClassAdapter.java b/system/general/src/main/java/org/wamblee/system/adapters/ClassAdapter.java index ace1525d..6bfa03f1 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ClassAdapter.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ClassAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import org.wamblee.system.core.AbstractComponent; @@ -22,35 +22,37 @@ import org.wamblee.system.core.Scope; /** * A Class Adapter adapts a given class to a Component. - * + * * @author Erik Brakkee */ public class ClassAdapter extends AbstractComponent { + private ClassConfiguration classConfig; + + /** + * Creates a new ClassAdapter object. + * + */ + public ClassAdapter(String aName, ClassConfiguration aClassConfig) { + super(aName, aClassConfig.getProvidedInterfaces().toArray( + new ProvidedInterface[0]), aClassConfig.getRequiredInterfaces() + .toArray(new RequiredInterface[0])); + classConfig = aClassConfig; + } + + @Override + protected Object doStart(Scope aScope) { + Object obj = classConfig.create(aScope); + classConfig.inject(aScope, obj); + + for (ProvidedInterface provided : getProvidedInterfaces()) { + addInterface(provided, obj, aScope); + } - private ClassConfiguration _classConfig; + return obj; + } - public ClassAdapter(String aName, ClassConfiguration aClassConfig) { - super(aName, - aClassConfig.getProvidedInterfaces().toArray(new ProvidedInterface[0]), - aClassConfig.getRequiredInterfaces().toArray(new RequiredInterface[0])); - _classConfig = aClassConfig; - } - - @Override - protected Object doStart(Scope aScope) { - - Object obj = _classConfig.create(aScope); - _classConfig.inject(aScope, obj); - - for (ProvidedInterface provided: getProvidedInterfaces()) { - addInterface(provided, obj, aScope); - } - - return obj; - } - - @Override - protected void doStop(Object aRuntime) { - // Empty. - } + @Override + protected void doStop(Object aRuntime) { + // Empty. + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ClassConfiguration.java b/system/general/src/main/java/org/wamblee/system/adapters/ClassConfiguration.java index 0fee7aca..31e09f92 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ClassConfiguration.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ClassConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,77 +12,87 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; +import java.util.ArrayList; +import java.util.List; + /** - * The class configuration encapsulates the knowledge of how to wrap a class as a component. + * The class configuration encapsulates the knowledge of how to wrap a class as + * a component. * * @author Erik Brakkee - * */ public class ClassConfiguration { + private Class clazz; + + private ConstructorConfiguration constructorConfig; + + private ObjectConfiguration objectConfig; + + /** + * Constructs the configuration. By default no constructor is selected and + * one of {@link #select(Class...)} or {@link #greedy()} must be called. + * + * @param aClass + * Class to construct. + */ + public ClassConfiguration(Class aClass) { + clazz = aClass; + constructorConfig = new ConstructorConfiguration(aClass); + objectConfig = new ObjectConfiguration(aClass); + } + + public ConstructorConfiguration getConstructorConfig() { + return constructorConfig; + } + + public ObjectConfiguration getObjectConfig() { + return objectConfig; + } + + /** + * Creates the object in the given scope. + * + * @param aScope + * Scope containing required interfaces for this object. + * + * @return object. + */ + public Object create(Scope aScope) { + return constructorConfig.create(aScope); + } + + /** + * Injects required interfaces through the setters + * + * @param aScope + * Scope in which injection takes place. + * @param aObject + * Object to inject into. + */ + public void inject(Scope aScope, Object aObject) { + objectConfig.inject(aScope, aObject); + } + + public List getProvidedInterfaces() { + List result = new ArrayList(); + result.add(new DefaultProvidedInterface("provided", clazz)); + + return result; + } - private Class _class; - private ConstructorConfiguration _constructorConfig; - private ObjectConfiguration _objectConfig; - - /** - * Constructs the configuration. By default no constructor is selected and - * one of {@link #select(Class...)} or - * {@link #greedy()} must be called. - * @param aClass Class to construct. - */ - public ClassConfiguration(Class aClass) { - _class = aClass; - _constructorConfig = new ConstructorConfiguration(aClass); - _objectConfig = new ObjectConfiguration(aClass); - } - - public ConstructorConfiguration getConstructorConfig() { - return _constructorConfig; - } - - public ObjectConfiguration getObjectConfig() { - return _objectConfig; - } + public List getRequiredInterfaces() { + List result = new ArrayList(); + result.addAll(constructorConfig.getRequiredInterfaces()); + result.addAll(objectConfig.getRequiredInterfaces()); - /** - * Creates the object in the given scope. - * @param aScope Scope containing required interfaces for this object. - * @return object. - */ - public Object create(Scope aScope) { - return _constructorConfig.create(aScope); - } - - /** - * Injects required interfaces through the setters - * @param aObject Object to inject into. - * @param aScope Scope in which injection takes place. - */ - public void inject(Scope aScope, Object aObject) { - _objectConfig.inject(aScope, aObject); - } - - public List getProvidedInterfaces() { - List result = new ArrayList(); - result.add(new DefaultProvidedInterface("provided", _class)); - return result; - } - - public List getRequiredInterfaces() { - List result = new ArrayList(); - result.addAll(_constructorConfig.getRequiredInterfaces()); - result.addAll(_objectConfig.getRequiredInterfaces()); - return result; - } + return result; + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ConstructorConfiguration.java b/system/general/src/main/java/org/wamblee/system/adapters/ConstructorConfiguration.java index 7a5c259d..b0057b5b 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ConstructorConfiguration.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ConstructorConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,165 +15,191 @@ */ package org.wamblee.system.adapters; -import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.wamblee.collections.CollectionFilter; + import org.wamblee.conditions.Condition; + import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Modifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * Class that allows configuration of the constructor to use. - * - * In particular, it provides: + * Class that allows configuration of the constructor to use. In particular, it + * provides: *
    - *
  • Selection of a constructor using explicit selection - * {@link #select(Class...)} or using the most greedy constructor - * {@link #greedy()}. - *
  • - *
  • - * Selection of methods to invoke to inject other objects into the object. - *
  • - *
  • Selection of fields to set. - *
  • + *
  • Selection of a constructor using explicit selection + * {@link #select(Class...)} or using the most greedy constructor + * {@link #greedy()}.
  • + *
  • Selection of methods to invoke to inject other objects into the object.
  • + *
  • Selection of fields to set.
  • *
*/ public class ConstructorConfiguration { - private Class _class; - private Constructor _constructor; - private ParameterValues _values; - private boolean _publicOnly; - - /** - * Constructs the configuration. By default the public constructor with the - * most arguments will be used. - * @param aClass Class to construct. - */ - public ConstructorConfiguration(Class aClass) { - _class = aClass; - _constructor = null; - _publicOnly = true; - } - - /** - * Sets whether or no non public constructors are also considered. - * Reset the choice of a constructor to its default. - * @param aNonPublic - * @return - */ - public ConstructorConfiguration setNonPublic(boolean aNonPublic) { - _publicOnly = !aNonPublic; - _constructor = null; - _values = null; - return this; - } - - /** - * Selects an explicit constructor. - * @param aTypes Arguments of the constructor. - * @return Return the injector to allow call chaining. - */ - public ConstructorConfiguration select(Class... aTypes) { - try { - _constructor = _class.getDeclaredConstructor(aTypes); - } catch (Exception e) { - throw new SystemAssemblyException(e.getMessage(), e); - } - resetValues(); - return this; - } - - /** - * Selects the greediest constructor. - * @return The injector to allow call chaining. - * @throws SystemAssemblyException if the greediest constructor cannot be uniquely - * identified. - */ - public ConstructorConfiguration greedy() { - Constructor[] declared = _class.getDeclaredConstructors(); - if (declared.length == 0) { - throw new SystemAssemblyException("Class '" + _class - + " is an interface, primitive type, or array"); - } - int max = -1; - List> checked = new ArrayList>(); - CollectionFilter.filter(Arrays.asList(declared), checked, - new Condition>() { - @Override - public boolean matches(Constructor aObject) { - if ( !_publicOnly ) { - return true; - } else { - return Modifier.isPublic(aObject.getModifiers()); - } - } - }); - for (Constructor ctor : checked) { - if (ctor.getParameterTypes().length > max) { - max = ctor.getParameterTypes().length; - } - } - final int max2 = max; - List> ctors = checked; - List> longest = new ArrayList>(); - CollectionFilter.filter(ctors, longest, - new Condition>() { - @Override - public boolean matches(Constructor aObject) { - return aObject.getParameterTypes().length == max2; - } - }); - if (longest.size() > 1) { - throw new SystemAssemblyException( - "Greediest constructor cannot be uniquely determined"); - } - _constructor = longest.get(0); - resetValues(); - return this; - } - - public ParameterValues getParameters() { - getConstructor(); // initialize constructor if needed. - return _values; - } - - /** - * Resets the values. - */ - private void resetValues() { - _constructor.setAccessible(true); - _values = new ParameterValues(_constructor.getParameterTypes()); - } - - /** - * Creates the object in the given scope. - * @param aScope Scope containing required interfaces for this object. - * @return object. - */ - public Object create(Scope aScope) { - Object[] values = _values.values(aScope); - try { - return getConstructor().newInstance(values); - } catch (Exception e) { - throw new SystemAssemblyException("Could not construct object " - + getConstructor() + " " + Arrays.asList(values), e); - } - } - - public List getRequiredInterfaces() { - getConstructor(); // initialize constructor if needed. - return _values.getRequiredInterfaces(); - } - - private Constructor getConstructor() { - if (_constructor == null ) { - greedy(); - } - return _constructor; - } + private Class clazz; + + private Constructor constructor; + + private ParameterValues values; + + private boolean publicOnly; + + /** + * Constructs the configuration. By default the public constructor with the + * most arguments will be used. + * + * @param aClass + * Class to construct. + */ + public ConstructorConfiguration(Class aClass) { + clazz = aClass; + constructor = null; + publicOnly = true; + } + + /** + * Sets whether or no non public constructors are also considered. Reset the + * choice of a constructor to its default. + * + * @param aNonPublic + * + * @return + */ + public ConstructorConfiguration setNonPublic(boolean aNonPublic) { + publicOnly = !aNonPublic; + constructor = null; + values = null; + + return this; + } + + /** + * Selects an explicit constructor. + * + * @return Return the injector to allow call chaining. + * + */ + public ConstructorConfiguration select(Class... aTypes) { + try { + constructor = clazz.getDeclaredConstructor(aTypes); + } catch (Exception e) { + throw new SystemAssemblyException(e.getMessage(), e); + } + + resetValues(); + + return this; + } + + /** + * Selects the greediest constructor. + * + * @return The injector to allow call chaining. + * + * @throws SystemAssemblyException + * if the greediest constructor cannot be uniquely identified. + */ + public ConstructorConfiguration greedy() { + Constructor[] declared = clazz.getDeclaredConstructors(); + + if (declared.length == 0) { + throw new SystemAssemblyException("Class '" + clazz + + " is an interface, primitive type, or array"); + } + + int max = -1; + List> checked = new ArrayList>(); + CollectionFilter.filter(Arrays.asList(declared), checked, + new Condition>() { + @Override + public boolean matches(Constructor aObject) { + if (!publicOnly) { + return true; + } else { + return Modifier.isPublic(aObject.getModifiers()); + } + } + }); + + for (Constructor ctor : checked) { + if (ctor.getParameterTypes().length > max) { + max = ctor.getParameterTypes().length; + } + } + + final int max2 = max; + List> ctors = checked; + List> longest = new ArrayList>(); + CollectionFilter.filter(ctors, longest, + new Condition>() { + @Override + public boolean matches(Constructor aObject) { + return aObject.getParameterTypes().length == max2; + } + }); + + if (longest.size() > 1) { + throw new SystemAssemblyException( + "Greediest constructor cannot be uniquely determined"); + } + + constructor = longest.get(0); + resetValues(); + + return this; + } + + public ParameterValues getParameters() { + getConstructor(); // initialize constructor if needed. + + return values; + } + + /** + * Resets the values. + */ + private void resetValues() { + constructor.setAccessible(true); + values = new ParameterValues(constructor.getParameterTypes()); + } + + /** + * Creates the object in the given scope. + * + * @param aScope + * Scope containing required interfaces for this object. + * + * @return object. + * + */ + public Object create(Scope aScope) { + Object[] valueArray = values.values(aScope); + + try { + return getConstructor().newInstance(valueArray); + } catch (Exception e) { + throw new SystemAssemblyException("Could not construct object " + + getConstructor() + " " + Arrays.asList(valueArray), e); + } + } + + public List getRequiredInterfaces() { + getConstructor(); // initialize constructor if needed. + + return values.getRequiredInterfaces(); + } + + private Constructor getConstructor() { + if (constructor == null) { + greedy(); + } + + return constructor; + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/DefaultContainer.java b/system/general/src/main/java/org/wamblee/system/adapters/DefaultContainer.java index 823b7c0d..a09507ae 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/DefaultContainer.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/DefaultContainer.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import org.wamblee.system.container.Container; @@ -20,8 +20,16 @@ import org.wamblee.system.core.Component; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultContainer extends Container { - + /** + * Creates a new DefaultContainer object. + * + */ public DefaultContainer(String aName) { super(aName); } @@ -29,32 +37,36 @@ public class DefaultContainer extends Container { @Override public DefaultContainer addComponent(Component aComponent) { super.addComponent(aComponent); + return this; } - - public DefaultContainer addComponent(String aName, ClassConfiguration aConfiguration) { + + public DefaultContainer addComponent(String aName, + ClassConfiguration aConfiguration) { return addComponent(new ClassAdapter(aName, aConfiguration)); } - public DefaultContainer addComponent(String aName, Object aObject, ObjectConfiguration aConfiguration) { - if ( !aConfiguration.appliesTo(aObject) ) { - throw new IllegalArgumentException("Configuration '" + aConfiguration + "' does nto applu to '" + - aObject + "'"); + public DefaultContainer addComponent(String aName, Object aObject, + ObjectConfiguration aConfiguration) { + if (!aConfiguration.appliesTo(aObject)) { + throw new IllegalArgumentException("Configuration '" + + aConfiguration + "' does nto applu to '" + aObject + "'"); } + return addComponent(new ObjectAdapter(aName, aObject, aConfiguration)); } - @Override public DefaultContainer addRequiredInterface(RequiredInterface aRequired) { super.addRequiredInterface(aRequired); + return this; } @Override public DefaultContainer addProvidedInterface(ProvidedInterface aProvided) { super.addProvidedInterface(aProvided); + return this; } - } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/FixedValueProvider.java b/system/general/src/main/java/org/wamblee/system/adapters/FixedValueProvider.java index 98fa48af..4cbe97b2 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/FixedValueProvider.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/FixedValueProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,23 +19,24 @@ import org.wamblee.system.core.Scope; /** * Value provider that provides a fixed value. - * + * * @author Erik Brakkee */ class FixedValueProvider implements ValueProvider { - - private Object _value; - - /** - * Constructs the value. - * @param aValue Value to construct. - */ - public FixedValueProvider(Object aValue) { - _value = aValue; - } + private Object value; + + /** + * Constructs the value. + * + * @param aValue + * Value to construct. + */ + public FixedValueProvider(Object aValue) { + value = aValue; + } - @Override - public Object getValue(Scope aScope) { - return _value; - } + @Override + public Object getValue(Scope aScope) { + return value; + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ObjectAdapter.java b/system/general/src/main/java/org/wamblee/system/adapters/ObjectAdapter.java index ff2fa0a2..19fd39b9 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ObjectAdapter.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ObjectAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import org.wamblee.system.core.AbstractComponent; @@ -22,37 +22,41 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; /** - * An adapter class that adapts an existing object to a component. - * + * An adapter class that adapts an existing object to a component. + * * @author Erik Brakkee */ public class ObjectAdapter extends AbstractComponent { + private ObjectConfiguration objectConfig; + + private Object object; + + /** + * Creates a new ObjectAdapter object. + * + */ + public ObjectAdapter(String aName, Object aObject, + ObjectConfiguration aObjectConfig) { + super(aName, new ProvidedInterface[] { new DefaultProvidedInterface( + aName, aObject.getClass()) }, aObjectConfig.getRequiredInterfaces() + .toArray(new RequiredInterface[0])); + objectConfig = aObjectConfig; + object = aObject; + } + + @Override + protected Object doStart(Scope aScope) { + objectConfig.inject(aScope, object); + + for (ProvidedInterface provided : getProvidedInterfaces()) { + addInterface(provided, object, aScope); + } + + return object; + } - private ObjectConfiguration _objectConfig; - private Object _object; - - public ObjectAdapter(String aName, Object aObject, ObjectConfiguration aObjectConfig) { - super(aName, - new ProvidedInterface[] { new DefaultProvidedInterface(aName, aObject.getClass()) }, - aObjectConfig.getRequiredInterfaces().toArray(new RequiredInterface[0])); - _objectConfig = aObjectConfig; - _object = aObject; - } - - @Override - protected Object doStart(Scope aScope) { - - _objectConfig.inject(aScope, _object); - - for (ProvidedInterface provided: getProvidedInterfaces()) { - addInterface(provided, _object, aScope); - } - - return _object; - } - - @Override - protected void doStop(Object aRuntime) { - // Empty. - } + @Override + protected void doStop(Object aRuntime) { + // Empty. + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ObjectConfiguration.java b/system/general/src/main/java/org/wamblee/system/adapters/ObjectConfiguration.java index 22df0491..51a90246 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ObjectConfiguration.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ObjectConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,48 +15,56 @@ */ package org.wamblee.system.adapters; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; +import java.util.ArrayList; +import java.util.List; + /** - * General configuration for an instantiated object. + * General configuration for an instantiated object. * * @author Erik Brakkee */ public class ObjectConfiguration { - - private Class _class; - private SetterConfiguration _setterConfig; + private Class clazz; + + private SetterConfiguration setterConfig; - public ObjectConfiguration(Class aClass) { - _class = aClass; - _setterConfig = new SetterConfiguration(aClass); + /** + * Creates a new ObjectConfiguration object. + * + */ + public ObjectConfiguration(Class aClass) { + clazz = aClass; + setterConfig = new SetterConfiguration(aClass); } - + /** - * Performs injection into an object of the configured class - * using information from the given scope. - * @param aScope Scope. - * @param aObject Object. + * Performs injection into an object of the configured class using + * information from the given scope. + * + * @param aScope + * Scope. + * @param aObject + * Object. */ - public void inject(Scope aScope, Object aObject) { - _setterConfig.inject(aScope, aObject); + public void inject(Scope aScope, Object aObject) { + setterConfig.inject(aScope, aObject); } - - public SetterConfiguration getSetterConfig() { - return _setterConfig; + + public SetterConfiguration getSetterConfig() { + return setterConfig; } - + public List getRequiredInterfaces() { List result = new ArrayList(); - result.addAll(_setterConfig.getRequiredInterfaces()); - return result; + result.addAll(setterConfig.getRequiredInterfaces()); + + return result; } public boolean appliesTo(Object aObject) { - return _class.isInstance(aObject); + return clazz.isInstance(aObject); } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ParameterValues.java b/system/general/src/main/java/org/wamblee/system/adapters/ParameterValues.java index 17789818..27ed495c 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ParameterValues.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ParameterValues.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,118 +15,146 @@ */ package org.wamblee.system.adapters; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** - * Represents parameter values for a method or constructor and allows for the configuration - * of how these values are retrieved. + * Represents parameter values for a method or constructor and allows for the + * configuration of how these values are retrieved. * * @author Erik Brakkee */ public class ParameterValues { - private String[] _names; - private Class[] _types; - private ValueProvider[] _values; - - /** - * Constructs the configuration. By default no constructor is selected and - * one of {@link #select(Class...)} or - * {@link #greedy()} must be called. - * @param aClass Class to construct. - */ - public ParameterValues(Class[] aTypes) { - _names = new String[aTypes.length]; - for (int i = 0; i < aTypes.length; i++) { - _names[i] = "arg" + i; - } - _types = aTypes; - resetValues(); - } - - /** - * Constructs the configuration. By default no constructor is selected and - * one of {@link #select(Class...)} or - * {@link #greedy()} must be called. - * @param aNames Names of the arguments. - * @param aClass Class to construct. + private String[] names; + + private Class[] types; + + private ValueProvider[] values; + + /** + * Constructs the configuration. By default no constructor is selected and + * one of {@link #select(Class...)} or {@link #greedy()} must be called. + * + * @param aClass + * Class to construct. + */ + public ParameterValues(Class[] aTypes) { + names = new String[aTypes.length]; + + for (int i = 0; i < aTypes.length; i++) { + names[i] = "arg" + i; + } + + types = aTypes; + resetValues(); + } + + /** + * Constructs the configuration. By default no constructor is selected and + * one of {@link #select(Class...)} or {@link #greedy()} must be called. + * + * @param aNames + * Names of the arguments. + * @param aClass + * Class to construct. */ public ParameterValues(String[] aNames, Class[] aTypes) { - assert aNames.length == aTypes.length; - _names = aNames; - _types = aTypes; - resetValues(); + assert aNames.length == aTypes.length; + names = aNames; + types = Arrays.copyOf(aTypes, aTypes.length); + resetValues(); + } + + /** + * The types of the parameter values. + * + * @return Types. + */ + public Class[] getTypes() { + return Arrays.copyOf(types, types.length); + } + + /** + * Sets argument i to be optional, meaning that null is allowed to be passed + * in. + * + * @param aArg + * Argument to set. + * + */ + public ParameterValues setOptional(int aArg) { + values[aArg] = new RequiredInterfaceProvider( + new DefaultRequiredInterface("arg" + aArg, types[aArg], true)); + + return this; + } + + /** + * Sets the argument i to a fixed value. + * + * @param aArg + * Argument to set. + * @param aValue + * Value. + * + */ + public ParameterValues setValue(int aArg, Object aValue) { + values[aArg] = new FixedValueProvider(aValue); + + return this; + } + + /** + * Resets the values. + */ + private void resetValues() { + values = new ValueProvider[types.length]; + + for (int i = 0; i < values.length; i++) { + values[i] = new RequiredInterfaceProvider( + new DefaultRequiredInterface(names[i], types[i])); + } + } + + /** + * Gets the required interfaces to provide values that are not provided in + * another way. + * + * @return Required interfaces. + */ + public List getRequiredInterfaces() { + List result = new ArrayList(); + + for (ValueProvider provider : values) { + if (provider instanceof RequiredInterfaceProvider) { + result.add(((RequiredInterfaceProvider) provider) + .getRequiredInterface()); + } + } + + return result; + } + + /** + * Returns the values to use in the given scope. + * + * @param aScope + * Scope within which to retrieve the values. + * + * @return Values. + */ + public Object[] values(Scope aScope) { + Object[] valueArray = new Object[values.length]; + + for (int i = 0; i < values.length; i++) { + valueArray[i] = values[i].getValue(aScope); + } + + return valueArray; } - - /** - * The types of the parameter values. - * @return Types. - */ - public Class[] getTypes() { - return _types; - } - - /** - * Sets argument i to be optional, meaning that null is allowed to be passed in. - * @param aArg Argument to set. - */ - public ParameterValues setOptional(int aArg) { - _values[aArg] = new RequiredInterfaceProvider(new DefaultRequiredInterface( - "arg" + aArg, _types[aArg], true)); - return this; - } - - /** - * Sets the argument i to a fixed value. - * @param aArg Argument to set. - * @param aValue Value. - */ - public ParameterValues setValue(int aArg, Object aValue) { - _values[aArg] = new FixedValueProvider(aValue); - return this; - } - - /** - * Resets the values. - */ - private void resetValues() { - _values = new ValueProvider[_types.length]; - for (int i = 0; i < _values.length; i++) { - _values[i] = new RequiredInterfaceProvider(new DefaultRequiredInterface( - _names[i], _types[i])); - } - } - - /** - * Gets the required interfaces to provide values that are not provided - * in another way. - * @return Required interfaces. - */ - public List getRequiredInterfaces() { - List result = new ArrayList(); - for (ValueProvider provider: _values) { - if ( provider instanceof RequiredInterfaceProvider) { - result.add( ((RequiredInterfaceProvider)provider).getRequiredInterface()); - } - } - return result; - } - - /** - * Returns the values to use in the given scope. - * @param aScope Scope within which to retrieve the values. - * @return Values. - */ - public Object[] values(Scope aScope) { - Object[] values = new Object[_values.length]; - for (int i = 0; i < _values.length; i++) { - values[i] = _values[i].getValue(aScope); - } - return values; - } - } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/RequiredInterfaceProvider.java b/system/general/src/main/java/org/wamblee/system/adapters/RequiredInterfaceProvider.java index 56170aed..1fd34625 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/RequiredInterfaceProvider.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/RequiredInterfaceProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,28 +20,29 @@ import org.wamblee.system.core.Scope; /** * Value provider that provides a value through a required interface. - * + * * @author Erik Brakkee */ class RequiredInterfaceProvider implements ValueProvider { - - private RequiredInterface _required; - - /** - * Constructs the provider - * @param aRequired Required interface. - */ - public RequiredInterfaceProvider(RequiredInterface aRequired) { - _required = aRequired; - } - - @Override - public Object getValue(Scope aScope) { - return aScope.getInterfaceImplementation(_required.getProvider(), Object.class); - } - - public RequiredInterface getRequiredInterface() { - return _required; - } + private RequiredInterface required; + + /** + * Constructs the provider + * + * @param aRequired + * Required interface. + */ + public RequiredInterfaceProvider(RequiredInterface aRequired) { + required = aRequired; + } + + @Override + public Object getValue(Scope aScope) { + return aScope.getInterfaceImplementation(required.getProvider(), + Object.class); + } + public RequiredInterface getRequiredInterface() { + return required; + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java b/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java index 57323a54..fffd828c 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/SetterConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,22 +15,15 @@ */ package org.wamblee.system.adapters; -import java.awt.CompositeContext; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import org.wamblee.collections.CollectionFilter; + import org.wamblee.conditions.Condition; import org.wamblee.conditions.FixedCondition; + import org.wamblee.general.Pair; + import org.wamblee.reflection.ReflectionUtils; + import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.ProvidedInterface; @@ -38,6 +31,19 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; +import java.awt.CompositeContext; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + /** * Represents the configuration for exposing the setters of a class as required * interfaces. @@ -45,259 +51,298 @@ import org.wamblee.system.core.SystemAssemblyException; * @author Erik Brakkee */ public class SetterConfiguration { + private Class clazz; + + private boolean publicOnly; + + private Map setters; + + /** + * Constructs the setter configuration. By default no setters are added. + * + * @param aClass + * Class which is being configured. + */ + public SetterConfiguration(Class aClass) { + clazz = aClass; + publicOnly = true; + setters = new HashMap(); + } + + /** + * Makes sure that all available setters are used. + * + */ + public SetterConfiguration initAllSetters() { + setters.clear(); + + for (Method method : getAllSetters(clazz, publicOnly)) { + setters.put(method, createParameterValues(method)); + } + + return this; + } + + /** + * Called to set whether non-public setters are also used. By default only + * public setters are used. The currently selected setters remain chosen. + * + * @param aIsNonPublic + * Non public flag. + * + */ + public SetterConfiguration setNonPublic(boolean aIsNonPublic) { + publicOnly = !aIsNonPublic; + + return this; + } + + /** + * Removes all setters. + * + * @return Reference to the current object to allow call chaining. + */ + public SetterConfiguration clear() { + setters.clear(); + + return this; + } + + /** + * Removes a setter from the set of methods. + * + * @param aName + * Name of the setter to remove. + * + * @return Reference to the current object to allow call chaining. + * + */ + public SetterConfiguration remove(String aName) { + for (Method method : setters.keySet()) { + if (method.getName().equals(aName)) { + setters.remove(method); - private Class _class; - private boolean _publicOnly; - - private Map _setters; - - /** - * Constructs the setter configuration. By default no setters are added. - * - * @param aClass - * Class which is being configured. - */ - public SetterConfiguration(Class aClass) { - _class = aClass; - _publicOnly = true; - _setters = new HashMap(); - } - - /** - * Makes sure that all available setters are used. - */ - public SetterConfiguration initAllSetters() { - _setters.clear(); - for (Method method: getAllSetters(_class, _publicOnly) ) { - _setters.put(method, createParameterValues(method)); - } - return this; - } - - /** - * Called to set whether non-public setters are also used. By default only - * public setters are used. The currently selected setters remain chosen. - * - * @param aIsNonPublic - * Non public flag. - */ - public SetterConfiguration setNonPublic(boolean aIsNonPublic) { - _publicOnly = !aIsNonPublic; - return this; - } - - /** - * Removes all setters. - * - * @return Reference to the current object to allow call chaining. - */ - public SetterConfiguration clear() { - _setters.clear(); - return this; - } - - /** - * Removes a setter from the set of methods. - * - * @param aName - * Name of the setter to remove. - * @return Reference to the current object to allow call chaining. - */ - public SetterConfiguration remove(String aName) { - for (Method method : _setters.keySet()) { - if (method.getName().equals(aName)) { - _setters.remove(method); - return this; - } - } - throw new IllegalArgumentException( - "No method configured by the name of '" + aName + "'"); - } - - /** - * Removes the method from the set of methods. - * @param aMethod Method to remove. - * @return - */ - public SetterConfiguration remove(Method aMethod) { - if ( !aMethod.getDeclaringClass().isAssignableFrom(_class) ) { - throw new RuntimeException("Method " + aMethod + " not found in class " + _class + " or its superclasses"); - } - for (Method method : _setters.keySet()) { - if (method.equals(aMethod)) { - _setters.remove(method); return this; } } + throw new IllegalArgumentException( - "Method '" + aMethod + "' was not configured. "); - } - - /** - * Adds a given setter name to the setters. - * - * @param aName Name of a setter method. - * @return Reference to the current object to allow call chaining. - */ - public SetterConfiguration add(final String aName) { - int oldlen = _setters.size(); - List methods = new ArrayList(); - CollectionFilter.filter(getAllSetters(_class, _publicOnly), methods, - new Condition() { - @Override - public boolean matches(Method aObject) { - return aObject.getName().equals(aName); - } - - }); - if (methods.size() == 0 ) { - throw new IllegalArgumentException("Method '" + aName - + "' not found in " + _class.getName()); - } - // TODO is it possible to get more than one setter here in case the subclass overrides - // the baseclass method? - _setters.put(methods.get(0), createParameterValues(methods.get(0))); - return this; - } - - /** - * Adds a given setter identified by the type it accepts to the list of - * setters.N - * - * @param aType - * Type to look for. Note that this must be the exact type as - * autoboxing and autounboxing is not used. - * @return Reference to the current object to allow call chaining. - * @throws IllegalArgumentException - * In case no setter is found or multiple setters are found. - */ - public SetterConfiguration addSetter(final Class aType) { - List result = new ArrayList(); - CollectionFilter.filter(getAllSetters(_class, _publicOnly), result, - new Condition() { - @Override - public boolean matches(Method aObject) { - Class type = aObject.getParameterTypes()[0]; - return type.equals(aType); - } - - }); - if (result.size() == 0) { - throw new IllegalArgumentException("No setter found in class '" - + _class.getName() - + "' that has a setter with argument type '" - + aType.getName() + "'"); - } - if (result.size() > 1) { - String setters = ""; - for (Method method : result) { - setters += method.getName() + " "; - } - throw new IllegalArgumentException( - "Multiple setters found in class '" + _class.getName() - + " that accept type '" + aType.getName() + "': " - + setters); - } - Method method = result.get(0); - _setters.put(method, createParameterValues(method)); - return this; - } - - /** - * Gets all setters for the current class. - * - * @return List of all setters. - */ - public static List getAllSetters(Class aClass, - boolean aPublicOnly) { - List result = new ArrayList(); - for (Method method : getAllMethods(aClass)) { - if (!aPublicOnly || Modifier.isPublic(method.getModifiers())) { - if (method.getName().startsWith("set") - && method.getParameterTypes().length == 1) { - method.setAccessible(true); - result.add(method); - } - } - } - return result; - } - - private static ParameterValues createParameterValues(Method aMethod) { - - Class[] paramTypes = aMethod.getParameterTypes(); - String[] paramNames = new String[paramTypes.length]; - for (int i = 0; i < paramTypes.length; i++) { - paramNames[i] = aMethod.getName() + "." + i; - } - return new ParameterValues(paramNames, paramTypes); - } - - private static final List getAllMethods(Class aClass) { - return ReflectionUtils.getAllMethods(aClass); - } - - /** - * Gets the required interfaces based on the configured setteres. - * - * @return List of required interfaces. - */ - public List getRequiredInterfaces() { - List result = new ArrayList(); - for (Method method : _setters.keySet()) { - result.addAll(_setters.get(method).getRequiredInterfaces()); - } - return result; - } - - /** - * Invokes all configured setters with the appropriate values. - * - * @param aScope - * Scope within which invocation takes place. - * @param aObject - * Object on which the invocation takes place. - */ - public void inject(Scope aScope, Object aObject) { - if (!_class.isInstance(aObject)) { - throw new IllegalArgumentException("Object '" + aObject - + "' is not an instance of " + _class.getName()); - } - for (Method method : _setters.keySet()) { - ParameterValues values = _setters.get(method); - - try { - method.invoke(aObject, values.values(aScope)); - } catch (IllegalAccessException e) { - throw new SystemAssemblyException("Problem invoking " + method - + " with " + values, e); - } catch (InvocationTargetException e) { - throw new SystemAssemblyException("Problem invoking " + method - + " with " + values, e); - } - } - } - - /** - * Returns the parameter values for allowing detailed configuration of how - * parameter values are set. - * - * @param aSetter - * Setter name without the "set" prefix with the first character - * converted to lower case. - * @return Parameter values. - */ - public ParameterValues values(String aMethod) { - for (Method method : _setters.keySet()) { - if (method.getName().equals(aMethod)) { - return _setters.get(method); - } - } - throw new IllegalArgumentException("No setter method '" + aMethod - + "' found"); - } - - public List getSetters() { - return new ArrayList(_setters.keySet()); - } + "No method configured by the name of '" + aName + "'"); + } + + /** + * Removes the method from the set of methods. + * + * @param aMethod + * Method to remove. + * + * @return + * + */ + public SetterConfiguration remove(Method aMethod) { + if (!aMethod.getDeclaringClass().isAssignableFrom(clazz)) { + throw new RuntimeException("Method " + aMethod + + " not found in class " + clazz + " or its superclasses"); + } + + for (Method method : setters.keySet()) { + if (method.equals(aMethod)) { + setters.remove(method); + + return this; + } + } + + throw new IllegalArgumentException("Method '" + aMethod + + "' was not configured. "); + } + + /** + * Adds a given setter name to the setters. + * + * @param aName + * Name of a setter method. + * + * @return Reference to the current object to allow call chaining. + * + */ + public SetterConfiguration add(final String aName) { + List methods = new ArrayList(); + CollectionFilter.filter(getAllSetters(clazz, publicOnly), methods, + new Condition() { + @Override + public boolean matches(Method aObject) { + return aObject.getName().equals(aName); + } + }); + + if (methods.size() == 0) { + throw new IllegalArgumentException("Method '" + aName + + "' not found in " + clazz.getName()); + } + + // TODO is it possible to get more than one setter here in case the + // subclass overrides + // the baseclass method? + setters.put(methods.get(0), createParameterValues(methods.get(0))); + + return this; + } + + /** + * Adds a given setter identified by the type it accepts to the list of + * setters.N + * + * @param aType + * Type to look for. Note that this must be the exact type as + * autoboxing and autounboxing is not used. + * + * @return Reference to the current object to allow call chaining. + * + * @throws IllegalArgumentException + * In case no setter is found or multiple setters are found. + */ + public SetterConfiguration addSetter(final Class aType) { + List result = new ArrayList(); + CollectionFilter.filter(getAllSetters(clazz, publicOnly), result, + new Condition() { + @Override + public boolean matches(Method aObject) { + Class type = aObject.getParameterTypes()[0]; + + return type.equals(aType); + } + }); + + if (result.size() == 0) { + throw new IllegalArgumentException("No setter found in class '" + + clazz.getName() + "' that has a setter with argument type '" + + aType.getName() + "'"); + } + + if (result.size() > 1) { + StringBuffer setters = new StringBuffer(); + + for (Method method : result) { + setters.append((method.getName() + " ")); + } + + throw new IllegalArgumentException( + "Multiple setters found in class '" + clazz.getName() + + " that accept type '" + aType.getName() + "': " + setters); + } + + Method method = result.get(0); + setters.put(method, createParameterValues(method)); + + return this; + } + + /** + * Gets all setters for the current class. + * + * + * @return List of all setters. + */ + public static List getAllSetters(Class aClass, boolean aPublicOnly) { + List result = new ArrayList(); + + for (Method method : getAllMethods(aClass)) { + if (!aPublicOnly || Modifier.isPublic(method.getModifiers())) { + if (method.getName().startsWith("set") && + (method.getParameterTypes().length == 1)) { + method.setAccessible(true); + result.add(method); + } + } + } + + return result; + } + + private static ParameterValues createParameterValues(Method aMethod) { + Class[] paramTypes = aMethod.getParameterTypes(); + String[] paramNames = new String[paramTypes.length]; + + for (int i = 0; i < paramTypes.length; i++) { + paramNames[i] = aMethod.getName() + "." + i; + } + + return new ParameterValues(paramNames, paramTypes); + } + + private static final List getAllMethods(Class aClass) { + return ReflectionUtils.getAllMethods(aClass); + } + + /** + * Gets the required interfaces based on the configured setteres. + * + * @return List of required interfaces. + */ + public List getRequiredInterfaces() { + List result = new ArrayList(); + + for (Method method : setters.keySet()) { + result.addAll(setters.get(method).getRequiredInterfaces()); + } + + return result; + } + + /** + * Invokes all configured setters with the appropriate values. + * + * @param aScope + * Scope within which invocation takes place. + * @param aObject + * Object on which the invocation takes place. + * + */ + public void inject(Scope aScope, Object aObject) { + if (!clazz.isInstance(aObject)) { + throw new IllegalArgumentException("Object '" + aObject + + "' is not an instance of " + clazz.getName()); + } + + for (Method method : setters.keySet()) { + ParameterValues values = setters.get(method); + + try { + method.invoke(aObject, values.values(aScope)); + } catch (IllegalAccessException e) { + throw new SystemAssemblyException("Problem invoking " + method + + " with " + values, e); + } catch (InvocationTargetException e) { + throw new SystemAssemblyException("Problem invoking " + method + + " with " + values, e); + } + } + } + + /** + * Returns the parameter values for allowing detailed configuration of how + * parameter values are set. + * + * @param aMethod + * Setter name without the "set" prefix with the first character + * converted to lower case. + * + * @return Parameter values. + * + */ + public ParameterValues values(String aMethod) { + for (Method method : setters.keySet()) { + if (method.getName().equals(aMethod)) { + return setters.get(method); + } + } + + throw new IllegalArgumentException("No setter method '" + aMethod + + "' found"); + } + + public List getSetters() { + return new ArrayList(setters.keySet()); + } } diff --git a/system/general/src/main/java/org/wamblee/system/adapters/ValueProvider.java b/system/general/src/main/java/org/wamblee/system/adapters/ValueProvider.java index 6582f8fc..d8f80238 100644 --- a/system/general/src/main/java/org/wamblee/system/adapters/ValueProvider.java +++ b/system/general/src/main/java/org/wamblee/system/adapters/ValueProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,11 +18,10 @@ package org.wamblee.system.adapters; import org.wamblee.system.core.Scope; /** - * Interface used to provide values for arguments of methods and constructors. + * Interface used to provide values for arguments of methods and constructors. * * @author Erik Brakkee */ interface ValueProvider { - - Object getValue(Scope aScope); + Object getValue(Scope aScope); } diff --git a/system/general/src/main/java/org/wamblee/system/components/ORMappingConfig.java b/system/general/src/main/java/org/wamblee/system/components/ORMappingConfig.java index 880e869e..6aad44a1 100644 --- a/system/general/src/main/java/org/wamblee/system/components/ORMappingConfig.java +++ b/system/general/src/main/java/org/wamblee/system/components/ORMappingConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.components; public class ORMappingConfig { @@ -42,20 +42,20 @@ public class ORMappingConfig { } }; - private boolean _schemaUpdate; - private DatabaseType _type; + private boolean schemaUpdate; + private DatabaseType type; public ORMappingConfig(boolean aSchemaUpdate, DatabaseType aType) { - _schemaUpdate = aSchemaUpdate; - _type = aType; + schemaUpdate = aSchemaUpdate; + type = aType; } public boolean isSchemaUpdate() { - return _schemaUpdate; + return schemaUpdate; } public DatabaseType getType() { - return _type; + return type; } } diff --git a/system/general/src/main/java/org/wamblee/system/components/PropertyComponent.java b/system/general/src/main/java/org/wamblee/system/components/PropertyComponent.java index d3c7e070..f64c2f09 100644 --- a/system/general/src/main/java/org/wamblee/system/components/PropertyComponent.java +++ b/system/general/src/main/java/org/wamblee/system/components/PropertyComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,56 +15,69 @@ */ package org.wamblee.system.components; -import java.io.IOException; -import java.util.Properties; - import org.wamblee.io.InputResource; + import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.Scope; +import java.io.IOException; + +import java.util.Properties; + /** - * Property component that reads a property file and provides - * it to other components through a provided interface. + * Property component that reads a property file and provides it to other + * components through a provided interface. NOTE: when multiple property + * components are used, disambiguation of provided and required interfaces is + * needed. * - * NOTE: when multiple property components are used, disambiguation - * of provided and required interfaces is needed. - * * @author Erik Brakkee */ public class PropertyComponent extends AbstractComponent { - - private static ProvidedInterface PROPS = new DefaultProvidedInterface("props", Properties.class); - - private Properties _props; - - public PropertyComponent(String aName, InputResource aResource) throws IOException { - this(aName, readProps(aResource)); - } - - private static Properties readProps(InputResource aResource) throws IOException { - Properties props = new Properties(); - props.load(aResource.getInputStream()); - return props; + private static ProvidedInterface PROPS = new DefaultProvidedInterface( + "props", Properties.class); + + private Properties props; + + /** + * Creates a new PropertyComponent object. + * + * + */ + public PropertyComponent(String aName, InputResource aResource) + throws IOException { + this(aName, readProps(aResource)); } + /** + * Creates a new PropertyComponent object. + * + */ public PropertyComponent(String aName, Properties aProps) { super(aName); - _props = aProps; - + props = aProps; + addProvidedInterface(PROPS); } + private static Properties readProps(InputResource aResource) + throws IOException { + Properties props = new Properties(); + props.load(aResource.getInputStream()); + + return props; + } + @Override protected Properties doStart(Scope aScope) { - addInterface(PROPS, _props, aScope); - return _props; + addInterface(PROPS, props, aScope); + + return props; } @Override protected void doStop(Properties aRuntime) { - // Empty + // Empty } - } diff --git a/system/general/src/main/java/org/wamblee/system/container/Container.java b/system/general/src/main/java/org/wamblee/system/container/Container.java index 9669cb21..dc0995a4 100644 --- a/system/general/src/main/java/org/wamblee/system/container/Container.java +++ b/system/general/src/main/java/org/wamblee/system/container/Container.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,16 +12,14 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.container; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.wamblee.general.Pair; + import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultScope; @@ -36,18 +34,23 @@ import org.wamblee.system.graph.component.ConnectExternalProvidedProvidedFilter; import org.wamblee.system.graph.component.ConnectRequiredExternallyRequiredEdgeFilter; import org.wamblee.system.graph.component.ConnectRequiredProvidedEdgeFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Container consisting of multiple components. * * @author Erik Brakkee */ public class Container extends AbstractComponent { - private static final Log LOG = LogFactory.getLog(Container.class); - private List _components; - private CompositeEdgeFilter _edgeFilter; - private boolean _sealed; + private List components; + + private CompositeEdgeFilter edgeFilter; + + private boolean sealed; /** * Constructs the container @@ -62,17 +65,18 @@ public class Container extends AbstractComponent { * Required services by the container. */ public Container(String aName, Component[] aComponents, - List aProvided, List aRequired) { + List aProvided, List aRequired) { super(aName, aProvided, aRequired); - _components = new ArrayList(); + components = new ArrayList(); + + edgeFilter = new CompositeEdgeFilter(); + sealed = false; - _edgeFilter = new CompositeEdgeFilter(); - _sealed = false; for (Component component : aComponents) { addComponent(component); } } - + /** * Constructs the container * @@ -86,130 +90,183 @@ public class Container extends AbstractComponent { * Required services by the container. */ public Container(String aName, Component[] aComponents, - ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { - this(aName, aComponents, Arrays.asList(aProvided), Arrays.asList(aRequired)); + ProvidedInterface[] aProvided, RequiredInterface[] aRequired) { + this(aName, aComponents, Arrays.asList(aProvided), Arrays + .asList(aRequired)); } + /** + * Creates a new Container object. + * + */ public Container(String aName) { this(aName, new Component[0], new ProvidedInterface[0], - new RequiredInterface[0]); + new RequiredInterface[0]); } public Container addComponent(Component aComponent) { checkSealed(); + if (aComponent.getContext() != null) { throw new SystemAssemblyException( - "Inconsistent hierarchy, component '" - + aComponent.getName() - + "' is already part of another hierarchy"); + "Inconsistent hierarchy, component '" + aComponent.getName() + + "' is already part of another hierarchy"); } - if ( findComponent(aComponent.getName()) != null ) { - throw new SystemAssemblyException("Duplicate component '" - + aComponent.getName() + "'"); + + if (findComponent(aComponent.getName()) != null) { + throw new SystemAssemblyException("Duplicate component '" + + aComponent.getName() + "'"); } - _components.add(aComponent); + + components.add(aComponent); aComponent.addContext(getQualifiedName()); + return this; } - + /** - * Explictly connects required and provided interfaces. - * @param aClientComponent Client component, may not be null. - * @param aRequiredInterface Required interface. If null it means all required interfaces. - * @param aServerComponent Server component to connect to. If null, it means that no server components - * may be connected to and the provider of the required interface will be null. - * @param aProvidedInterface Provided interface. If null, it means that there is no restriction on the - * name of the provided interface and that it is automatically selected. + * Explictly connects required and provided interfaces. + * + * @param aClientComponent + * Client component, may not be null. + * @param aRequiredInterface + * Required interface. If null it means all required interfaces. + * @param aServerComponent + * Server component to connect to. If null, it means that no + * server components may be connected to and the provider of the + * required interface will be null. + * @param aProvidedInterface + * Provided interface. If null, it means that there is no + * restriction on the name of the provided interface and that it + * is automatically selected. + * */ - public void connectRequiredProvided(String aClientComponent, String aRequiredInterface, - String aServerComponent, String aProvidedInterface) { + public void connectRequiredProvided(String aClientComponent, + String aRequiredInterface, String aServerComponent, + String aProvidedInterface) { checkSealed(); + Component client = findComponent(aClientComponent); Component server = findComponent(aServerComponent); - if ( client == null ) { - throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aClientComponent + "' in the container"); + + if (client == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": No component '" + aClientComponent + "' in the container"); } - if ( aRequiredInterface != null ) { - if ( findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null ) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aClientComponent + "' does not have a required interface named '" - + aRequiredInterface + "'"); - } + + if (aRequiredInterface != null) { + if (findInterface(client.getRequiredInterfaces(), + aRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aClientComponent + + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } } - if ( server == null ) { - throw new SystemAssemblyException("No component '" + aClientComponent + "' in the container"); + + if (server == null) { + throw new SystemAssemblyException("No component '" + + aClientComponent + "' in the container"); } - if ( aProvidedInterface != null ) { - if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aServerComponent + "' does not have a provided interface named '" - + aProvidedInterface + "'"); - } + + if (aProvidedInterface != null) { + if (findInterface(server.getProvidedInterfaces(), + aProvidedInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aServerComponent + + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } } - _edgeFilter.add(new ConnectRequiredProvidedEdgeFilter(aClientComponent, aRequiredInterface, aServerComponent, aProvidedInterface)); + + edgeFilter.add(new ConnectRequiredProvidedEdgeFilter(aClientComponent, + aRequiredInterface, aServerComponent, aProvidedInterface)); } - + /** - * Explicitly connects a externally required interface to an internally required interface. - * @param aComponent Component requiring the interface (must be non-null). - * @param aRequiredInterface Required interface of the component (must be non-null). - * @param aExternalRequiredInterface Externally required interface (must be non-null). + * Explicitly connects a externally required interface to an internally + * required interface. + * + * @param aComponent + * Component requiring the interface (must be non-null). + * @param aRequiredInterface + * Required interface of the component (must be non-null). + * @param aExternalRequiredInterface + * Externally required interface (must be non-null). + * */ - public void connectExternalRequired(String aComponent, String aRequiredInterface, - String aExternalRequiredInterface) { + public void connectExternalRequired(String aComponent, + String aRequiredInterface, String aExternalRequiredInterface) { checkSealed(); + Component client = findComponent(aComponent); - if ( client == null ) { - throw new SystemAssemblyException(getQualifiedName() + ": No component '" + aComponent + "' in the container"); + + if (client == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": No component '" + aComponent + "' in the container"); } - if ( aRequiredInterface != null ) { - if ( findInterface(client.getRequiredInterfaces(), aRequiredInterface) == null ) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aComponent + "' does not have a required interface named '" - + aRequiredInterface + "'"); - } + + if (aRequiredInterface != null) { + if (findInterface(client.getRequiredInterfaces(), + aRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aComponent + + "' does not have a required interface named '" + + aRequiredInterface + "'"); + } } - if ( aExternalRequiredInterface != null) { - if ( findInterface(getRequiredInterfaces(), aExternalRequiredInterface) == null ) { - throw new SystemAssemblyException( - getQualifiedName() + ": container does not have a required interface named '" - + aExternalRequiredInterface + "'"); - } + + if (aExternalRequiredInterface != null) { + if (findInterface(getRequiredInterfaces(), + aExternalRequiredInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": container does not have a required interface named '" + + aExternalRequiredInterface + "'"); + } } - _edgeFilter.add(new ConnectRequiredExternallyRequiredEdgeFilter( - aComponent, aRequiredInterface, aExternalRequiredInterface)); + + edgeFilter.add(new ConnectRequiredExternallyRequiredEdgeFilter( + aComponent, aRequiredInterface, aExternalRequiredInterface)); } - - public void connectExternalProvided(String aExternalProvided, String aComponent, String aProvidedInterface) { + + public void connectExternalProvided(String aExternalProvided, + String aComponent, String aProvidedInterface) { checkSealed(); + Component server = findComponent(aComponent); - - - if ( server == null ) { - throw new SystemAssemblyException("No component '" + aComponent + "' in the container"); + + if (server == null) { + throw new SystemAssemblyException("No component '" + aComponent + + "' in the container"); } - if ( aProvidedInterface != null ) { - if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { - throw new SystemAssemblyException( - getQualifiedName() + ": Component '" + aComponent + "' does not have a provided interface named '" - + aProvidedInterface + "'"); - } + + if (aProvidedInterface != null) { + if (findInterface(server.getProvidedInterfaces(), + aProvidedInterface) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Component '" + aComponent + + "' does not have a provided interface named '" + + aProvidedInterface + "'"); + } } - if ( aExternalProvided != null ) { - if ( findInterface(getProvidedInterfaces(), aExternalProvided) == null) { - throw new SystemAssemblyException( - getQualifiedName() + ": Container does not have a provided interface named '" - + aExternalProvided + "'"); - } + + if (aExternalProvided != null) { + if (findInterface(getProvidedInterfaces(), aExternalProvided) == null) { + throw new SystemAssemblyException(getQualifiedName() + + ": Container does not have a provided interface named '" + + aExternalProvided + "'"); + } } - _edgeFilter.add(new ConnectExternalProvidedProvidedFilter(aExternalProvided, aComponent, aProvidedInterface)); - } + edgeFilter.add(new ConnectExternalProvidedProvidedFilter( + aExternalProvided, aComponent, aProvidedInterface)); + } @Override public Container addProvidedInterface(ProvidedInterface aProvided) { checkSealed(); super.addProvidedInterface(aProvided); + return this; } @@ -217,13 +274,15 @@ public class Container extends AbstractComponent { public Container addRequiredInterface(RequiredInterface aRequired) { checkSealed(); super.addRequiredInterface(aRequired); + return this; } @Override public void addContext(String aContext) { super.addContext(aContext); - for (Component component : _components) { + + for (Component component : components) { component.addContext(aContext); } } @@ -233,9 +292,6 @@ public class Container extends AbstractComponent { * services not in the required list and no services in the provided list * that cannot be provided. Also logs a warning in case of superfluous * requirements. - * - * @throws SystemAssemblyException - * in case of any validation problems. */ public void validate() { doStartOptionalDryRun(null, true); @@ -246,7 +302,7 @@ public class Container extends AbstractComponent { * be added. */ public void seal() { - _sealed = true; + sealed = true; } /** @@ -255,7 +311,7 @@ public class Container extends AbstractComponent { * @return True iff the container is sealed. */ public boolean isSealed() { - return _sealed; + return sealed; } /** @@ -266,24 +322,29 @@ public class Container extends AbstractComponent { */ public Scope start() { Scope scope = new DefaultScope(getProvidedInterfaces()); + return super.start(scope); } @Override protected Scope doStart(Scope aExternalScope) { validate(); - Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope); + + Scope scope = new DefaultScope(getProvidedInterfaces().toArray( + new ProvidedInterface[0]), aExternalScope); ComponentGraph graph = doStartOptionalDryRun(scope, false); exposeProvidedInterfaces(graph, aExternalScope, scope); seal(); + return scope; } - private void exposeProvidedInterfaces(ComponentGraph aGraph, Scope aExternalScope, - Scope aInternalScope) { - for (Pair mapping: - aGraph.findExternalProvidedInterfaceMapping()) { - Object svc = aInternalScope.getInterfaceImplementation(mapping.getSecond(), Object.class); + private void exposeProvidedInterfaces(ComponentGraph aGraph, + Scope aExternalScope, Scope aInternalScope) { + for (Pair mapping : aGraph + .findExternalProvidedInterfaceMapping()) { + Object svc = aInternalScope.getInterfaceImplementation(mapping + .getSecond(), Object.class); addInterface(mapping.getFirst(), svc, aExternalScope); } } @@ -296,7 +357,8 @@ public class Container extends AbstractComponent { LOG.info("Starting '" + getQualifiedName() + "'"); List started = new ArrayList(); - for (Component component : _components) { + + for (Component component : components) { try { // Start the service. if (!aDryRun) { @@ -307,33 +369,38 @@ public class Container extends AbstractComponent { } catch (SystemAssemblyException e) { throw e; } catch (RuntimeException e) { - LOG.error(getQualifiedName() + ": could not start '" - + component.getQualifiedName() + "'", e); + LOG.error(getQualifiedName() + ": could not start '" + + component.getQualifiedName() + "'", e); stopAlreadyStartedComponents(started, aScope); throw e; } } + return graph; } private ComponentGraph createComponentGraph() { ComponentGraph graph = new ComponentGraph(); + for (RequiredInterface req : getRequiredInterfaces()) { graph.addRequiredInterface(this, req); } - for (Component comp : _components) { + + for (Component comp : components) { graph.addComponent(comp); } - for (ProvidedInterface prov: getProvidedInterfaces()) { + + for (ProvidedInterface prov : getProvidedInterfaces()) { graph.addProvidedInterface(this, prov); } - graph.addEdgeFilter(_edgeFilter); + graph.addEdgeFilter(edgeFilter); + return graph; } private void stopAlreadyStartedComponents(List aStarted, - Scope aScope) { + Scope aScope) { // an exception occurred, stop the successfully started // components for (int i = aStarted.size() - 1; i >= 0; i--) { @@ -341,47 +408,53 @@ public class Container extends AbstractComponent { Component component = aStarted.get(i); aStarted.get(i).stop(aScope.getRuntime(component)); } catch (Throwable t) { - LOG.error(getQualifiedName() + ": error stopping " - + aStarted.get(i).getQualifiedName()); + LOG.error(getQualifiedName() + ": error stopping " + + aStarted.get(i).getQualifiedName()); } } } @Override protected void doStop(Scope aScope) { - for (int i = _components.size() - 1; i >= 0; i--) { - Component component = _components.get(i); + for (int i = components.size() - 1; i >= 0; i--) { + Component component = components.get(i); Object runtime = aScope.getRuntime(component); component.stop(runtime); } } private void checkSealed() { - if (_sealed) { + if (sealed) { throw new SystemAssemblyException("Container is sealed"); } } - + /** - * Finds a component based on the non-qualified name of the component. - * @param aName Component name. - * @return Component or null if not found. + * Finds a component based on the non-qualified name of the component. + * + * @param aName + * Component name. + * + * @return Component or null if not found. */ - public Component findComponent(String aName) { - for (Component component: _components) { - if ( component.getName().equals(aName)) { - return component; - } - } - return null; + public Component findComponent(String aName) { + for (Component component : components) { + if (component.getName().equals(aName)) { + return component; + } + } + + return null; } - - private static T findInterface(List aInterfaces, String aInterfaceName) { - for (T intf: aInterfaces) { - if ( intf.getName().equals(aInterfaceName)) { - return intf; - } - } - return null; + + private static T findInterface( + List aInterfaces, String aInterfaceName) { + for (T intf : aInterfaces) { + if (intf.getName().equals(aInterfaceName)) { + return intf; + } + } + + return null; } } diff --git a/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java b/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java index d2cf69fe..1bf835a8 100644 --- a/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java +++ b/system/general/src/main/java/org/wamblee/system/core/AbstractComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,51 +12,54 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - /** * Abstract subsystem class making it easy to implement new subsystems. + * */ public abstract class AbstractComponent implements Component { + private static final Log LOG = LogFactory.getLog(AbstractComponent.class); + + private ThreadLocal> remaining; + + private String context; + + private String name; + + private List provided; + + private List required; + + /** + * Constructs the subsystem. + * + * @param aName + * Name of the system. + * @param aProvided + * Provided services. + * @param aRequired + * Required services. + */ + protected AbstractComponent(String aName, + List aProvided, List aRequired) { + remaining = new ThreadLocal>(); + context = null; + name = aName; + provided = new ArrayList(aProvided); + required = new ArrayList(aRequired); + } - private static final Log LOG = LogFactory.getLog(AbstractComponent.class); - - private ThreadLocal> _remaining; - - private String _context; - private String _name; - private List _provided; - private List _required; - - /** - * Constructs the subsystem. - * - * @param aName - * Name of the system. - * @param aProvided - * Provided services. - * @param aRequired - * Required services. - */ - protected AbstractComponent(String aName, List aProvided, - List aRequired) { - _remaining = new ThreadLocal>(); - _context = null; - _name = aName; - _provided = new ArrayList(aProvided); - _required = new ArrayList(aRequired); - } - - /** + /** * Constructs the subsystem. * * @param aName @@ -67,147 +70,170 @@ public abstract class AbstractComponent implements Component { * Required services. */ protected AbstractComponent(String aName, ProvidedInterface[] aProvided, - RequiredInterface[] aRequired) { + RequiredInterface[] aRequired) { this(aName, Arrays.asList(aProvided), Arrays.asList(aRequired)); } - - protected AbstractComponent(String aName) { - this(aName, new ProvidedInterface[0], new RequiredInterface[0]); - } - - public AbstractComponent addProvidedInterface(ProvidedInterface aProvided) { - _provided.add(aProvided); - return this; - } - - public AbstractComponent addRequiredInterface(RequiredInterface aRequired) { - _required.add(aRequired); - return this; - } - - @Override - public final String getName() { - return _name; - } - - @Override - public void addContext(String aContext) { - if (_context == null) { - _context = aContext; - } else { - _context = aContext + "." + _context; - } - } - - @Override - public String getContext() { - return _context; - } - - @Override - public String getQualifiedName() { - if (_context == null) { - return getName(); - } - return _context + "." + getName(); - } - - @Override - public final List getProvidedInterfaces() { - return Collections.unmodifiableList(_provided); - } - - @Override - public final List getRequiredInterfaces() { - return Collections.unmodifiableList(_required); - } - - @Override - public final Type start(Scope aScope) { - LOG.info("Initialization starting '" + getQualifiedName() + "'"); - List oldRemaining = _remaining.get(); - _remaining.set(new ArrayList(getProvidedInterfaces())); - try { - Type runtime = doStart(aScope); - checkNotStartedInterfaces(); - LOG.info("Initialization finished '" + getQualifiedName() + "'"); - return runtime; - } finally { - _remaining.set(oldRemaining); - } - } - - private void checkNotStartedInterfaces() { - if (_remaining.get().size() > 0) { - String notProvided = ""; - for (ProvidedInterface provided : _remaining.get()) { - notProvided += "\nComponent " + getQualifiedName() - + " did not start interface " + provided; - } - throw new SystemAssemblyException(notProvided); - } - } - - /** - * Must be implemented for initializing the subsystem. The implementation - * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for each service that is started. - * - * @return Returns the runtime of the component. - */ - protected abstract Type doStart(Scope aScope); - - /** - * Implementations must call this method to indicate that a new service has - * been started. - * - * @param aDescriptor - * Provided interface. - * @param aService - * Implementation of the interface. - * @param aScope - * scope in which to publish the implementation. - */ - protected final void addInterface(ProvidedInterface aDescriptor, - Object aService, Scope aScope) { - LOG.info("Interface '" + getQualifiedName() + "." - + aDescriptor.getName() + "' started."); - if ( !_remaining.get().remove(aDescriptor) ) { - throw new SystemAssemblyException("Component '" + getQualifiedName() + "' started an unexpected interface '" + - aDescriptor + "' that was not registerd as a provided interface before"); - } - aScope.publishInterface(aDescriptor, aService); - } - - @Override - public void stop(Type aRuntime) { - LOG.info("Stopping initiated '" + getQualifiedName() + "'"); - doStop(aRuntime); - LOG.info("Stopping completed '" + getQualifiedName() + "'"); - } - - protected abstract void doStop(Type aRuntime); - - @Override - public String toString() { - return getQualifiedName(); - } - - public ProvidedInterface findProvidedInterface(String aName) { - for (ProvidedInterface provided: getProvidedInterfaces()) { - if ( provided.getName().equals(aName)) { - return provided; - } - } - return null; - } - - public RequiredInterface findRequiredInterface(String aName) { - for (RequiredInterface required: getRequiredInterfaces()) { - if ( required.getName().equals(aName)) { - return required; - } - } - return null; - } + /** + * Creates a new AbstractComponent object. + * + */ + protected AbstractComponent(String aName) { + this(aName, new ProvidedInterface[0], new RequiredInterface[0]); + } + + public AbstractComponent addProvidedInterface( + ProvidedInterface aProvided) { + provided.add(aProvided); + + return this; + } + + public AbstractComponent addRequiredInterface( + RequiredInterface aRequired) { + required.add(aRequired); + + return this; + } + + @Override + public final String getName() { + return name; + } + + @Override + public void addContext(String aContext) { + if (context == null) { + context = aContext; + } else { + context = aContext + "." + context; + } + } + + @Override + public String getContext() { + return context; + } + + @Override + public String getQualifiedName() { + if (context == null) { + return getName(); + } + + return context + "." + getName(); + } + + @Override + public final List getProvidedInterfaces() { + return Collections.unmodifiableList(provided); + } + + @Override + public final List getRequiredInterfaces() { + return Collections.unmodifiableList(required); + } + + @Override + public final Type start(Scope aScope) { + LOG.info("Initialization starting '" + getQualifiedName() + "'"); + + List oldRemaining = remaining.get(); + remaining + .set(new ArrayList(getProvidedInterfaces())); + + try { + Type runtime = doStart(aScope); + checkNotStartedInterfaces(); + LOG.info("Initialization finished '" + getQualifiedName() + "'"); + + return runtime; + } finally { + remaining.set(oldRemaining); + } + } + + private void checkNotStartedInterfaces() { + if (remaining.get().size() > 0) { + StringBuffer notProvided = new StringBuffer(); + + for (ProvidedInterface provided : remaining.get()) { + notProvided.append("\nComponent " + getQualifiedName() + + " did not start interface " + provided); + } + + throw new SystemAssemblyException(notProvided.toString()); + } + } + + /** + * Must be implemented for initializing the subsystem. The implementation + * must call {@link #addInterface(ProvidedInterface, Object, Scope)} for + * each service that is started. + * + * + * @return Returns the runtime of the component. + */ + protected abstract Type doStart(Scope aScope); + + /** + * Implementations must call this method to indicate that a new service has + * been started. + * + * @param aDescriptor + * Provided interface. + * @param aService + * Implementation of the interface. + * @param aScope + * scope in which to publish the implementation. + * + */ + protected final void addInterface(ProvidedInterface aDescriptor, + Object aService, Scope aScope) { + LOG.info("Interface '" + getQualifiedName() + "." + + aDescriptor.getName() + "' started."); + + if (!remaining.get().remove(aDescriptor)) { + throw new SystemAssemblyException("Component '" + + getQualifiedName() + "' started an unexpected interface '" + + aDescriptor + + "' that was not registerd as a provided interface before"); + } + + aScope.publishInterface(aDescriptor, aService); + } + + @Override + public void stop(Type aRuntime) { + LOG.info("Stopping initiated '" + getQualifiedName() + "'"); + doStop(aRuntime); + LOG.info("Stopping completed '" + getQualifiedName() + "'"); + } + + protected abstract void doStop(Type aRuntime); + + @Override + public String toString() { + return getQualifiedName(); + } + + public ProvidedInterface findProvidedInterface(String aName) { + for (ProvidedInterface provided : getProvidedInterfaces()) { + if (provided.getName().equals(aName)) { + return provided; + } + } + + return null; + } + + public RequiredInterface findRequiredInterface(String aName) { + for (RequiredInterface required : getRequiredInterfaces()) { + if (required.getName().equals(aName)) { + return required; + } + } + + return null; + } } diff --git a/system/general/src/main/java/org/wamblee/system/core/Component.java b/system/general/src/main/java/org/wamblee/system/core/Component.java index 9506bb1f..e3a45b69 100644 --- a/system/general/src/main/java/org/wamblee/system/core/Component.java +++ b/system/general/src/main/java/org/wamblee/system/core/Component.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,71 +18,81 @@ package org.wamblee.system.core; import java.util.List; /** - * A component represents a part of a system that requires a - * number of interfaces and provides a number of interfaces. + * A component represents a part of a system that requires a number of + * interfaces and provides a number of interfaces. + * + * The component interface provides the meta-data for a component. After calling + * {@link #start(Scope)}, an actual runtime representation of the component can + * be created which is independent of this component. As a special case, the + * runtime representation may be identical to the component instance but in + * general it is not. This allows a component to be used as a factory for + * creating objects. * - * The component interface provides the meta-data for a component. - * After calling {@link #start(Scope)}, an actual runtime representation of the - * component can be created which is independent of this component. - * As a special case, the runtime representation may be identical to the - * component instance but in general it is not. This allows a component to be - * used as a factory for creating objects. * - * * @author Erik Brakkee */ public interface Component { - - /** - * Gets the name of the subsystem. - * @return Subsystem name. - */ - String getName(); - - /** - * Prepends the context with a super context. - */ - void addContext(String aContext); - - /** - * Getst the context. - * @return Context or null if not set. - */ - String getContext(); - - /** - * Gets the fully qualified name of the component which includes - * the context of the component. - * This method can only be used after the component has started. - * @return Qualified name. - */ - String getQualifiedName(); + /** + * Gets the name of the subsystem. + * + * @return Subsystem name. + */ + String getName(); + + /** + * Prepends the context with a super context. + * + */ + void addContext(String aContext); + + /** + * Getst the context. + * + * @return Context or null if not set. + */ + String getContext(); + + /** + * Gets the fully qualified name of the component which includes the context + * of the component. This method can only be used after the component has + * started. + * + * @return Qualified name. + */ + String getQualifiedName(); + + /** + * Gets a description of the provided interfaces. + * + * @return Provided interfaces. + */ + List getProvidedInterfaces(); + + /** + * Gets a description of the required interfaces. + * + * @return Required interfaces. + */ + List getRequiredInterfaces(); - /** - * Gets a description of the provided interfaces. - * @return Provided interfaces. - */ - List getProvidedInterfaces(); - - /** - * Gets a description of the required interfaces. - * @return Required interfaces. - */ - List getRequiredInterfaces(); + /** + * Initialises the subsystem by starting all the services that it described + * as provided. + * + * @param aScope + * Scope with external interface implementations that are + * available. The component must publish its runtime and its + * provided interfaces in this scope. + * + * @return Gets an object representing the runtime of the component. + */ + Type start(Scope aScope); - - /** - * Initialises the subsystem by starting all the services that - * it described as provided. - * @param aScope Scope with external interface implementations that are available. The component - * must publish its runtime and its provided interfaces in this scope. - * @return Gets an object representing the runtime of the component. - */ - Type start(Scope aScope); - - /** - * Stops a component. - * @param aRuntime THe runtime part of the component. - */ - void stop(Type aRuntime); + /** + * Stops a component. + * + * @param aRuntime + * THe runtime part of the component. + */ + void stop(Type aRuntime); } diff --git a/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java b/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java index c7905673..b45a19dd 100644 --- a/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,88 +20,101 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; - /** * Default implementation of a service descriptor. - * + * * @author Erik Brakkee */ public class DefaultProvidedInterface implements ProvidedInterface { - - private String _name; - private Class[] _interfaces; - - /** - * Constructs the descriptor. - * @param aInterface Type of service. - */ - public DefaultProvidedInterface(String aName, Class aInterface) { - this(aName, new Class[] { aInterface }); - } - - public DefaultProvidedInterface(String aName, Class[] aInterfaces) { - _name = aName; - _interfaces = Arrays.copyOf(aInterfaces, aInterfaces.length); - } - - @Override - public String getName() { - return _name; - } - - @Override - public Class[] getInterfaceTypes() { - return _interfaces; - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(getName()); - buf.append(":"); - for (Class intf: _interfaces) { - buf.append(" " + intf.getName()); - } - return buf.toString(); - } - - @Override - public boolean equals(Object aObj) { - return this == aObj; - /* - if ( !(aObj instanceof DefaultProvidedInterface)) { - return false; - } - DefaultProvidedInterface provided = (DefaultProvidedInterface)aObj; - return getEqualsRepresentation().equals(provided.getEqualsRepresentation()); - */ - } - - @Override - public int hashCode() { - return getEqualsRepresentation().hashCode(); - } - - @Override - public boolean covers(ProvidedInterface aInterface) { - // TODO do more than just equals. - if ( !(aInterface instanceof DefaultProvidedInterface)) { - return false; - } - return getEqualsRepresentation().equals(((DefaultProvidedInterface)aInterface).getEqualsRepresentation()); - } - - - private String getEqualsRepresentation() { - List result = new ArrayList(); - for (Class cls: _interfaces) { - result.add(cls.getName()); - } - Collections.sort(result); - String value = ""; - for (String str: result) { - value += ":" + str; - } - return value; - } + private String name; + + private Class[] interfaces; + + /** + * Constructs the descriptor. + * + * @param aInterface + * Type of service. + */ + public DefaultProvidedInterface(String aName, Class aInterface) { + this(aName, new Class[] { aInterface }); + } + + /** + * Creates a new DefaultProvidedInterface object. + * + */ + public DefaultProvidedInterface(String aName, Class[] aInterfaces) { + name = aName; + interfaces = Arrays.copyOf(aInterfaces, aInterfaces.length); + } + + @Override + public String getName() { + return name; + } + + @Override + public Class[] getInterfaceTypes() { + return interfaces; + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append(getName()); + buf.append(":"); + + for (Class intf : interfaces) { + buf.append(" " + intf.getName()); + } + + return buf.toString(); + } + + @Override + public boolean equals(Object aObj) { + return this == aObj; + + /* + * if ( !(aObj instanceof DefaultProvidedInterface)) { return false; } + * DefaultProvidedInterface provided = (DefaultProvidedInterface)aObj; + * return + * getEqualsRepresentation().equals(provided.getEqualsRepresentation()); + */ + } + + @Override + public int hashCode() { + return getEqualsRepresentation().hashCode(); + } + + @Override + public boolean covers(ProvidedInterface aInterface) { + // TODO do more than just equals. + if (!(aInterface instanceof DefaultProvidedInterface)) { + return false; + } + + return getEqualsRepresentation().equals( + ((DefaultProvidedInterface) aInterface).getEqualsRepresentation()); + } + + private String getEqualsRepresentation() { + List result = new ArrayList(); + + for (Class cls : interfaces) { + result.add(cls.getName()); + } + + Collections.sort(result); + + StringBuffer value = new StringBuffer(); + + for (String str : result) { + value.append(":" + str); + } + + return value.toString(); + } } diff --git a/system/general/src/main/java/org/wamblee/system/core/DefaultRequiredInterface.java b/system/general/src/main/java/org/wamblee/system/core/DefaultRequiredInterface.java index 4e0db74b..b538a22a 100644 --- a/system/general/src/main/java/org/wamblee/system/core/DefaultRequiredInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/DefaultRequiredInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,128 +15,169 @@ */ package org.wamblee.system.core; -import java.util.Arrays; - import org.wamblee.reflection.ReflectionUtils; +import java.util.Arrays; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultRequiredInterface implements RequiredInterface { + private String name; + + private boolean optional; + + private Class[] required; + + private ProvidedInterface provider; + + /** + * Creates a new DefaultRequiredInterface object. + * + */ + public DefaultRequiredInterface(String aName, Class aInterface) { + this(aName, new Class[] { aInterface }); + } + + /** + * Creates a new DefaultRequiredInterface object. + * + */ + public DefaultRequiredInterface(String aName, Class[] aInterfaces) { + this(aName, aInterfaces, false); + } + + /** + * Creates a new DefaultRequiredInterface object. + * + */ + public DefaultRequiredInterface(String aName, Class aInterface, + boolean aIsOptional) { + this(aName, new Class[] { aInterface }, aIsOptional); + } + + /** + * Creates a new DefaultRequiredInterface object. + * + */ + public DefaultRequiredInterface(String aName, Class[] aInterfaces, + boolean aIsOptional) { + name = aName; + optional = aIsOptional; + required = aInterfaces; + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean isOptional() { + return optional; + } + + @Override + public boolean implementedBy(ProvidedInterface aDescriptor) { + Class[] provided = aDescriptor.getInterfaceTypes(); + + for (Class requiredIntf : required) { + if (!serviceProvided(requiredIntf, provided)) { + return false; + } + } + + // all required interfaces are provided. + return true; + } + + /** + * Check if the required interface is implemented by one of the provided + * interfaces. + * + * @param aRequired + * required interface + * @param aProvided + * Provided interfaces. + * + * @return + */ + private boolean serviceProvided(Class aRequired, Class[] aProvided) { + for (Class provided : aProvided) { + try { + provided = ReflectionUtils.wrapIfNeeded(provided); + aRequired = ReflectionUtils.wrapIfNeeded(aRequired); + provided.asSubclass(aRequired); + + return true; + } catch (ClassCastException e) { + // No match, try the next one. + } + } + + return false; + } + + @Override + public ProvidedInterface getProvider() { + return provider; + } + + @Override + public void setProvider(ProvidedInterface aProvider) { + assert aProvider != null; + assert implementedBy(aProvider); + provider = aProvider; + } + + @Override + public boolean equals(Object aObject) { + return this == aObject; + } + + @Override + public boolean covers(RequiredInterface aObject) { + // TODO do more than equals. + if (!(aObject instanceof DefaultRequiredInterface)) { + return false; + } + + DefaultRequiredInterface descr = (DefaultRequiredInterface) aObject; + + if (required.length != descr.required.length) { + return false; + } + + String[] interfaces1 = new String[required.length]; + String[] interfaces2 = new String[required.length]; + + for (int i = 0; i < required.length; i++) { + interfaces1[i] = required[i].getName(); + interfaces2[i] = descr.required[i].getName(); + } + + Arrays.sort(interfaces1); + Arrays.sort(interfaces2); + + return Arrays.equals(interfaces1, interfaces2); + } + + @Override + public int hashCode() { + return Arrays.hashCode(required); + } + + @Override + public String toString() { + StringBuffer buf = new StringBuffer(); + buf.append("." + getName() + ":"); + + for (Class intf : required) { + buf.append("." + intf.getName()); + } - private String _name; - private boolean _optional; - private Class[] _required; - private ProvidedInterface _provider; - - public DefaultRequiredInterface(String aName, Class aInterface) { - this(aName, new Class[] { aInterface }); - } - - public DefaultRequiredInterface(String aName, Class[] aInterfaces) { - this(aName, aInterfaces, false); - } - - public DefaultRequiredInterface(String aName, Class aInterface, boolean aIsOptional) { - this(aName, new Class[] { aInterface }, aIsOptional ); - } - - - public DefaultRequiredInterface(String aName, Class[] aInterfaces, boolean aIsOptional) { - _name = aName; - _optional = aIsOptional; - _required = aInterfaces; - } - - @Override - public String getName() { - return _name; - } - - @Override - public boolean isOptional() { - return _optional; - } - - @Override - public boolean implementedBy(ProvidedInterface aDescriptor) { - Class[] provided = aDescriptor.getInterfaceTypes(); - for (Class required : _required) { - if ( !serviceProvided(required, provided)) { - return false; - } - } - // all required interfaces are provided. - return true; - } - - /** - * Check if the required interface is implemented by one of the provided interfaces. - * @param aRequired required interface - * @param aProvided Provided interfaces. - * @return - */ - private boolean serviceProvided(Class aRequired, Class[] aProvided) { - for (Class provided: aProvided) { - try { - provided = ReflectionUtils.wrapIfNeeded(provided); - aRequired = ReflectionUtils.wrapIfNeeded(aRequired); - provided.asSubclass(aRequired); - return true; - } catch (ClassCastException e) { - // No match, try the next one. - } - } - return false; - } - - @Override - public ProvidedInterface getProvider() { - return _provider; - } - - @Override - public void setProvider(ProvidedInterface aProvider) { - assert aProvider != null; - assert implementedBy(aProvider); - _provider = aProvider; - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - - @Override - public boolean covers(RequiredInterface obj) { - // TODO do more than equals. - if ( !(obj instanceof DefaultRequiredInterface)) { - return false; - } - DefaultRequiredInterface descr = (DefaultRequiredInterface)obj; - if ( _required.length != descr._required.length ) { - return false; - } - String[] interfaces1 = new String[_required.length]; - String[] interfaces2 = new String[_required.length]; - for (int i = 0; i < _required.length; i++) { - interfaces1[i] = _required[i].getName(); - interfaces2[i] = descr._required[i].getName(); - } - Arrays.sort(interfaces1); - Arrays.sort(interfaces2); - return Arrays.equals(interfaces1, interfaces2); - } - - @Override - public int hashCode() { - return _required.hashCode(); - } - - @Override - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append("." + getName() + ":"); - for (Class intf: _required) { - buf.append("." + intf.getName()); - } - return buf.toString(); - } + return buf.toString(); + } } diff --git a/system/general/src/main/java/org/wamblee/system/core/DefaultScope.java b/system/general/src/main/java/org/wamblee/system/core/DefaultScope.java index 50c6cc3b..e0de6790 100644 --- a/system/general/src/main/java/org/wamblee/system/core/DefaultScope.java +++ b/system/general/src/main/java/org/wamblee/system/core/DefaultScope.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; import java.util.ArrayList; @@ -22,90 +22,118 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultScope implements Scope { + private List parents; + + private Map properties; + + private Map runtimes; + + private Map provided; + + private List externallyProvided; + + /** + * Creates a new DefaultScope object. + * + */ + public DefaultScope(List aExternallyProvided) { + this(aExternallyProvided.toArray(new ProvidedInterface[0])); + } + + /** + * Creates a new DefaultScope object. + * + */ + public DefaultScope(ProvidedInterface[] aExternallyProvided) { + this(aExternallyProvided, new ArrayList()); + } + + /** + * Creates a new DefaultScope object. + * + */ + public DefaultScope(ProvidedInterface[] aExternallyProvided, Scope aParent) { + this(aExternallyProvided, Arrays.asList(new Scope[] { aParent })); + } + + /** + * Creates a new DefaultScope object. + * + */ + public DefaultScope(ProvidedInterface[] aExternallyProvided, + List aParent) { + parents = new ArrayList(aParent); + properties = new HashMap(); + runtimes = new HashMap(); + provided = new HashMap(); + externallyProvided = new ArrayList(); + externallyProvided.addAll(Arrays.asList(aExternallyProvided)); + } + + @Override + public List getProvidedInterfaces() { + return Collections.unmodifiableList(externallyProvided); + } + + @Override + public Object get(String aKey) { + return properties.get(aKey); + } + + @Override + public void put(String aKey, Object aValue) { + properties.put(aKey, aValue); + } + + @Override + public void addRuntime(Component aComponent, Object aRuntime) { + runtimes.put(aComponent.getName(), aRuntime); + } + + @Override + public Object getRuntime(Component aComponent) { + return runtimes.get(aComponent.getName()); + } + + @Override + public Object getRuntime(String aName) { + return runtimes.get(aName); + } + + @Override + synchronized public void publishInterface(ProvidedInterface aInterface, + Object aImplementation) { + provided.put(aInterface, new ProvidedInterfaceImplementation( + aInterface, aImplementation)); + } + + @Override + public T getInterfaceImplementation(ProvidedInterface aInterface, + Class aType) { + if (aInterface == null) { + return null; + } + + ProvidedInterfaceImplementation providedIntf = provided.get(aInterface); + + if (providedIntf == null) { + for (Scope parent : parents) { + T impl = parent.getInterfaceImplementation(aInterface, aType); + + if (impl != null) { + return impl; + } + } - private List _parents; - private Map _properties; - private Map _runtimes; - private Map _provided; - private List _externallyProvided; - - public DefaultScope(ListaExternallyProvided) { - this(aExternallyProvided.toArray(new ProvidedInterface[0])); - } - - public DefaultScope(ProvidedInterface[] aExternallyProvided) { - this(aExternallyProvided, new ArrayList()); - } - - public DefaultScope(ProvidedInterface[] aExternallyProvided, Scope aParent) { - this(aExternallyProvided, Arrays.asList(new Scope[] { aParent })); - } - - public DefaultScope(ProvidedInterface[] aExternallyProvided, - List aParent) { - _parents = new ArrayList(aParent); - _properties = new HashMap(); - _runtimes = new HashMap(); - _provided = new HashMap(); - _externallyProvided = new ArrayList(); - _externallyProvided.addAll(Arrays.asList(aExternallyProvided)); - } - - @Override - public List getProvidedInterfaces() { - return Collections.unmodifiableList(_externallyProvided); - } - - @Override - public Object get(String aKey) { - return _properties.get(aKey); - } - - @Override - public void put(String aKey, Object aValue) { - _properties.put(aKey, aValue); - } - - @Override - public void addRuntime(Component aComponent, Object aRuntime) { - _runtimes.put(aComponent.getName(), aRuntime); - } - - @Override - public Object getRuntime(Component aComponent) { - return _runtimes.get(aComponent.getName()); - } - - @Override - public Object getRuntime(String aName) { - return _runtimes.get(aName); - } - - @Override - synchronized public void publishInterface(ProvidedInterface aInterface, - Object aImplementation) { - _provided.put(aInterface, new ProvidedInterfaceImplementation(aInterface, - aImplementation)); - } - - @Override - public T getInterfaceImplementation(ProvidedInterface aInterface, - Class aType) { - if ( aInterface == null ) { - return null; - } - ProvidedInterfaceImplementation provided = _provided.get(aInterface); - if (provided == null) { - for (Scope parent : _parents) { - T impl = parent.getInterfaceImplementation(aInterface, aType); - if ( impl != null ) { - return impl; - } - } - return null; - } else { - return provided.getImplementation(aType); - } - } + return null; + } else { + return providedIntf.getImplementation(aType); + } + } } diff --git a/system/general/src/main/java/org/wamblee/system/core/NamedInterface.java b/system/general/src/main/java/org/wamblee/system/core/NamedInterface.java index 9800621e..f71e004c 100644 --- a/system/general/src/main/java/org/wamblee/system/core/NamedInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/NamedInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,15 @@ */ package org.wamblee.system.core; +/** + * + * @author $author$ + * @version $Revision: 1.6 $ + */ public interface NamedInterface { /** - * Name for the interface. + * Name for the interface. + * */ String getName(); } diff --git a/system/general/src/main/java/org/wamblee/system/core/ProvidedInterface.java b/system/general/src/main/java/org/wamblee/system/core/ProvidedInterface.java index f09a5270..86875115 100644 --- a/system/general/src/main/java/org/wamblee/system/core/ProvidedInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/ProvidedInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,25 +18,29 @@ package org.wamblee.system.core; import java.util.Collection; /** - * Represents an interface provided by a component. - * Different component objects should never share ProvidedInterface instances! - * + * Represents an interface provided by a component. Different component objects + * should never share ProvidedInterface instances! + * * @author Erik Brakkee */ public interface ProvidedInterface extends NamedInterface { - - /** - * Returns the service type. - * @return Service type. - */ - Class[] getInterfaceTypes(); - - - /** - * Determines whether the current provided interface exceeds the given provided interface. - * In other words if it can provide at least what the given provided interface can provide. - * @param aInterface Interface to compare to. - * @return True if the current interface exceeds the given provided interface. - */ - boolean covers(ProvidedInterface aInterface); + /** + * Returns the service type. + * + * @return Service type. + */ + Class[] getInterfaceTypes(); + + /** + * Determines whether the current provided interface exceeds the given + * provided interface. In other words if it can provide at least what the + * given provided interface can provide. + * + * @param aInterface + * Interface to compare to. + * + * @return True if the current interface exceeds the given provided + * interface. + */ + boolean covers(ProvidedInterface aInterface); } diff --git a/system/general/src/main/java/org/wamblee/system/core/ProvidedInterfaceImplementation.java b/system/general/src/main/java/org/wamblee/system/core/ProvidedInterfaceImplementation.java index abeb70d5..61c80c7a 100644 --- a/system/general/src/main/java/org/wamblee/system/core/ProvidedInterfaceImplementation.java +++ b/system/general/src/main/java/org/wamblee/system/core/ProvidedInterfaceImplementation.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,38 +16,47 @@ package org.wamblee.system.core; /** - * Represents a provided interface together with its implementation. + * Represents a provided interface together with its implementation. * * @author Erik Brakkee */ class ProvidedInterfaceImplementation { + private ProvidedInterface provided; - private ProvidedInterface _provided; - private Object _implementation; - - /** - * Constructs the object. - * @param aProvided Provided interface. - * @param aImplementation Implementation. - */ - public ProvidedInterfaceImplementation(ProvidedInterface aProvided, Object aImplementation) { - _provided = aProvided; - _implementation = aImplementation; - } + private Object implementation; - /** - * @return The provided interface. - */ - public ProvidedInterface getProvided() { - return _provided; - } - - /** - * @param Expected type of the implementation. - * @param aType Type of the implementation. - * @return Implementation. - */ - public T getImplementation(Class aType) { - return (T)_implementation; - } + /** + * Constructs the object. + * + * @param aProvided + * Provided interface. + * @param aImplementation + * Implementation. + */ + public ProvidedInterfaceImplementation(ProvidedInterface aProvided, + Object aImplementation) { + provided = aProvided; + implementation = aImplementation; + } + + /** + * + * @return The provided interface. + */ + public ProvidedInterface getProvided() { + return provided; + } + + /** + * + * @param + * Expected type of the implementation. + * @param aType + * Type of the implementation. + * + * @return Implementation. + */ + public T getImplementation(Class aType) { + return (T) implementation; + } } diff --git a/system/general/src/main/java/org/wamblee/system/core/RequiredInterface.java b/system/general/src/main/java/org/wamblee/system/core/RequiredInterface.java index 4dd77fc7..bd61469e 100644 --- a/system/general/src/main/java/org/wamblee/system/core/RequiredInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/RequiredInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,36 +15,48 @@ */ package org.wamblee.system.core; +/** + * + * @author $author$ + * @version $Revision: 1.6 $ + */ public interface RequiredInterface extends NamedInterface { - - /** - * @return True iff the required interface is optional. - */ - boolean isOptional(); - - - /** - * Checks if the service is provided by a given provided interface. - * @param aInterface Provided interface. - * @return - */ - boolean implementedBy(ProvidedInterface aInterface); - - /** - * Sets the provider of this interface. - * @param aProvider Provider. - */ - void setProvider(ProvidedInterface aProvider); - - /** - * Gets the provider interface. - * @return Provider or null if not set. - */ - ProvidedInterface getProvider(); - - /** - * Determines if the requirements of the current interface are at least those - * of the given required interface. - */ - boolean covers(RequiredInterface aInterface); + /** + * + * @return True iff the required interface is optional. + */ + boolean isOptional(); + + /** + * Checks if the service is provided by a given provided interface. + * + * @param aInterface + * Provided interface. + * + * @return + */ + boolean implementedBy(ProvidedInterface aInterface); + + /** + * Sets the provider of this interface. + * + * @param aProvider + * Provider. + */ + void setProvider(ProvidedInterface aProvider); + + /** + * Gets the provider interface. + * + * @return Provider or null if not set. + */ + ProvidedInterface getProvider(); + + /** + * Determines if the requirements of the current interface are at least + * those of the given required interface. + * + * + */ + boolean covers(RequiredInterface aInterface); } diff --git a/system/general/src/main/java/org/wamblee/system/core/Scope.java b/system/general/src/main/java/org/wamblee/system/core/Scope.java index fe83e857..25c52e4d 100644 --- a/system/general/src/main/java/org/wamblee/system/core/Scope.java +++ b/system/general/src/main/java/org/wamblee/system/core/Scope.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,69 +18,79 @@ package org.wamblee.system.core; import java.util.List; /** - * A scope represents a set of running services and the runtime information for the - * started components and is (usually) the result of - * starting a container. + * A scope represents a set of running services and the runtime information for + * the started components and is (usually) the result of starting a container. * * @author Erik Brakkee */ public interface Scope { - - /** - * Gets the provided interfaces by this scope. - * @return Provided interfaces. - */ - List getProvidedInterfaces(); - - /** - * Adds a key value pair to the scope. - * @param aKey Key - * @param aValue Value. - */ - void put(String aKey, Object aValue); - - /** - * Retrieves a value for the key. - * @param aKey Key. - * @return Value. - */ - Object get(String aKey); - - /** - * Adds the runtime of a started component. - * @param aComponent Component. - * @param aRuntime Runtime. - */ - void addRuntime(Component aComponent, Object aRuntime); - - /** - * Publishes an implementation of a provided interface. - * @param aInterface Interface that is provided. - * @param aImplementation Implementation of the interface. - */ - void publishInterface(ProvidedInterface aInterface, Object aImplementation); - - /** - * Retrieves an implementation of a provided interface. - * @param aProvided P - * rovided interface. If it is null then null is returned. - * @param aType Type of implementation that is expected. - * @return Retrieved interface. - */ - T getInterfaceImplementation(ProvidedInterface aProvided, Class aType ); + /** + * Gets the provided interfaces by this scope. + * + * @return Provided interfaces. + */ + List getProvidedInterfaces(); - /** - * Gets the runtime for a component. - * @param aComponent Component for which we want to get the runtime. - * @return Runtime. - */ - Object getRuntime(Component aComponent); - - /** - * Gets the runtime for a component based on the name of the component - * (excluding its context). - * @param aName Component name. - * @return Component name. - */ - Object getRuntime(String aName); + /** + * Adds a key value pair to the scope. + * + * @param aKey + * Key + * @param aValue + * Value. + */ + void put(String aKey, Object aValue); + + /** + * Retrieves a value for the key. + * + * @param aKey + * Key. + * + * @return Value. + */ + Object get(String aKey); + + /** + * Adds the runtime of a started component. + * + * @param aComponent + * Component. + * @param aRuntime + * Runtime. + */ + void addRuntime(Component aComponent, Object aRuntime); + + /** + * Publishes an implementation of a provided interface. + * + * @param aInterface + * Interface that is provided. + * @param aImplementation + * Implementation of the interface. + */ + void publishInterface(ProvidedInterface aInterface, Object aImplementation); + + T getInterfaceImplementation(ProvidedInterface aProvided, Class aType); + + /** + * Gets the runtime for a component. + * + * @param aComponent + * Component for which we want to get the runtime. + * + * @return Runtime. + */ + Object getRuntime(Component aComponent); + + /** + * Gets the runtime for a component based on the name of the component + * (excluding its context). + * + * @param aName + * Component name. + * + * @return Component name. + */ + Object getRuntime(String aName); } diff --git a/system/general/src/main/java/org/wamblee/system/core/SystemAssemblyException.java b/system/general/src/main/java/org/wamblee/system/core/SystemAssemblyException.java index a8a0ac16..054edf87 100644 --- a/system/general/src/main/java/org/wamblee/system/core/SystemAssemblyException.java +++ b/system/general/src/main/java/org/wamblee/system/core/SystemAssemblyException.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,25 +17,29 @@ package org.wamblee.system.core; /** * Exception thrown when an error occurs in assembling the systems. - * + * * @author Erik Brakkee */ public class SystemAssemblyException extends RuntimeException { + /** + * Constructs the exception. + * + * @param aMsg + * Message. + */ + public SystemAssemblyException(String aMsg) { + super(aMsg); + } - /** - * Constructs the exception. - * @param aMsg Message. - */ - public SystemAssemblyException(String aMsg) { - super(aMsg); - } - - /** - * Constructs the exception. - * @param aMsg Message - * @param aCause Cause. - */ - public SystemAssemblyException(String aMsg, Throwable aCause) { - super(aMsg, aCause); - } + /** + * Constructs the exception. + * + * @param aMsg + * Message + * @param aCause + * Cause. + */ + public SystemAssemblyException(String aMsg, Throwable aCause) { + super(aMsg, aCause); + } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/CompositeEdgeFilter.java b/system/general/src/main/java/org/wamblee/system/graph/CompositeEdgeFilter.java index 692c881f..effec0c0 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/CompositeEdgeFilter.java +++ b/system/general/src/main/java/org/wamblee/system/graph/CompositeEdgeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,26 +18,33 @@ package org.wamblee.system.graph; import java.util.ArrayList; import java.util.List; +/** + * + * @author $author$ + * @version $Revision$ + */ public class CompositeEdgeFilter implements EdgeFilter { - - private List _filters; - - public CompositeEdgeFilter() { - _filters = new ArrayList(); + private List filters; + + /** + * Creates a new CompositeEdgeFilter object. + */ + public CompositeEdgeFilter() { + filters = new ArrayList(); } - - public void add(EdgeFilter aFilter) { - _filters.add(aFilter); + + public void add(EdgeFilter aFilter) { + filters.add(aFilter); } @Override public boolean isViolated(Edge aEdge) { - for (EdgeFilter filter: _filters) { - if ( filter.isViolated(aEdge) ) { - return true; + for (EdgeFilter filter : filters) { + if (filter.isViolated(aEdge)) { + return true; } } - return false; - } + return false; + } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java b/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java index 35d648ff..48fea512 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java +++ b/system/general/src/main/java/org/wamblee/system/graph/DefaultEdge.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,35 +16,37 @@ package org.wamblee.system.graph; /** - * Represents an application-independent edge of a graph. - * Applications might choose to implement the Edge interface - * directly. + * Represents an application-independent edge of a graph. Applications might + * choose to implement the Edge interface directly. * * @author Erik Brakkee */ public class DefaultEdge implements Edge { - - private Node _from; - private Node _to; - - public DefaultEdge(Node aFrom, Node aTo) { - _from = aFrom; - _to = aTo; + private Node from; + + private Node to; + + /** + * Creates a new DefaultEdge object. + * + */ + public DefaultEdge(Node aFrom, Node aTo) { + from = aFrom; + to = aTo; } @Override public Node getFrom() { - return _from; + return from; } @Override public Node getTo() { - return _to; + return to; } - + @Override public String toString() { - return "Edge(" + _from.getName() + ", " + _to.getName() + ")"; + return "Edge(" + from.getName() + ", " + to.getName() + ")"; } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java b/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java index 925c08c1..86fda267 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/DefaultNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,42 +16,46 @@ package org.wamblee.system.graph; /** - * Default application-independent node. Specific applications of the graph might - * implement the Node interface directly. + * Default application-independent node. Specific applications of the graph + * might implement the Node interface directly. + * * @author Erik Brakkee - * */ public class DefaultNode implements Node { - - private String _name; - + private String name; + /** - * Constructs the node. - * @param aName Node name. + * Constructs the node. + * + * @param aName + * Node name. */ - public DefaultNode(String aName) { - _name = aName; + public DefaultNode(String aName) { + name = aName; } /** - * Returns the node name. + * Returns the node name. + * */ @Override public String getName() { - return _name; + return name; } @Override public boolean equals(Object aObj) { - if ( !(aObj instanceof Node)) { - return false; + if (!(aObj instanceof Node)) { + return false; } - Node node = (Node)aObj; - return _name.equals(node.getName()); + + Node node = (Node) aObj; + + return name.equals(node.getName()); } - + @Override public int hashCode() { - return _name.hashCode(); + return name.hashCode(); } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/Edge.java b/system/general/src/main/java/org/wamblee/system/graph/Edge.java index a340015a..1ea905d2 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/Edge.java +++ b/system/general/src/main/java/org/wamblee/system/graph/Edge.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +16,22 @@ package org.wamblee.system.graph; /** - * Represents an edge of a graph. + * Represents an edge of a graph. * * @author Erik Brakkee */ public interface Edge { - /** - * @return The from part of the edge. + * + * + * @return The from part of the edge. */ Node getFrom(); - + /** - * @return The to part of the edge. + * + * + * @return The to part of the edge. */ Node getTo(); } diff --git a/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java b/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java index 4ac39f6f..6a76e8fc 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java +++ b/system/general/src/main/java/org/wamblee/system/graph/EdgeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,17 +18,22 @@ package org.wamblee.system.graph; import java.util.List; /** - * Edge factory used to extend a graph with new edges. + * Edge factory used to extend a graph with new edges. + * * @author Erik Brakkee - * - * @param Type of node. + * + * @param + * Type of node. */ public interface EdgeFactory { /** - * Computes a number of new edges to be added to the graph. - * @param aFrom From node. - * @param aTo To node. - * @return List of edges from the from to the to node. + * Computes a number of new edges to be added to the graph. + * + * @param aFrom + * From node. + * @param aTo + * To node. + * @return List of edges from the from to the to node. */ - List create(NodeType aFrom, NodeType aTo); + List create(NodeType aFrom, NodeType aTo); } diff --git a/system/general/src/main/java/org/wamblee/system/graph/EdgeFilter.java b/system/general/src/main/java/org/wamblee/system/graph/EdgeFilter.java index b372f082..d19977f8 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/EdgeFilter.java +++ b/system/general/src/main/java/org/wamblee/system/graph/EdgeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,11 @@ */ package org.wamblee.system.graph; +/** + * + * @author $author$ + * @version $Revision: 1.6 $ + */ public interface EdgeFilter { - - boolean isViolated(Edge aEdge); + boolean isViolated(Edge aEdge); } diff --git a/system/general/src/main/java/org/wamblee/system/graph/EdgeSelector.java b/system/general/src/main/java/org/wamblee/system/graph/EdgeSelector.java index c49f82c1..b403c897 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/EdgeSelector.java +++ b/system/general/src/main/java/org/wamblee/system/graph/EdgeSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,23 +15,35 @@ */ package org.wamblee.system.graph; +/** + * + * @author $author$ + * @version $Revision$ + * + */ public class EdgeSelector { - - public static interface Selector { - void execute(FromType aFrom, ToType aTo); - } - - private Class _fromType; - private Class _toType; - + private Class fromType; + + private Class toType; + + /** + * Creates a new EdgeSelector object. + * + */ public EdgeSelector(Class aFrom, Class aTo) { - _fromType = aFrom; - _toType = aTo; + fromType = aFrom; + toType = aTo; + } + + public void execute(Selector aSelector, Edge aEdge) { + if (fromType.isInstance(aEdge.getFrom()) && + toType.isInstance(aEdge.getTo())) { + aSelector.execute((FromType) aEdge.getFrom(), (ToType) aEdge + .getTo()); + } } - public void execute(Selector aSelector, Edge aEdge) { - if ( _fromType.isInstance(aEdge.getFrom()) && _toType.isInstance(aEdge.getTo())) { - aSelector.execute((FromType)aEdge.getFrom(), (ToType)aEdge.getTo()); - } + public static interface Selector { + void execute(FromType aFrom, ToType aTo); } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/Graph.java b/system/general/src/main/java/org/wamblee/system/graph/Graph.java index 0e4f6ccb..1fe3fcfd 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/Graph.java +++ b/system/general/src/main/java/org/wamblee/system/graph/Graph.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph; import java.util.ArrayList; @@ -25,16 +25,16 @@ import java.util.List; * @author Erik Brakkee */ public class Graph { + private List nodes; - private List _nodes; - private List _edges; + private List edges; /** * Constructs the graph. */ public Graph() { - _nodes = new ArrayList(); - _edges = new ArrayList(); + nodes = new ArrayList(); + edges = new ArrayList(); } /** @@ -42,16 +42,18 @@ public class Graph { * * @param aNode * Node to add. + * * @throws IllegalArgumentException * In case the node already exists. Node equality is checked * using equals. */ public void addNode(Node aNode) { - if (_nodes.contains(aNode)) { - throw new IllegalArgumentException("Node '" + aNode.getName() - + "' already exists"); + if (nodes.contains(aNode)) { + throw new IllegalArgumentException("Node '" + aNode.getName() + + "' already exists"); } - _nodes.add(aNode); + + nodes.add(aNode); } /** @@ -59,14 +61,16 @@ public class Graph { * * @param aName * Node name. + * * @return Node or null if not found. */ public Node findNode(String aName) { - for (Node node : _nodes) { + for (Node node : nodes) { if (node.getName().equals(aName)) { return node; } } + return null; } @@ -75,17 +79,20 @@ public class Graph { * * @param aNode * Node to remove. + * * @return True iff the node was removed. + * * @throws IllegalArgumentException * In case there are edges of which the node is a part. */ public boolean removeNode(Node aNode) { if (!findOutgoing(aNode).isEmpty() || !findIncoming(aNode).isEmpty()) { - throw new IllegalArgumentException("Cannot remove node '" - + aNode.getName() - + "' because it is connected to one or more edges"); + throw new IllegalArgumentException("Cannot remove node '" + + aNode.getName() + + "' because it is connected to one or more edges"); } - return _nodes.remove(aNode); + + return nodes.remove(aNode); } /** @@ -107,39 +114,48 @@ public class Graph { * * @param aEdge * Edge to add. + * * @throws IllegalArgumentException * In case one of the nodes of the edges is not part of the * graph or if the same edge (as determined by * {@link #equals(Object)} is already a part of the graph. */ public void addEdge(Edge aEdge) { - if (_edges.contains(aEdge)) { - throw new IllegalArgumentException("Edge '" + aEdge - + "' already exists"); + if (edges.contains(aEdge)) { + throw new IllegalArgumentException("Edge '" + aEdge + + "' already exists"); } - if (!_nodes.contains(aEdge.getFrom())) { - throw new IllegalArgumentException("From node '" + aEdge.getFrom() - + "' from edge '" + aEdge + "' is not part of the graph"); + + if (!nodes.contains(aEdge.getFrom())) { + throw new IllegalArgumentException("From node '" + aEdge.getFrom() + + "' from edge '" + aEdge + "' is not part of the graph"); } - if (!_nodes.contains(aEdge.getTo())) { - throw new IllegalArgumentException("To node '" + aEdge.getTo() - + "' from edge '" + aEdge + "' is not part of the graph"); + + if (!nodes.contains(aEdge.getTo())) { + throw new IllegalArgumentException("To node '" + aEdge.getTo() + + "' from edge '" + aEdge + "' is not part of the graph"); } - _edges.add(aEdge); + + edges.add(aEdge); } /** - * Removes an edge. - * @param aEdge Edge to remove. - * @return True if the edge was removed. + * Removes an edge. + * + * @param aEdge + * Edge to remove. + * + * @return True if the edge was removed. */ public boolean removeEdge(Edge aEdge) { - return _edges.remove(aEdge); + return edges.remove(aEdge); } /** - * Adds a number of edges. - * @param aEdges Edges to add. + * Adds a number of edges. + * + * @param aEdges + * Edges to add. */ public void addEdges(List aEdges) { for (Edge edge : aEdges) { @@ -148,94 +164,114 @@ public class Graph { } /** - * Gets the nodes. - * @return Copy of the list of nodes of the graph. + * Gets the nodes. + * + * @return Copy of the list of nodes of the graph. */ public List getNodes() { - return new ArrayList(_nodes); + return new ArrayList(nodes); } /** - * Gets the edges. - * @return Copy of the list of edges of the graph. + * Gets the edges. + * + * @return Copy of the list of edges of the graph. */ public List getEdges() { - return new ArrayList(_edges); + return new ArrayList(edges); } /** - * Extends the graph with edges using an edge factory. All combinations of - * nodes are passed to the factory which creates additional edges. - * @param aFactory Edge factory. + * Extends the graph with edges using an edge factory. All combinations of + * nodes are passed to the factory which creates additional edges. + * + * @param aFactory + * Edge factory. */ public void extend(EdgeFactory aFactory) { - for (Node from : _nodes) { - for (Node to : _nodes) { - _edges.addAll(aFactory.create(from, to)); + for (Node from : nodes) { + for (Node to : nodes) { + edges.addAll(aFactory.create(from, to)); } } } - + /** - * Applies a filter to the graph for removing elements. - * @param aFilter Filter to apply. + * Applies a filter to the graph for removing elements. + * + * @param aFilter + * Filter to apply. */ public void applyFilter(EdgeFilter aFilter) { - for (Iterator edge = _edges.iterator(); edge.hasNext(); ) { - if (aFilter.isViolated(edge.next())) { + for (Iterator edge = edges.iterator(); edge.hasNext();) { + if (aFilter.isViolated(edge.next())) { edge.remove(); } } } /** - * Finds all outgoing edges of a node. More specifically, finds - * all edges e for which e.getFrom().getName() = aNode.getName(). - * @param aNode Node for which to find outgoing edges. - * @return List of outgoing edges. + * Finds all outgoing edges of a node. More specifically, finds all edges + * e for which e.getFrom().getName() = + * aNode.getName(). + * + * @param aNode + * Node for which to find outgoing edges. + * + * @return List of outgoing edges. */ public List findOutgoing(Node aNode) { List result = new ArrayList(); - for (Edge edge : _edges) { + + for (Edge edge : edges) { if (edge.getFrom().getName().equals(aNode.getName())) { result.add(edge); } } + return result; } /** - * Finds all incoming edges of a node. - * More specifically, finds - * all edges e for which e.getTo().getName() = aNode.getName(). - * @param aNode Node for which to find incoming edges. - * @return List of incoming edges. + * Finds all incoming edges of a node. More specifically, finds all edges + * e for which e.getTo().getName() = + * aNode.getName(). + * + * @param aNode + * Node for which to find incoming edges. + * + * @return List of incoming edges. */ public List findIncoming(Node aNode) { List result = new ArrayList(); - for (Edge edge : _edges) { + + for (Edge edge : edges) { if (edge.getTo().getName().equals(aNode.getName())) { result.add(edge); } } + return result; } /** - * Implements a visitor design pattern. - * This loops over all nodes and all edges and invokes the appropriate visit - * methods on the visitor. - * @param aVisitor Visitor. + * Implements a visitor design pattern. This loops over all nodes and all + * edges and invokes the appropriate visit methods on the visitor. + * + * @param aVisitor + * Visitor. */ public void accept(Visitor aVisitor) { List nodes = getNodes(); // copy to make sure the visitor can // modify the // list of nodes as part of the loop. + List edges = getEdges(); // copy ..... (see above). for (Node node : nodes) { aVisitor.visitNode(node); } + for (Edge edge : edges) { aVisitor.visitEdge(edge); } diff --git a/system/general/src/main/java/org/wamblee/system/graph/Node.java b/system/general/src/main/java/org/wamblee/system/graph/Node.java index d1df3c03..754e8010 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/Node.java +++ b/system/general/src/main/java/org/wamblee/system/graph/Node.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,15 +16,15 @@ package org.wamblee.system.graph; /** - * Represents a node in a graph. + * Represents a node in a graph. + * * @author Erik Brakkee */ public interface Node { - /** - * Gets the node name uniquely identifying the node in the graph. - * @return Node name. + * Gets the node name uniquely identifying the node in the graph. + * + * @return Node name. */ String getName(); - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/Visitor.java b/system/general/src/main/java/org/wamblee/system/graph/Visitor.java index e65a535c..1db6ef13 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/Visitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/Visitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,21 +16,25 @@ package org.wamblee.system.graph; /** - * Visitor of a graph. + * Visitor of a graph. + * * @author Erik Brakkee. - * + * */ public interface Visitor { - /** * Visits a node. Called by {@link Graph#accept(Visitor)}. - * @param aNode Node to visit. + * + * @param aNode + * Node to visit. */ - void visitNode(Node aNode); - + void visitNode(Node aNode); + /** * Visits a node. Called by {@link Graph#accept(Visitor)}. - * @param aEdge Edge to visit. + * + * @param aEdge + * Edge to visit. */ - void visitEdge(Edge aEdge); + void visitEdge(Edge aEdge); } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyProvidedVisitor.java b/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyProvidedVisitor.java index c921630b..b68c6003 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyProvidedVisitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyProvidedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,31 +15,31 @@ */ package org.wamblee.system.graph.component; -import java.util.List; - import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.Graph; import org.wamblee.system.graph.Node; import org.wamblee.system.graph.Visitor; +import java.util.List; + /** - * Visitor that checks whether all externally provided interfaces are actually provided - * by any of the internal components. + * Visitor that checks whether all externally provided interfaces are actually + * provided by any of the internal components. * * @author Erik Brakkee - * */ public class CheckExternallyProvidedVisitor implements Visitor { - - private Graph _graph; + private Graph graph; /** - * Constructs the visitor. - * @param aGraph Component graph. + * Constructs the visitor. + * + * @param aGraph + * Component graph. */ - public CheckExternallyProvidedVisitor(Graph aGraph) { - _graph = aGraph; + public CheckExternallyProvidedVisitor(Graph aGraph) { + graph = aGraph; } @Override @@ -49,26 +49,33 @@ public class CheckExternallyProvidedVisitor implements Visitor { @Override public void visitNode(Node aNode) { - if ( aNode instanceof ExternalProvidedInterfaceNode) { - ExternalProvidedInterfaceNode provided = (ExternalProvidedInterfaceNode) aNode; - List edges = _graph.findOutgoing(provided); - if ( edges.size() > 2 ) { - createDuplicateException("External provided interfaces has multiple internal matches", aNode, edges); + if (aNode instanceof ExternalProvidedInterfaceNode) { + ExternalProvidedInterfaceNode provided = (ExternalProvidedInterfaceNode) aNode; + List edges = graph.findOutgoing(provided); + + if (edges.size() > 2) { + createDuplicateException( + "External provided interfaces has multiple internal matches", + aNode, edges); } - if ( edges.size() == 0 ) { - throw new SystemAssemblyException(aNode + ": external provded interface is not provided by any of the internal components"); + + if (edges.size() == 0) { + throw new SystemAssemblyException( + aNode + + ": external provded interface is not provided by any of the internal components"); } } } - - private void createDuplicateException(String aMsg, Node aNode, List edges) { + + private void createDuplicateException(String aMsg, Node aNode, + List aEdges) { StringBuffer buf = new StringBuffer(); - buf.append(aNode - + ": " + aMsg + ": "); - for (Edge edge : edges) { + buf.append(aNode + ": " + aMsg + ": "); + + for (Edge edge : aEdges) { buf.append(edge.getTo() + "/ "); } + throw new SystemAssemblyException(buf.toString()); } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyRequiredVisitor.java b/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyRequiredVisitor.java index 1ce53d07..8e90ef4f 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyRequiredVisitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/CheckExternallyRequiredVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,34 +12,37 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.Graph; import org.wamblee.system.graph.Node; import org.wamblee.system.graph.Visitor; +import java.util.List; + /** * Visitor that checks whether all required external interfaces of the container * are provided. * * @author Erik Brakkee - * */ public class CheckExternallyRequiredVisitor implements Visitor { + private static final Log LOG = LogFactory.getLog(CheckExternallyRequiredVisitor.class); - private Log LOG = LogFactory.getLog(CheckExternallyRequiredVisitor.class); - - private Graph _graph; + private Graph graph; + /** + * Creates a new CheckExternallyRequiredVisitor object. + * + */ public CheckExternallyRequiredVisitor(Graph aGraph) { - _graph = aGraph; + graph = aGraph; } @Override @@ -51,30 +54,33 @@ public class CheckExternallyRequiredVisitor implements Visitor { public void visitNode(Node aNode) { if (aNode instanceof ExternalRequiredInterfaceNode) { ExternalRequiredInterfaceNode required = (ExternalRequiredInterfaceNode) aNode; - if (!required.getRequired().isOptional() - && required.getRequired().getProvider() == null) { - throw new SystemAssemblyException(aNode - + ": External required interface is not provided"); + + if (!required.getRequired().isOptional() && + (required.getRequired().getProvider() == null)) { + throw new SystemAssemblyException(aNode + + ": External required interface is not provided"); } - List edges = _graph.findIncoming(aNode); + List edges = graph.findIncoming(aNode); if (edges.isEmpty()) { LOG.warn(aNode + ": Superfluous required interface"); } + for (Edge edge : edges) { Node from = edge.getFrom(); assert from instanceof RequiredInterfaceNode; - RequiredInterfaceNode reqNode = (RequiredInterfaceNode)from; - if (!reqNode.getRequired().isOptional() - && required.getRequired().isOptional()) { + + RequiredInterfaceNode reqNode = (RequiredInterfaceNode) from; + + if (!reqNode.getRequired().isOptional() && + required.getRequired().isOptional()) { throw new SystemAssemblyException( - aNode - + ": externally required interface is optional but a corresponding internal required interface is mandatory: " - + reqNode); + aNode + + ": externally required interface is optional but a corresponding internal required interface is mandatory: " + + reqNode); } } } } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/CheckRequiredProvidedMultiplicityVisitor.java b/system/general/src/main/java/org/wamblee/system/graph/component/CheckRequiredProvidedMultiplicityVisitor.java index 608dfc16..fc8eaf27 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/CheckRequiredProvidedMultiplicityVisitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/CheckRequiredProvidedMultiplicityVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,36 +12,37 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; -import java.util.List; - import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.Graph; import org.wamblee.system.graph.Node; import org.wamblee.system.graph.Visitor; +import java.util.List; + /** * Visitor that checks whether required and provided interfaces are matched * appropriately: *
    - *
  • Each required interface is connected to at most one provided interface - *
  • + *
  • Each required interface is connected to at most one provided interface
  • *
  • Required interfaces that are not optional must be connected to precisely * one provided interface
  • *
* * @author Erik Brakkee - * */ public class CheckRequiredProvidedMultiplicityVisitor implements Visitor { + private Graph graph; - private Graph _graph; - + /** + * Creates a new CheckRequiredProvidedMultiplicityVisitor object. + * + */ public CheckRequiredProvidedMultiplicityVisitor(Graph aGraph) { - _graph = aGraph; + graph = aGraph; } @Override @@ -53,34 +54,44 @@ public class CheckRequiredProvidedMultiplicityVisitor implements Visitor { public void visitNode(Node aNode) { if (aNode instanceof RequiredInterfaceNode) { RequiredInterfaceNode required = (RequiredInterfaceNode) aNode; - List edges = _graph.findOutgoing(aNode); + List edges = graph.findOutgoing(aNode); + if (edges.size() > 1) { - createDuplicateException("Multiple providers of required interface found", aNode, edges); + createDuplicateException( + "Multiple providers of required interface found", aNode, + edges); } - if (edges.size() == 0 && !required.getRequired().isOptional()) { + + if ((edges.size() == 0) && !required.getRequired().isOptional()) { throw new SystemAssemblyException( - aNode - + ": mandatpory required interface not provided by other components started earlier"); + aNode + + ": mandatpory required interface not provided by other components started earlier"); } - } else if ( aNode instanceof ExternalProvidedInterfaceNode) { - List edges = _graph.findOutgoing(aNode); - if ( edges.size() > 1) { - createDuplicateException("multiple internal matches for externally provided interface", aNode, edges); + } else if (aNode instanceof ExternalProvidedInterfaceNode) { + List edges = graph.findOutgoing(aNode); + + if (edges.size() > 1) { + createDuplicateException( + "multiple internal matches for externally provided interface", + aNode, edges); } - if ( edges.size() == 0 ) { - throw new SystemAssemblyException(aNode + ": external provided interface is not provided internally"); + + if (edges.size() == 0) { + throw new SystemAssemblyException(aNode + + ": external provided interface is not provided internally"); } } } - private void createDuplicateException(String aMsg, Node aNode, List edges) { + private void createDuplicateException(String aMsg, Node aNode, + List aEdges) { StringBuffer buf = new StringBuffer(); - buf.append(aNode - + ": " + aMsg + ": "); - for (Edge edge : edges) { + buf.append(aNode + ": " + aMsg + ": "); + + for (Edge edge : aEdges) { buf.append(edge.getTo() + "/ "); } + throw new SystemAssemblyException(buf.toString()); } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/CheckStartupDependenciesVisitor.java b/system/general/src/main/java/org/wamblee/system/graph/component/CheckStartupDependenciesVisitor.java index 61f4e704..c865b8b7 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/CheckStartupDependenciesVisitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/CheckStartupDependenciesVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,33 +15,35 @@ */ package org.wamblee.system.graph.component; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.Graph; import org.wamblee.system.graph.Node; import org.wamblee.system.graph.Visitor; +import java.util.ArrayList; +import java.util.List; + /** - * Checks whether the given component graph can be started in component - * order without any missing dependencies. + * Checks whether the given component graph can be started in component order + * without any missing dependencies. + * * @author Erik Brakkee - * */ public class CheckStartupDependenciesVisitor implements Visitor { - - private Graph _graph; - private List _available; + private Graph graph; + + private List available; /** - * Constructs the visitor. - * @param aGraph Graph. + * Constructs the visitor. + * + * @param aGraph + * Graph. */ - public CheckStartupDependenciesVisitor(Graph aGraph) { - _graph = aGraph; - _available = new ArrayList(); + public CheckStartupDependenciesVisitor(Graph aGraph) { + graph = aGraph; + available = new ArrayList(); } @Override @@ -51,17 +53,18 @@ public class CheckStartupDependenciesVisitor implements Visitor { @Override public void visitNode(Node aNode) { - List edges = _graph.findOutgoing(aNode); - + List edges = graph.findOutgoing(aNode); + // check dependencies. - for (Edge edge: edges) { + for (Edge edge : edges) { Node dep = edge.getTo(); - if ( !_available.contains(dep)) { - throw new SystemAssemblyException(aNode + ": required dependency '" + dep + "' was not started"); + + if (!available.contains(dep)) { + throw new SystemAssemblyException(aNode + + ": required dependency '" + dep + "' was not started"); } } - - _available.add(aNode); - } + available.add(aNode); + } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ComponentGraph.java b/system/general/src/main/java/org/wamblee/system/graph/component/ComponentGraph.java index b41c41c8..3032df0c 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ComponentGraph.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ComponentGraph.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,8 @@ */ package org.wamblee.system.graph.component; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.general.Pair; + import org.wamblee.system.core.Component; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; @@ -28,127 +26,144 @@ import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.Graph; import org.wamblee.system.graph.Node; +import java.util.ArrayList; +import java.util.List; + /** - * Represents a component graph and provides the bridge from the - * component model to a graph model. The graph model is easier - * to work with to implement specific actions and validations than - * the component model. + * Represents a component graph and provides the bridge from the component model + * to a graph model. The graph model is easier to work with to implement + * specific actions and validations than the component model. */ public class ComponentGraph extends Graph { - - private boolean _isLinked; - private CompositeEdgeFilter _edgeFilter; + private boolean isLinked; + + private CompositeEdgeFilter edgeFilter; /** - * Constructs an empty component graph. + * Constructs an empty component graph. */ public ComponentGraph() { - _isLinked = false; - _edgeFilter = new CompositeEdgeFilter(); + isLinked = false; + edgeFilter = new CompositeEdgeFilter(); } - + /** - * Adds an externally required interface of a container. - * This should be called before any components of the container are - * added. - * @param aComponent Component requiring the interface. - * @param aInterface Required interface. + * Adds an externally required interface of a container. This should be + * called before any components of the container are added. + * + * @param aComponent + * Component requiring the interface. + * @param aInterface + * Required interface. */ - public void addRequiredInterface(Component aComponent, RequiredInterface aInterface) { + public void addRequiredInterface(Component aComponent, + RequiredInterface aInterface) { addNode(new ExternalRequiredInterfaceNode(aComponent, aInterface)); } - + /** - * Adds an externally provided interface of a container. - * This should be called after all components of the container have been added. - * @param aComponent Component providing the interface. - * @param aInterface Provided interface. + * Adds an externally provided interface of a container. This should be + * called after all components of the container have been added. + * + * @param aComponent + * Component providing the interface. + * @param aInterface + * Provided interface. */ - public void addProvidedInterface(Component aComponent, ProvidedInterface aInterface) { + public void addProvidedInterface(Component aComponent, + ProvidedInterface aInterface) { addNode(new ExternalProvidedInterfaceNode(aComponent, aInterface)); } - + /** - * Validates the component graph. + * Validates the component graph. */ - public void validate() { + public void validate() { extend(new RequiredProvidedEdgeFactory()); - applyFilter(_edgeFilter); + applyFilter(edgeFilter); accept(new CheckRequiredProvidedMultiplicityVisitor(this)); - accept(new CheckExternallyRequiredVisitor(this)); + accept(new CheckExternallyRequiredVisitor(this)); accept(new CheckExternallyProvidedVisitor(this)); accept(new CheckStartupDependenciesVisitor(this)); } - + /** - * Links provided and required interfaces together in the component - * model based on the graph model. + * Links provided and required interfaces together in the component model + * based on the graph model. */ public void link() { - if ( _isLinked ) { - return; + if (isLinked) { + return; } + accept(new LinkVisitor()); - _isLinked = true; + isLinked = true; } - + /** - * Finds a list of mappings of external provided interface to internal provided interface. + * Finds a list of mappings of external provided interface to internal + * provided interface. * - * @return List of pairs of external to internal interface. + * @return List of pairs of external to internal interface. */ - public List> findExternalProvidedInterfaceMapping() { - List> result = - new ArrayList>(); - for (Edge edge: getEdges()) { - if ( edge.getFrom() instanceof ExternalProvidedInterfaceNode && - edge.getTo() instanceof ProvidedInterfaceNode ) { - result.add(new Pair( - ((ExternalProvidedInterfaceNode)edge.getFrom()).getProvided(), - ((ProvidedInterfaceNode)edge.getTo()).getProvided() - )); + public List> findExternalProvidedInterfaceMapping() { + List> result = new ArrayList>(); + + for (Edge edge : getEdges()) { + if (edge.getFrom() instanceof ExternalProvidedInterfaceNode && + edge.getTo() instanceof ProvidedInterfaceNode) { + result.add(new Pair( + ((ExternalProvidedInterfaceNode) edge.getFrom()) + .getProvided(), ((ProvidedInterfaceNode) edge.getTo()) + .getProvided())); } } - return result; + + return result; } - + /** - * Adds a component by adding required interfaces, components, and - * provided interfaces. - * @param aComponent Component to add. + * Adds a component by adding required interfaces, components, and provided + * interfaces. + * + * @param aComponent + * Component to add. */ - public void addComponent(Component aComponent) { - // Add required interfaces. + public void addComponent(Component aComponent) { + // Add required interfaces. Node compNode = new ComponentNode(aComponent); List requiredNodes = new ArrayList(); - for (RequiredInterface required: aComponent.getRequiredInterfaces()) { - Node reqNode = new RequiredInterfaceNode(aComponent, required); + + for (RequiredInterface required : aComponent.getRequiredInterfaces()) { + Node reqNode = new RequiredInterfaceNode(aComponent, required); addNode(reqNode); requiredNodes.add(reqNode); } + // Add the component addNode(compNode); - - // Edges from component to required interface. - for (Node reqNode: requiredNodes) { + + // Edges from component to required interface. + for (Node reqNode : requiredNodes) { addEdge(new DefaultEdge(compNode, reqNode)); } - + // Add provided interfaces List providedNodes = new ArrayList(); - for (ProvidedInterface provided: aComponent.getProvidedInterfaces()) { - Node provNode = new ProvidedInterfaceNode(aComponent, provided); + + for (ProvidedInterface provided : aComponent.getProvidedInterfaces()) { + Node provNode = new ProvidedInterfaceNode(aComponent, provided); addNode(provNode); providedNodes.add(provNode); } - + // Edges from provided interface to component - for (Node provNode: providedNodes) { + for (Node provNode : providedNodes) { addEdge(new DefaultEdge(provNode, compNode)); } } public void addEdgeFilter(CompositeEdgeFilter aEdgeFilter) { - _edgeFilter.add(aEdgeFilter); + edgeFilter.add(aEdgeFilter); } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ComponentNode.java b/system/general/src/main/java/org/wamblee/system/graph/component/ComponentNode.java index dc344268..3656d6b6 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ComponentNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ComponentNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,24 +19,27 @@ import org.wamblee.system.core.Component; import org.wamblee.system.graph.Node; /** - * Represents a component node. - * @author Erik Brakkee. - * + * Represents a component node. + * + * @author Erik Brakkee. */ public class ComponentNode implements Node { - - private Component _component; - - public ComponentNode(Component aComponent) { - _component = aComponent; + private Component component; + + /** + * Creates a new ComponentNode object. + * + */ + public ComponentNode(Component aComponent) { + component = aComponent; } @Override public String getName() { - return _component.getQualifiedName(); + return component.getQualifiedName(); } - + public Component getComponent() { - return _component; + return component; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedFilter.java b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedFilter.java index 1007ae70..7bd1756f 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedFilter.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import org.wamblee.system.graph.Edge; @@ -23,49 +23,62 @@ import org.wamblee.system.graph.EdgeFilter; * container. * * @author Erik Brakkee - * */ public class ConnectExternalProvidedProvidedFilter implements EdgeFilter { + private String externalProvided; + + private String component; - private String _externalProvided; - private String _component; - private String _provided; + private String provided; - public ConnectExternalProvidedProvidedFilter(String aExternalProvided, String aComponent, - String aProvided) { - _externalProvided = aExternalProvided; - _component = aComponent; - _provided = aProvided; - if ( _externalProvided == null ) { - throw new IllegalArgumentException("External provided interface name must be specified."); + /** + * Creates a new ConnectExternalProvidedProvidedFilter object. + * + */ + public ConnectExternalProvidedProvidedFilter(String aExternalProvided, + String aComponent, String aProvided) { + externalProvided = aExternalProvided; + component = aComponent; + provided = aProvided; + + if (externalProvided == null) { + throw new IllegalArgumentException( + "External provided interface name must be specified."); } - if ( _component == null ) { - throw new IllegalArgumentException("Component name must be specified"); + + if (component == null) { + throw new IllegalArgumentException( + "Component name must be specified"); } - if ( _provided == null ) { - throw new IllegalArgumentException("Provided interface name of internal component must be specified"); + + if (provided == null) { + throw new IllegalArgumentException( + "Provided interface name of internal component must be specified"); } } @Override public boolean isViolated(Edge aEdge) { - if (aEdge.getFrom() instanceof ExternalProvidedInterfaceNode - && aEdge.getTo() instanceof ProvidedInterfaceNode) { + if (aEdge.getFrom() instanceof ExternalProvidedInterfaceNode && + aEdge.getTo() instanceof ProvidedInterfaceNode) { return isViolated((ExternalProvidedInterfaceNode) aEdge.getFrom(), - (ProvidedInterfaceNode) aEdge.getTo()); + (ProvidedInterfaceNode) aEdge.getTo()); } + return false; } private boolean isViolated(ExternalProvidedInterfaceNode aFrom, - ProvidedInterfaceNode aTo) { - if ( !aFrom.getName().equals(_externalProvided)) { + ProvidedInterfaceNode aTo) { + if (!aFrom.getName().equals(externalProvided)) { return false; // wrong provided interface. } - if ( aTo.getComponent().getName().equals(_component) && - aTo.getProvided().getName().equals(_provided) ) { - return false; // ok + + if (aTo.getComponent().getName().equals(component) && + aTo.getProvided().getName().equals(provided)) { + return false; // ok } - return true; + + return true; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilter.java b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilter.java index c7084028..04677473 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilter.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import org.wamblee.system.graph.Edge; @@ -23,52 +23,66 @@ import org.wamblee.system.graph.EdgeFilter; * container. * * @author Erik Brakkee - * */ public class ConnectRequiredExternallyRequiredEdgeFilter implements EdgeFilter { + private String client; + + private String required; - private String _client; - private String _required; - private String _externalRequired; + private String externalRequired; - public ConnectRequiredExternallyRequiredEdgeFilter(String aClient, String aRequired, - String aExternalRequired) { - _client = aClient; - _required = aRequired; - _externalRequired = aExternalRequired; - if ( _client == null ) { - throw new IllegalArgumentException("Client component must be specified"); + /** + * Creates a new ConnectRequiredExternallyRequiredEdgeFilter object. + * + */ + public ConnectRequiredExternallyRequiredEdgeFilter(String aClient, + String aRequired, String aExternalRequired) { + client = aClient; + required = aRequired; + externalRequired = aExternalRequired; + + if (client == null) { + throw new IllegalArgumentException( + "Client component must be specified"); } - if ( _required == null ) { - throw new IllegalArgumentException("Required interface must be specified"); + + if (required == null) { + throw new IllegalArgumentException( + "Required interface must be specified"); } - if ( _externalRequired == null ) { - throw new IllegalArgumentException("External required interface must be specified"); + + if (externalRequired == null) { + throw new IllegalArgumentException( + "External required interface must be specified"); } } @Override public boolean isViolated(Edge aEdge) { - if (aEdge.getFrom() instanceof RequiredInterfaceNode - && aEdge.getTo() instanceof ExternalRequiredInterfaceNode) { + if (aEdge.getFrom() instanceof RequiredInterfaceNode && + aEdge.getTo() instanceof ExternalRequiredInterfaceNode) { return isViolated((RequiredInterfaceNode) aEdge.getFrom(), - (ExternalRequiredInterfaceNode) aEdge.getTo()); + (ExternalRequiredInterfaceNode) aEdge.getTo()); } + return false; } private boolean isViolated(RequiredInterfaceNode aFrom, - ExternalRequiredInterfaceNode aTo) { - if ( !aFrom.getComponent().getName().equals(_client)) { - return false; // wrong component. + ExternalRequiredInterfaceNode aTo) { + if (!aFrom.getComponent().getName().equals(client)) { + return false; // wrong component. } - if ( !(_required == null || aFrom.getRequired().getName().equals(_required))) { + + if (!((required == null) || aFrom.getRequired().getName().equals( + required))) { return false; // wrong interface } - if ( !aTo.getRequired().getName().equals(_externalRequired)) { - return true; // wrong externally required interface. + + if (!aTo.getRequired().getName().equals(externalRequired)) { + return true; // wrong externally required interface. } - - return false; + + return false; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilter.java b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilter.java index a1d2481f..a2f91877 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilter.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import org.wamblee.system.graph.Edge; @@ -23,54 +23,62 @@ import org.wamblee.system.graph.EdgeFilter; * container. * * @author Erik Brakkee - * */ public class ConnectRequiredProvidedEdgeFilter implements EdgeFilter { + private String client; + + private String required; + + private String server; - private String _client; - private String _required; - private String _server; - private String _provided; + private String provided; + /** + * Creates a new ConnectRequiredProvidedEdgeFilter object. + * + */ public ConnectRequiredProvidedEdgeFilter(String aClient, String aRequired, - String aServer, String aProvided) { - _client = aClient; - _required = aRequired; - _server = aServer; - _provided = aProvided; - if ( _client == null ) { - throw new IllegalArgumentException("Client component must be specified"); + String aServer, String aProvided) { + client = aClient; + required = aRequired; + server = aServer; + provided = aProvided; + + if (client == null) { + throw new IllegalArgumentException( + "Client component must be specified"); } } @Override public boolean isViolated(Edge aEdge) { - if (aEdge.getFrom() instanceof RequiredInterfaceNode - && aEdge.getTo() instanceof ProvidedInterfaceNode) { + if (aEdge.getFrom() instanceof RequiredInterfaceNode && + aEdge.getTo() instanceof ProvidedInterfaceNode) { return isViolated((RequiredInterfaceNode) aEdge.getFrom(), - (ProvidedInterfaceNode) aEdge.getTo()); + (ProvidedInterfaceNode) aEdge.getTo()); } + return false; } private boolean isViolated(RequiredInterfaceNode aFrom, - ProvidedInterfaceNode aTo) { - if (_client.equals(aFrom.getComponent().getName()) - && (_required == null || _required.equals(aFrom.getRequired() - .getName()))) { + ProvidedInterfaceNode aTo) { + if (client.equals(aFrom.getComponent().getName()) && + ((required == null) || required.equals(aFrom.getRequired() + .getName()))) { // From part matches. - if ( _server == null ) { + if (server == null) { return true; // all connections are eliminated } - if (_server.equals(aTo.getComponent().getName()) - && (_provided == null || _provided.equals(aTo.getProvided() - .getName()))) { + + if (server.equals(aTo.getComponent().getName()) && + ((provided == null) || provided.equals(aTo.getProvided() + .getName()))) { // to part matches also return false; - } - else { + } else { // From matches and to doesn't so edgefilter is violated. - return true; + return true; } } else { // From part does not match, restriction does not apply. diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ExternalProvidedInterfaceNode.java b/system/general/src/main/java/org/wamblee/system/graph/component/ExternalProvidedInterfaceNode.java index c7fd7d0b..bc465cb7 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ExternalProvidedInterfaceNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ExternalProvidedInterfaceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,35 +20,40 @@ import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.graph.Node; /** - * Represents an external provided interface of a container. + * Represents an external provided interface of a container. + * * @author Erik Brakkee - * */ public class ExternalProvidedInterfaceNode implements Node { + private Component component; + + private ProvidedInterface provided; - private Component _component; - private ProvidedInterface _provided; - - public ExternalProvidedInterfaceNode(Component aComponent, ProvidedInterface aProvided) { - _component = aComponent; - _provided = aProvided; + /** + * Creates a new ExternalProvidedInterfaceNode object. + * + */ + public ExternalProvidedInterfaceNode(Component aComponent, + ProvidedInterface aProvided) { + component = aComponent; + provided = aProvided; } - + @Override public String getName() { - return _provided.getName(); + return provided.getName(); } - + public Component getComponent() { - return _component; + return component; } - + public ProvidedInterface getProvided() { - return _provided; + return provided; } - + @Override public String toString() { - return _component.getQualifiedName() + ":" + _provided; + return component.getQualifiedName() + ":" + provided; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ExternalRequiredInterfaceNode.java b/system/general/src/main/java/org/wamblee/system/graph/component/ExternalRequiredInterfaceNode.java index 5c65ebdb..1baf0559 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ExternalRequiredInterfaceNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ExternalRequiredInterfaceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,35 +20,40 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.graph.Node; /** - * Represents an externally required interface of a container. + * Represents an externally required interface of a container. + * * @author Erik Brakkee - * */ public class ExternalRequiredInterfaceNode implements Node { - - private Component _component; - private RequiredInterface _required; + private Component component; + + private RequiredInterface required; - public ExternalRequiredInterfaceNode(Component aComponent, RequiredInterface aRequired) { - _component = aComponent; - _required = aRequired; + /** + * Creates a new ExternalRequiredInterfaceNode object. + * + */ + public ExternalRequiredInterfaceNode(Component aComponent, + RequiredInterface aRequired) { + component = aComponent; + required = aRequired; } - + @Override public String getName() { - return _required.getName(); + return required.getName(); } - + public Component getComponent() { - return _component; + return component; } - + public RequiredInterface getRequired() { - return _required; + return required; } - + @Override public String toString() { - return _component.getQualifiedName() + ":" + _required; + return component.getQualifiedName() + ":" + required; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/LinkVisitor.java b/system/general/src/main/java/org/wamblee/system/graph/component/LinkVisitor.java index cc2007ff..ca8eda3f 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/LinkVisitor.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/LinkVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import org.wamblee.system.core.ProvidedInterface; @@ -24,37 +24,36 @@ import org.wamblee.system.graph.Visitor; /** * Visitor that creates links between required and provided interfaces as - * described by the edges in the graph. - * - * Specically it links together (1) required and provided interfaces of internal component - * of a container and (2) the providers of externally required interfaces and internal required - * interfaces. + * described by the edges in the graph. Specically it links together (1) + * required and provided interfaces of internal component of a container and (2) + * the providers of externally required interfaces and internal required + * interfaces. * * @author Erik Brakkee - * */ public class LinkVisitor implements Visitor { - @Override public void visitEdge(Edge aEdge) { Node from = aEdge.getFrom(); Node to = aEdge.getTo(); + if (from instanceof RequiredInterfaceNode) { RequiredInterfaceNode required = (RequiredInterfaceNode) from; - if (to instanceof ProvidedInterfaceNode) { + if (to instanceof ProvidedInterfaceNode) { ProvidedInterfaceNode provided = (ProvidedInterfaceNode) to; required.getRequired().setProvider(provided.getProvided()); - } else if (to instanceof ExternalRequiredInterfaceNode) { ExternalRequiredInterfaceNode external = (ExternalRequiredInterfaceNode) to; ProvidedInterface provider = external.getRequired() - .getProvider(); - if (provider == null && !required.getRequired().isOptional()) { - throw new SystemAssemblyException("Mandatory interface '" - + from + "' is not provided."); + .getProvider(); + + if ((provider == null) && !required.getRequired().isOptional()) { + throw new SystemAssemblyException("Mandatory interface '" + + from + "' is not provided."); } - if ( provider != null ) { + + if (provider != null) { required.getRequired().setProvider(provider); } } @@ -68,5 +67,4 @@ public class LinkVisitor implements Visitor { public void visitNode(Node aNode) { // Empty. } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/ProvidedInterfaceNode.java b/system/general/src/main/java/org/wamblee/system/graph/component/ProvidedInterfaceNode.java index 2fb2c0f7..f4a4989e 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/ProvidedInterfaceNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/ProvidedInterfaceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,34 +20,40 @@ import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.graph.Node; /** - * Provided interface node. + * Provided interface node. + * * @author Erik Brakkee */ public class ProvidedInterfaceNode implements Node { - - private Component _component; - private ProvidedInterface _provided; - - public ProvidedInterfaceNode(Component aComponent, ProvidedInterface aProvided) { - _component = aComponent; - _provided = aProvided; + private Component component; + + private ProvidedInterface provided; + + /** + * Creates a new ProvidedInterfaceNode object. + * + */ + public ProvidedInterfaceNode(Component aComponent, + ProvidedInterface aProvided) { + component = aComponent; + provided = aProvided; } @Override public String getName() { - return _component.getQualifiedName() + ":" + _provided.getName(); + return component.getQualifiedName() + ":" + provided.getName(); } public ProvidedInterface getProvided() { - return _provided; + return provided; } - + public Component getComponent() { - return _component; + return component; } - + @Override public String toString() { - return _component.getQualifiedName() + ":" + _provided; + return component.getQualifiedName() + ":" + provided; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/RequiredInterfaceNode.java b/system/general/src/main/java/org/wamblee/system/graph/component/RequiredInterfaceNode.java index b1540512..454ebce2 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/RequiredInterfaceNode.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/RequiredInterfaceNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,35 +20,40 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.graph.Node; /** - * Required interface node. + * Required interface node. + * * @author Erik Brakkee - * */ public class RequiredInterfaceNode implements Node { - - private Component _component; - private RequiredInterface _required; - - public RequiredInterfaceNode(Component aComponent, RequiredInterface aRequired) { - _component = aComponent; - _required = aRequired; + private Component component; + + private RequiredInterface required; + + /** + * Creates a new RequiredInterfaceNode object. + * + */ + public RequiredInterfaceNode(Component aComponent, + RequiredInterface aRequired) { + component = aComponent; + required = aRequired; } @Override public String getName() { - return _component.getQualifiedName() + ":" + _required.getName(); + return component.getQualifiedName() + ":" + required.getName(); } public RequiredInterface getRequired() { - return _required; + return required; } - + public Component getComponent() { - return _component; + return component; } - + @Override public String toString() { - return _component.getQualifiedName() + ":" + _required; + return component.getQualifiedName() + ":" + required; } } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/RequiredProvidedEdgeFactory.java b/system/general/src/main/java/org/wamblee/system/graph/component/RequiredProvidedEdgeFactory.java index 711501a1..0af63d34 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/RequiredProvidedEdgeFactory.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/RequiredProvidedEdgeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,31 +12,32 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; -import java.util.ArrayList; -import java.util.List; - import org.wamblee.system.graph.DefaultEdge; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.EdgeFactory; import org.wamblee.system.graph.Node; +import java.util.ArrayList; +import java.util.List; + /** * Factory that creates edges between required and provided interfaces. - * Speciflcally it creates: + * Speciflcally it creates: *
    - *
  • Edges between provided and required interfaces of a container.
  • - *
  • Edges between required and externally required interfaces
  • - *
  • Edges between externally provided and provided interfaces. + *
  • Edges between provided and required interfaces of a container.
  • + *
  • Edges between required and externally required interfaces
  • + *
  • Edges between externally provided and provided interfaces. *
* * @author Erik Brakkee - * */ public class RequiredProvidedEdgeFactory implements EdgeFactory { - + /** + * Creates a new RequiredProvidedEdgeFactory object. + */ public RequiredProvidedEdgeFactory() { // Empty. } @@ -44,31 +45,36 @@ public class RequiredProvidedEdgeFactory implements EdgeFactory { @Override public List create(Node aFrom, Node aTo) { List result = new ArrayList(); + if (aFrom instanceof RequiredInterfaceNode) { RequiredInterfaceNode required = (RequiredInterfaceNode) aFrom; + if (aTo instanceof ProvidedInterfaceNode) { - ProvidedInterfaceNode provided = (ProvidedInterfaceNode) aTo; + if (required.getRequired() - .implementedBy(provided.getProvided())) { + .implementedBy(provided.getProvided())) { result.add(new DefaultEdge(required, provided)); } } else if (aTo instanceof ExternalRequiredInterfaceNode) { ExternalRequiredInterfaceNode external = (ExternalRequiredInterfaceNode) aTo; - if ( external.getRequired().covers(required.getRequired())) { + + if (external.getRequired().covers(required.getRequired())) { result.add(new DefaultEdge(required, external)); } } - } else if ( aFrom instanceof ProvidedInterfaceNode) { - ProvidedInterfaceNode provided = (ProvidedInterfaceNode)aFrom; - if ( aTo instanceof ExternalProvidedInterfaceNode) { - ExternalProvidedInterfaceNode external = (ExternalProvidedInterfaceNode)aTo; - if (provided.getProvided().covers(external.getProvided())) { + } else if (aFrom instanceof ProvidedInterfaceNode) { + ProvidedInterfaceNode provided = (ProvidedInterfaceNode) aFrom; + + if (aTo instanceof ExternalProvidedInterfaceNode) { + ExternalProvidedInterfaceNode external = (ExternalProvidedInterfaceNode) aTo; + + if (provided.getProvided().covers(external.getProvided())) { result.add(new DefaultEdge(external, provided)); } } } + return result; } - } diff --git a/system/general/src/main/java/org/wamblee/system/graph/component/package-info.java b/system/general/src/main/java/org/wamblee/system/graph/component/package-info.java index f886d788..e906c601 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/component/package-info.java +++ b/system/general/src/main/java/org/wamblee/system/graph/component/package-info.java @@ -1,28 +1,18 @@ -/** - *

Graph component package

+/* + * Copyright 2005-2010 the original author or authors. * - * The graph component package provides the representation of a number of - * components {@link Component} - * their required and provided interfaces ({@link RequiredInterface} and - * {@link ProvidedInterface}), and how these are connected together. + * 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 * - * This package provides the bridge between the component model and the - * representation of the components and their connections in a graph. - * The component package provides various algorithms, filters, and - * validations that are required for the implementation of a container. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The main abstractions are: - *
    - *
  • {@link ComponentGraph}: A graph of components. This provides the logic - * for creating a graph based on components.
  • - *
  • {@link ComponentNode}: A node representing a component.
  • - *
  • {@link RequiredInterfaceNode}: A node representing a required interface of a component.
  • - *
  • {@link ProvidedInterfaceNode}: A node repesenting a provided interface of a component.
  • - *
  • {@link ExternalRequiredInterfaceNode}: A node representing a required interface of a container
  • - *
  • {@link ExternalProvidedInterfaceNode}: A node representing a provided interface of a container
  • - *
- * - */ + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.wamblee.system.graph.component; import org.wamblee.system.core.Component; diff --git a/system/general/src/main/java/org/wamblee/system/graph/package-info.java b/system/general/src/main/java/org/wamblee/system/graph/package-info.java index 6a2318ec..7fe76541 100644 --- a/system/general/src/main/java/org/wamblee/system/graph/package-info.java +++ b/system/general/src/main/java/org/wamblee/system/graph/package-info.java @@ -1,20 +1,17 @@ -/** - *

Graph package

+/* + * Copyright 2005-2010 the original author or authors. * - * The graph package provides a general very simple abstraction of a graph. - * It was developed for the IOC container to represent dependences between - * components through their required and provided interfaces. + * 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 * - * The graph package supports a number of simple graph traversal operations, graph - * extension operations, and a visitor pattern. + * http://www.apache.org/licenses/LICENSE-2.0 * - * The main abstractions are: - *
    - *
  • {@link Graph}: The graph itself.
  • - *
  • {@link Node}: A node of a graph.
  • - *
  • {@link Edge}: An edge of a graph>
  • - *
  • {@link Visitor}: A visitor for implementing various operations on a graph.
  • - *
  • {@link EdgeFactory}: For extending the graph with new edges
  • - *
- */ -package org.wamblee.system.graph; \ No newline at end of file + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.wamblee.system.graph; + diff --git a/system/general/src/test/java/org/wamblee/system/adapters/AdapterTestCase.java b/system/general/src/test/java/org/wamblee/system/adapters/AdapterTestCase.java index cf67b247..7ca8b96b 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/AdapterTestCase.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/AdapterTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,23 +15,40 @@ */ package org.wamblee.system.adapters; +import junit.framework.TestCase; + import org.wamblee.system.core.DefaultScope; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.Scope; -import org.wamblee.test.EventTracker; -import junit.framework.TestCase; +import org.wamblee.test.EventTracker; +/** + * + * @author $author$ + * @version $Revision$ + */ public class AdapterTestCase extends TestCase { - - protected Scope _scope; - static EventTracker EVENT_TRACKER; + private static EventTracker EVENT_TRACKER; - @Override - protected void setUp() throws Exception { - super.setUp(); - EVENT_TRACKER = new EventTracker(); - _scope = new DefaultScope(new ProvidedInterface[0]); - } + private Scope scope; + protected Scope getScope() { + return scope; + } + + public static EventTracker getEventTracker() { + return EVENT_TRACKER; + } + + private static void setEventTracker(EventTracker aTracker) { + EVENT_TRACKER = aTracker; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + setEventTracker(new EventTracker()); + scope = new DefaultScope(new ProvidedInterface[0]); + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/ClassAdapterTest.java b/system/general/src/test/java/org/wamblee/system/adapters/ClassAdapterTest.java index 5e4f868f..1a6f9b58 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/ClassAdapterTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/ClassAdapterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,72 +20,82 @@ import org.wamblee.system.core.Component; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; + import org.wamblee.test.AssertionUtils; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ClassAdapterTest extends AdapterTestCase { + public void testSimpleConstructorInjection() { + ClassConfiguration x1Config = new ClassConfiguration(X1.class); + x1Config.getObjectConfig().getSetterConfig().initAllSetters(); + x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); - - public void testSimpleConstructorInjection() { - ClassConfiguration x1Config = new ClassConfiguration(X1.class); - x1Config.getObjectConfig().getSetterConfig().initAllSetters(); - x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); ClassConfiguration x4Config = new ClassConfiguration(X4.class); x4Config.getObjectConfig().getSetterConfig().initAllSetters(); - + ClassAdapter x1Adapter = new ClassAdapter("x1", x1Config); ClassAdapter x4Adapter = new ClassAdapter("x4", x4Config); - - Container container = new Container("top", new Component[] { - x1Adapter, x4Adapter - }, new ProvidedInterface[0], new RequiredInterface[0]); - + + Container container = new Container("top", new Component[] { x1Adapter, + x4Adapter }, new ProvidedInterface[0], new RequiredInterface[0]); + Scope scope = container.start(); AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)" }, - EVENT_TRACKER.getEvents(Thread.currentThread()).toArray()); - + getEventTracker().getEvents(Thread.currentThread()).toArray()); + Object obj1 = scope.getRuntime(x1Adapter); - assertTrue(obj1 instanceof X1); + assertTrue(obj1 instanceof X1); + Object obj4 = scope.getRuntime(x4Adapter); assertTrue(obj4 instanceof X4); - + X1 x1 = (X1) obj1; X4 x4 = (X4) obj4; - + assertSame(x1, x4.getX1()); - } - - public void testConstructorAndSetterInjection() { - ClassConfiguration x1Config = new ClassConfiguration(X1.class); - x1Config.getObjectConfig().getSetterConfig().initAllSetters(); + } + + public void testConstructorAndSetterInjection() { + ClassConfiguration x1Config = new ClassConfiguration(X1.class); + x1Config.getObjectConfig().getSetterConfig().initAllSetters(); x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); + ClassConfiguration x4Config = new ClassConfiguration(X4.class); x4Config.getObjectConfig().getSetterConfig().initAllSetters(); + ClassConfiguration x8Config = new ClassConfiguration(X8.class); x8Config.getObjectConfig().getSetterConfig().initAllSetters(); - + ClassAdapter x1Adapter = new ClassAdapter("x1", x1Config); ClassAdapter x4Adapter = new ClassAdapter("x4", x4Config); ClassAdapter x8Adapter = new ClassAdapter("x8", x8Config); - - Container container = new Container("top", new Component[] { - x1Adapter, x4Adapter, x8Adapter - }, new ProvidedInterface[0], new RequiredInterface[0]); - + + Container container = new Container("top", new Component[] { x1Adapter, + x4Adapter, x8Adapter }, new ProvidedInterface[0], + new RequiredInterface[0]); + Scope scope = container.start(); - AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)", "x8(x1)", "x8.setX4(x4)" }, - EVENT_TRACKER.getEvents(Thread.currentThread()).toArray()); - + AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)", + "x8(x1)", "x8.setX4(x4)" }, getEventTracker().getEvents( + Thread.currentThread()).toArray()); + Object obj1 = scope.getRuntime(x1Adapter); - assertTrue(obj1 instanceof X1); + assertTrue(obj1 instanceof X1); + Object obj4 = scope.getRuntime(x4Adapter); assertTrue(obj4 instanceof X4); - Object obj8 = scope.getRuntime(x8Adapter); - + + Object obj8 = scope.getRuntime(x8Adapter); + X1 x1 = (X1) obj1; X4 x4 = (X4) obj4; - X8 x8 = (X8) obj8; - + X8 x8 = (X8) obj8; + assertSame(x4, x8.getX4()); assertSame(x1, x8.getX1()); - } + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/ClassConfigurationTest.java b/system/general/src/test/java/org/wamblee/system/adapters/ClassConfigurationTest.java index 8d5703dd..24a8bae8 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/ClassConfigurationTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/ClassConfigurationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import java.util.Collections; @@ -22,18 +22,20 @@ import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.RequiredInterfaceComparator; +import org.wamblee.system.core.Scope; import org.wamblee.test.AssertionUtils; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ClassConfigurationTest extends AdapterTestCase { - public void testConstructorConfig() { ClassConfiguration classConfig = new ClassConfiguration(X1.class); - ConstructorConfiguration config = classConfig.getConstructorConfig() - .greedy(); - ProvidedInterface provided = new DefaultProvidedInterface("arg", - String.class); + String.class); List required = classConfig.getRequiredInterfaces(); assertEquals(1, required.size()); @@ -41,23 +43,25 @@ public class ClassConfigurationTest extends AdapterTestCase { required.get(0).setProvider(provided); - _scope.publishInterface(provided, "hello"); - classConfig.create(_scope); + getScope().publishInterface(provided, "hello"); + classConfig.create(getScope()); AssertionUtils.assertEquals(new String[] { "x1(hello)" }, - AdapterTestCase.EVENT_TRACKER.getEvents(Thread.currentThread()) - .toArray()); + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); } public void testConstructorConfigWithSetters() { ClassConfiguration classConfig = new ClassConfiguration(X7.class); classConfig.getConstructorConfig().select(Boolean.class); - classConfig.getObjectConfig().getSetterConfig().initAllSetters().values("setPort").setValue(0, 10); - - ProvidedInterface providedBoolean = new DefaultProvidedInterface("boolean", - Boolean.class); - ProvidedInterface providedHost = new DefaultProvidedInterface("host", String.class); + classConfig.getObjectConfig().getSetterConfig().initAllSetters() + .values("setPort").setValue(0, 10); + + ProvidedInterface providedBoolean = new DefaultProvidedInterface( + "boolean", Boolean.class); + ProvidedInterface providedHost = new DefaultProvidedInterface("host", + String.class); List required = classConfig.getRequiredInterfaces(); Collections.sort(required, new RequiredInterfaceComparator()); @@ -67,21 +71,22 @@ public class ClassConfigurationTest extends AdapterTestCase { required.get(0).setProvider(providedBoolean); required.get(1).setProvider(providedHost); - _scope.publishInterface(providedBoolean, true); - _scope.publishInterface(providedHost, "host.name.org"); - - Object obj = classConfig.create(_scope); + Scope scope = getScope(); + scope.publishInterface(providedBoolean, true); + scope.publishInterface(providedHost, "host.name.org"); + + Object obj = classConfig.create(scope); assertTrue(obj instanceof X7); - X7 x7 = (X7)obj; + + X7 x7 = (X7) obj; assertNotNull(x7.getBoolean()); assertTrue(x7.getBoolean()); assertNull(x7.getHost()); assertNull(x7.getPort()); - classConfig.inject(_scope, obj); - + classConfig.inject(scope, obj); + assertEquals("host.name.org", x7.getHost()); assertEquals(10, x7.getPort().intValue()); } - } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/ConstructorConfigurationTest.java b/system/general/src/test/java/org/wamblee/system/adapters/ConstructorConfigurationTest.java index 0cec6fba..ee57526f 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/ConstructorConfigurationTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/ConstructorConfigurationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import java.util.List; @@ -20,122 +20,145 @@ import java.util.List; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; +import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.test.AssertionUtils; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConstructorConfigurationTest extends AdapterTestCase { - - public void testGreedyUnique() { - ConstructorConfiguration config = new ConstructorConfiguration(X1.class) - .greedy(); - ProvidedInterface provided = new DefaultProvidedInterface("arg", - String.class); - List required = config.getRequiredInterfaces(); - - assertEquals(1, required.size()); - assertFalse(required.get(0).isOptional()); - - required.get(0).setProvider(provided); - - _scope.publishInterface(provided, "hello"); - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x1(hello)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } - - public void testGreedyNonUnique() { - try { - ConstructorConfiguration config = new ConstructorConfiguration( - X2.class).greedy(); - } catch (SystemAssemblyException e) { - // e.printStackTrace(); - return; - } - fail(); - } - - public void testSpecificConstructor() { - ConstructorConfiguration config = new ConstructorConfiguration(X2.class) - .select(String.class); - ProvidedInterface provided = new DefaultProvidedInterface("arg", - String.class); - List required = config.getRequiredInterfaces(); - - assertEquals(1, required.size()); - required.get(0).setProvider(provided); - - _scope.publishInterface(provided, "hello"); - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x2(hello)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } - - public void testSetValue() { - ConstructorConfiguration config = new ConstructorConfiguration(X1.class) - .greedy(); - config.getParameters().setValue(0, "bla"); - - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x1(bla)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } - - public void testOptionalValueProvided() { - ConstructorConfiguration config = new ConstructorConfiguration(X1.class) - .greedy(); - config.getParameters().setOptional(0); - ProvidedInterface provided = new DefaultProvidedInterface("arg", - String.class); - List required = config.getRequiredInterfaces(); - - assertEquals(1, required.size()); - required.get(0).setProvider(provided); - - _scope.publishInterface(provided, "hello"); - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x1(hello)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } - - public void testOptionalValueMissing() { - ConstructorConfiguration config = new ConstructorConfiguration(X1.class) - .greedy(); - config.getParameters().setOptional(0); - assertTrue(config.getRequiredInterfaces().get(0).isOptional()); - - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x1(null)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } - - public void testIgnoredNonPublic() { - ConstructorConfiguration config = new ConstructorConfiguration(X3.class) - .greedy(); - List required = config.getRequiredInterfaces(); - assertEquals(0, config.getParameters().getTypes().length); - } - - public void testNonPublicConstructor() { - ConstructorConfiguration config = new ConstructorConfiguration(X3.class) - .setNonPublic(true).greedy(); - ProvidedInterface provided = new DefaultProvidedInterface("arg", - String.class); - List required = config.getRequiredInterfaces(); - - assertEquals(1, required.size()); - assertFalse(required.get(0).isOptional()); - - required.get(0).setProvider(provided); - - _scope.publishInterface(provided, "hello"); - config.create(_scope); - - AssertionUtils.assertEquals(new String[] { "x3(hello)" }, AdapterTestCase.EVENT_TRACKER - .getEvents(Thread.currentThread()).toArray()); - } + public void testGreedyUnique() { + ConstructorConfiguration config = new ConstructorConfiguration(X1.class) + .greedy(); + ProvidedInterface provided = new DefaultProvidedInterface("arg", + String.class); + List required = config.getRequiredInterfaces(); + + assertEquals(1, required.size()); + assertFalse(required.get(0).isOptional()); + + required.get(0).setProvider(provided); + + Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x1(hello)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } + + public void testGreedyNonUnique() { + try { + ConstructorConfiguration config = new ConstructorConfiguration( + X2.class).greedy(); + ignoredVariable(config); + } catch (SystemAssemblyException e) { + // e.printStackTrace(); + return; + } + + fail(); + } + + private static void ignoredVariable(Object aObject) { + // for findbugs. + } + + public void testSpecificConstructor() { + ConstructorConfiguration config = new ConstructorConfiguration(X2.class) + .select(String.class); + ProvidedInterface provided = new DefaultProvidedInterface("arg", + String.class); + List required = config.getRequiredInterfaces(); + + assertEquals(1, required.size()); + required.get(0).setProvider(provided); + + Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x2(hello)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } + + public void testSetValue() { + ConstructorConfiguration config = new ConstructorConfiguration(X1.class) + .greedy(); + config.getParameters().setValue(0, "bla"); + + Scope scope = getScope(); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x1(bla)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } + + public void testOptionalValueProvided() { + ConstructorConfiguration config = new ConstructorConfiguration(X1.class) + .greedy(); + config.getParameters().setOptional(0); + + ProvidedInterface provided = new DefaultProvidedInterface("arg", + String.class); + List required = config.getRequiredInterfaces(); + + assertEquals(1, required.size()); + required.get(0).setProvider(provided); + + Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x1(hello)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } + + public void testOptionalValueMissing() { + ConstructorConfiguration config = new ConstructorConfiguration(X1.class) + .greedy(); + config.getParameters().setOptional(0); + assertTrue(config.getRequiredInterfaces().get(0).isOptional()); + + Scope scope = getScope(); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x1(null)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } + + public void testIgnoredNonPublic() { + ConstructorConfiguration config = new ConstructorConfiguration(X3.class) + .greedy(); + assertEquals(0, config.getParameters().getTypes().length); + } + + public void testNonPublicConstructor() { + ConstructorConfiguration config = new ConstructorConfiguration(X3.class) + .setNonPublic(true).greedy(); + ProvidedInterface provided = new DefaultProvidedInterface("arg", + String.class); + List required = config.getRequiredInterfaces(); + + assertEquals(1, required.size()); + assertFalse(required.get(0).isOptional()); + + required.get(0).setProvider(provided); + + Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + config.create(scope); + + AssertionUtils.assertEquals(new String[] { "x3(hello)" }, + AdapterTestCase.getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/DefaultContainerTest.java b/system/general/src/test/java/org/wamblee/system/adapters/DefaultContainerTest.java index 938a1222..e405b565 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/DefaultContainerTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/DefaultContainerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,72 +12,81 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import org.wamblee.system.core.Scope; + import org.wamblee.test.AssertionUtils; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultContainerTest extends AdapterTestCase { - public void testConstructorInjection() { ClassConfiguration x1Config = new ClassConfiguration(X1.class); x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); x1Config.getObjectConfig().getSetterConfig().initAllSetters(); - + ClassConfiguration x4Config = new ClassConfiguration(X4.class); x4Config.getObjectConfig().getSetterConfig().initAllSetters(); DefaultContainer container = new DefaultContainer("top").addComponent( - "x1", x1Config).addComponent("x4", x4Config); + "x1", x1Config).addComponent("x4", x4Config); Scope scope = container.start(); AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)" }, - EVENT_TRACKER.getEvents(Thread.currentThread()).toArray()); + getEventTracker().getEvents(Thread.currentThread()).toArray()); Object obj = scope.getRuntime("x1"); assertTrue(obj instanceof X1); obj = scope.getRuntime("x4"); assertTrue(obj instanceof X4); } - + public void testConstructorInjectionAndSetterInjection() { ClassConfiguration x1Config = new ClassConfiguration(X1.class); x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); x1Config.getObjectConfig().getSetterConfig().initAllSetters(); - - X8 x8 = new X8(null); - EVENT_TRACKER.clear(); + + X8 x8 = new X8(null); + getEventTracker().clear(); ClassConfiguration x4Config = new ClassConfiguration(X4.class); x4Config.getObjectConfig().getSetterConfig().initAllSetters(); - + ObjectConfiguration x8Config = new ObjectConfiguration(X8.class); x8Config.getSetterConfig().initAllSetters(); - + DefaultContainer container = new DefaultContainer("top").addComponent( - "x1", x1Config).addComponent("x4", x4Config).addComponent("x8", x8, x8Config); + "x1", x1Config).addComponent("x4", x4Config).addComponent("x8", x8, + x8Config); Scope scope = container.start(); AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)", - "x8.setX4(x4)"}, - EVENT_TRACKER.getEvents(Thread.currentThread()).toArray()); + "x8.setX4(x4)" }, getEventTracker().getEvents(Thread.currentThread()) + .toArray()); Object obj1 = scope.getRuntime("x1"); assertTrue(obj1 instanceof X1); + Object obj4 = scope.getRuntime("x4"); assertTrue(obj4 instanceof X4); + Object obj8 = scope.getRuntime("x8"); assertSame(x8, obj8); assertSame(obj4, x8.getX4()); } - - public void testWrongObjectType() { + + public void testWrongObjectType() { final DefaultContainer container = new DefaultContainer("top"); AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { - container.addComponent("x", "y", new ObjectConfiguration(Integer.class)); + container.addComponent("x", "y", new ObjectConfiguration( + Integer.class)); } }, IllegalArgumentException.class); } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/ObjectAdapterTest.java b/system/general/src/test/java/org/wamblee/system/adapters/ObjectAdapterTest.java index 0c6825e7..23c3bd9c 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/ObjectAdapterTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/ObjectAdapterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,6 @@ */ package org.wamblee.system.adapters; -import java.util.Collections; -import java.util.List; - import org.wamblee.system.container.Container; import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultProvidedInterface; @@ -25,48 +22,59 @@ import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.RequiredInterfaceComparator; import org.wamblee.system.core.Scope; + import org.wamblee.test.AssertionUtils; +import java.util.Collections; +import java.util.List; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class ObjectAdapterTest extends AdapterTestCase { + public void testSetterInjection() { + ClassConfiguration x1Config = new ClassConfiguration(X1.class); + x1Config.getObjectConfig().getSetterConfig().initAllSetters(); + x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); - public void testSetterInjection() { - - ClassConfiguration x1Config = new ClassConfiguration(X1.class); - x1Config.getObjectConfig().getSetterConfig().initAllSetters(); - x1Config.getConstructorConfig().getParameters().setValue(0, "hello"); - ClassConfiguration x4Config = new ClassConfiguration(X4.class); x4Config.getObjectConfig().getSetterConfig().initAllSetters(); + ObjectConfiguration x8Config = new ObjectConfiguration(X8.class); x8Config.getSetterConfig().initAllSetters(); - - X1 x1 = new X1(); + + X1 x1 = new X1(); X8 x8 = new X8(x1); - + ClassAdapter x1Adapter = new ClassAdapter("x1", x1Config); ClassAdapter x4Adapter = new ClassAdapter("x4", x4Config); ObjectAdapter x8Adapter = new ObjectAdapter("x8", x8, x8Config); - - Container container = new Container("top", new Component[] { - x1Adapter, x4Adapter, x8Adapter - }, new ProvidedInterface[0], new RequiredInterface[0]); - - EVENT_TRACKER.clear(); + + Container container = new Container("top", new Component[] { x1Adapter, + x4Adapter, x8Adapter }, new ProvidedInterface[0], + new RequiredInterface[0]); + + getEventTracker().clear(); + Scope scope = container.start(); - AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)", "x8.setX4(x4)" }, - EVENT_TRACKER.getEvents(Thread.currentThread()).toArray()); - + AssertionUtils.assertEquals(new String[] { "x1(hello)", "x4(x1)", + "x8.setX4(x4)" }, getEventTracker().getEvents(Thread.currentThread()) + .toArray()); + Object obj1 = scope.getRuntime(x1Adapter); - assertTrue(obj1 instanceof X1); + assertTrue(obj1 instanceof X1); + Object obj4 = scope.getRuntime(x4Adapter); assertTrue(obj4 instanceof X4); + Object obj8 = scope.getRuntime(x8Adapter); assertSame(x8, obj8); - + X4 x4 = (X4) obj4; - - + assertSame(x4, x8.getX4()); assertSame(x1, x8.getX1()); - } + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/SetterConfigurationTest.java b/system/general/src/test/java/org/wamblee/system/adapters/SetterConfigurationTest.java index aebdc3df..b9b2ac6c 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/SetterConfigurationTest.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/SetterConfigurationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.adapters; import java.lang.reflect.Method; @@ -27,338 +27,368 @@ import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.RequiredInterfaceComparator; +import org.wamblee.system.core.Scope; import org.wamblee.test.AssertionUtils; +/** + * + * @author $author$ + * @version $Revision$ + */ public class SetterConfigurationTest extends AdapterTestCase { + public void testOneSetter() { + SetterConfiguration config = new SetterConfiguration(X5.class); + config.initAllSetters(); + + List required = config.getRequiredInterfaces(); + assertEquals(1, required.size()); + assertEquals("setValue.0", required.get(0).getName()); + + ProvidedInterface provided = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided); + Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + + X5 obj = new X5(); + assertNull(obj.getValue()); + config.inject(scope, obj); + assertEquals("hello", obj.getValue()); + } + + public void testPrivateSetter() { + SetterConfiguration config = new SetterConfiguration(X5.class); + config.setNonPublic(true); + config.initAllSetters(); + + List required = new ArrayList( + config.getRequiredInterfaces()); + Collections.sort(required, new Comparator() { + @Override + public int compare(RequiredInterface aO1, RequiredInterface aO2) { + return aO1.getName().compareTo(aO2.getName()); + } + }); + assertEquals(2, required.size()); + assertEquals("setValue.0", required.get(0).getName()); + assertEquals("setXyz.0", required.get(1).getName()); + + ProvidedInterface providedString = new DefaultProvidedInterface( + "janse", String.class); + assertTrue(required.get(0).implementedBy(providedString)); + required.get(0).setProvider(providedString); + Scope scope = getScope(); + scope.publishInterface(providedString, "hello"); + + ProvidedInterface providedInt = new DefaultProvidedInterface("xxx", + Integer.class); + assertTrue(required.get(1).implementedBy(providedInt)); + required.get(1).setProvider(providedInt); + scope.publishInterface(providedInt, 100); + + X5 obj = new X5(); + assertNull(obj.getValue()); + assertNull(obj.getXyz()); + config.inject(scope, obj); + assertEquals("hello", obj.getValue()); + assertEquals(100, obj.getXyz().intValue()); + } + + public void testInheritance() { + SetterConfiguration config = new SetterConfiguration(X9.class); + config.setNonPublic(true); + config.initAllSetters(); + + List required = new ArrayList( + config.getRequiredInterfaces()); + Collections.sort(required, new Comparator() { + @Override + public int compare(RequiredInterface aO1, RequiredInterface aO2) { + return aO1.getName().compareTo(aO2.getName()); + } + }); + assertEquals(3, required.size()); + assertEquals("setFlag.0", required.get(0).getName()); + assertEquals("setValue.0", required.get(1).getName()); + assertEquals("setXyz.0", required.get(2).getName()); + + ProvidedInterface providedBoolean = new DefaultProvidedInterface( + "janse", Boolean.class); + assertTrue(required.get(0).implementedBy(providedBoolean)); + required.get(0).setProvider(providedBoolean); + Scope scope = getScope(); + scope.publishInterface(providedBoolean, true); + + ProvidedInterface providedString = new DefaultProvidedInterface( + "janse", String.class); + assertTrue(required.get(1).implementedBy(providedString)); + required.get(1).setProvider(providedString); + scope.publishInterface(providedString, "hello"); + + ProvidedInterface providedInt = new DefaultProvidedInterface("xxx", + Integer.class); + assertTrue(required.get(2).implementedBy(providedInt)); + required.get(2).setProvider(providedInt); + scope.publishInterface(providedInt, 100); + + X9 obj = new X9(); + assertNull(obj.getValue()); + assertNull(obj.getXyz()); + assertFalse(obj.isFlag()); + config.inject(scope, obj); + assertEquals("hello", obj.getValue()); + assertEquals(100, obj.getXyz().intValue()); + assertTrue(obj.isFlag()); + } + + public void testMultipleSetters() { + SetterConfiguration config = new SetterConfiguration(X6.class) + .initAllSetters(); + List required = config.getRequiredInterfaces(); + Collections.sort(required, new RequiredInterfaceComparator()); + assertEquals(2, required.size()); + assertEquals("setHost.0", required.get(0).getName()); + assertEquals("setPort.0", required.get(1).getName()); + + ProvidedInterface provided0 = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided0); + Scope scope = getScope(); + scope.publishInterface(provided0, "hello"); + + ProvidedInterface provided1 = new DefaultProvidedInterface("port", + Integer.class); + required.get(1).setProvider(provided1); + scope.publishInterface(provided1, 10); + + X6 obj = new X6(); + assertNull(obj.getHost()); + assertNull(obj.getPort()); + + config.inject(scope, obj); + assertEquals("hello", obj.getHost()); + assertEquals(10, obj.getPort().intValue()); + } + + public void testInvokeWrongType() { + final SetterConfiguration config = new SetterConfiguration(X5.class) + .initAllSetters(); + List required = config.getRequiredInterfaces(); + assertEquals(1, required.size()); + assertEquals("setValue.0", required.get(0).getName()); + + ProvidedInterface provided = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided); + final Scope scope = getScope(); + scope.publishInterface(provided, "hello"); + + final X6 obj = new X6(); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.inject(scope, obj); + } + }, IllegalArgumentException.class); + } + + public void testSetExplicitValue() { + SetterConfiguration config = new SetterConfiguration(X5.class) + .initAllSetters(); + config.values("setValue").setValue(0, "bladibla"); + + List required = config.getRequiredInterfaces(); + assertEquals(0, required.size()); + + X5 obj = new X5(); + assertNull(obj.getValue()); + Scope scope = getScope(); + config.inject(scope, obj); + assertEquals("bladibla", obj.getValue()); + } + + public void testClear() { + SetterConfiguration config = new SetterConfiguration(X6.class); + config.clear(); + + List required = config.getRequiredInterfaces(); + Collections.sort(required, new RequiredInterfaceComparator()); + assertEquals(0, required.size()); + + X6 obj = new X6(); + assertNull(obj.getHost()); + assertNull(obj.getPort()); + + Scope scope = getScope(); + config.inject(scope, obj); + + assertNull(obj.getHost()); + assertNull(obj.getPort()); + } + + public void testAddByName() { + SetterConfiguration config = new SetterConfiguration(X6.class); + config.clear().add("setHost"); + + List required = config.getRequiredInterfaces(); + Collections.sort(required, new RequiredInterfaceComparator()); + assertEquals(1, required.size()); + assertEquals("setHost.0", required.get(0).getName()); + + ProvidedInterface provided0 = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided0); + Scope scope = getScope(); + scope.publishInterface(provided0, "hello"); + + X6 obj = new X6(); + assertNull(obj.getHost()); + assertNull(obj.getPort()); + + config.inject(scope, obj); + assertEquals("hello", obj.getHost()); + assertNull(obj.getPort()); + } + + public void testAddByType() { + SetterConfiguration config = new SetterConfiguration(X6.class); + config.clear().addSetter(String.class); + + List required = config.getRequiredInterfaces(); + Collections.sort(required, new RequiredInterfaceComparator()); + assertEquals(1, required.size()); + assertEquals("setHost.0", required.get(0).getName()); + + ProvidedInterface provided0 = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided0); + Scope scope = getScope(); + scope.publishInterface(provided0, "hello"); + + X6 obj = new X6(); + assertNull(obj.getHost()); + assertNull(obj.getPort()); + + config.inject(scope, obj); + assertEquals("hello", obj.getHost()); + assertNull(obj.getPort()); + } + + public void testAddPrivate() { + final SetterConfiguration config = new SetterConfiguration(X5.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.add("xyz"); + } + }, IllegalArgumentException.class); + + config.setNonPublic(true); + config.clear(); + config.add("setXyz"); + assertEquals(1, config.getRequiredInterfaces().size()); + } - public void testOneSetter() { - SetterConfiguration config = new SetterConfiguration(X5.class); - config.initAllSetters(); - List required = config.getRequiredInterfaces(); - assertEquals(1, required.size()); - assertEquals("setValue.0", required.get(0).getName()); - - ProvidedInterface provided = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided); - _scope.publishInterface(provided, "hello"); - - X5 obj = new X5(); - assertNull(obj.getValue()); - config.inject(_scope, obj); - assertEquals("hello", obj.getValue()); - } - - public void testPrivateSetter() { - SetterConfiguration config = new SetterConfiguration(X5.class); - config.setNonPublic(true); - config.initAllSetters(); - List required = new ArrayList( - config.getRequiredInterfaces()); - Collections.sort(required, new Comparator() { - @Override - public int compare(RequiredInterface aO1, RequiredInterface aO2) { - return aO1.getName().compareTo(aO2.getName()); - } - }); - assertEquals(2, required.size()); - assertEquals("setValue.0", required.get(0).getName()); - assertEquals("setXyz.0", required.get(1).getName()); - - ProvidedInterface providedString = new DefaultProvidedInterface( - "janse", String.class); - assertTrue(required.get(0).implementedBy(providedString)); - required.get(0).setProvider(providedString); - _scope.publishInterface(providedString, "hello"); - - ProvidedInterface providedInt = new DefaultProvidedInterface("xxx", - Integer.class); - assertTrue(required.get(1).implementedBy(providedInt)); - required.get(1).setProvider(providedInt); - _scope.publishInterface(providedInt, 100); - - X5 obj = new X5(); - assertNull(obj.getValue()); - assertNull(obj.getXyz()); - config.inject(_scope, obj); - assertEquals("hello", obj.getValue()); - assertEquals(100, obj.getXyz().intValue()); - } - - public void testInheritance() { - SetterConfiguration config = new SetterConfiguration(X9.class); - config.setNonPublic(true); - config.initAllSetters(); - List required = new ArrayList( - config.getRequiredInterfaces()); - Collections.sort(required, new Comparator() { - @Override - public int compare(RequiredInterface aO1, RequiredInterface aO2) { - return aO1.getName().compareTo(aO2.getName()); - } - }); - assertEquals(3, required.size()); - assertEquals("setFlag.0", required.get(0).getName()); - assertEquals("setValue.0", required.get(1).getName()); - assertEquals("setXyz.0", required.get(2).getName()); - - ProvidedInterface providedBoolean = new DefaultProvidedInterface( - "janse", Boolean.class); - assertTrue(required.get(0).implementedBy(providedBoolean)); - required.get(0).setProvider(providedBoolean); - _scope.publishInterface(providedBoolean, true); - - ProvidedInterface providedString = new DefaultProvidedInterface( - "janse", String.class); - assertTrue(required.get(1).implementedBy(providedString)); - required.get(1).setProvider(providedString); - _scope.publishInterface(providedString, "hello"); - - ProvidedInterface providedInt = new DefaultProvidedInterface("xxx", - Integer.class); - assertTrue(required.get(2).implementedBy(providedInt)); - required.get(2).setProvider(providedInt); - _scope.publishInterface(providedInt, 100); - - X9 obj = new X9(); - assertNull(obj.getValue()); - assertNull(obj.getXyz()); - assertFalse(obj.isFlag()); - config.inject(_scope, obj); - assertEquals("hello", obj.getValue()); - assertEquals(100, obj.getXyz().intValue()); - assertTrue(obj.isFlag()); - } - - public void testMultipleSetters() { - SetterConfiguration config = new SetterConfiguration(X6.class).initAllSetters(); - List required = config.getRequiredInterfaces(); - Collections.sort(required, new RequiredInterfaceComparator()); - assertEquals(2, required.size()); - assertEquals("setHost.0", required.get(0).getName()); - assertEquals("setPort.0", required.get(1).getName()); - - ProvidedInterface provided0 = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided0); - _scope.publishInterface(provided0, "hello"); - - ProvidedInterface provided1 = new DefaultProvidedInterface("port", - Integer.class); - required.get(1).setProvider(provided1); - _scope.publishInterface(provided1, 10); - - X6 obj = new X6(); - assertNull(obj.getHost()); - assertNull(obj.getPort()); - - config.inject(_scope, obj); - assertEquals("hello", obj.getHost()); - assertEquals(10, obj.getPort().intValue()); - } - - public void testInvokeWrongType() { - final SetterConfiguration config = new SetterConfiguration(X5.class).initAllSetters(); - List required = config.getRequiredInterfaces(); - assertEquals(1, required.size()); - assertEquals("setValue.0", required.get(0).getName()); - - ProvidedInterface provided = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided); - _scope.publishInterface(provided, "hello"); - - final X6 obj = new X6(); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.inject(_scope, obj); - } - }, IllegalArgumentException.class); - } - - public void testSetExplicitValue() { - SetterConfiguration config = new SetterConfiguration(X5.class).initAllSetters(); - config.values("setValue").setValue(0, "bladibla"); - - List required = config.getRequiredInterfaces(); - assertEquals(0, required.size()); - - X5 obj = new X5(); - assertNull(obj.getValue()); - config.inject(_scope, obj); - assertEquals("bladibla", obj.getValue()); - } - - public void testClear() { - SetterConfiguration config = new SetterConfiguration(X6.class); - config.clear(); - List required = config.getRequiredInterfaces(); - Collections.sort(required, new RequiredInterfaceComparator()); - assertEquals(0, required.size()); - - X6 obj = new X6(); - assertNull(obj.getHost()); - assertNull(obj.getPort()); - - config.inject(_scope, obj); - - assertNull(obj.getHost()); - assertNull(obj.getPort()); - } - - public void testAddByName() { - SetterConfiguration config = new SetterConfiguration(X6.class); - config.clear().add("setHost"); - List required = config.getRequiredInterfaces(); - Collections.sort(required, new RequiredInterfaceComparator()); - assertEquals(1, required.size()); - assertEquals("setHost.0", required.get(0).getName()); - - ProvidedInterface provided0 = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided0); - _scope.publishInterface(provided0, "hello"); - - X6 obj = new X6(); - assertNull(obj.getHost()); - assertNull(obj.getPort()); - - config.inject(_scope, obj); - assertEquals("hello", obj.getHost()); - assertNull(obj.getPort()); - } - - public void testAddByType() { - SetterConfiguration config = new SetterConfiguration(X6.class); - config.clear().addSetter(String.class); - List required = config.getRequiredInterfaces(); - Collections.sort(required, new RequiredInterfaceComparator()); - assertEquals(1, required.size()); - assertEquals("setHost.0", required.get(0).getName()); - - ProvidedInterface provided0 = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided0); - _scope.publishInterface(provided0, "hello"); - - X6 obj = new X6(); - assertNull(obj.getHost()); - assertNull(obj.getPort()); - - config.inject(_scope, obj); - assertEquals("hello", obj.getHost()); - assertNull(obj.getPort()); - } - - public void testAddPrivate() { - X5 obj = new X5(); - final SetterConfiguration config = new SetterConfiguration(X5.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.add("xyz"); - } - }, IllegalArgumentException.class); - - config.setNonPublic(true); - config.clear(); - config.add("setXyz"); - assertEquals(1, config.getRequiredInterfaces().size()); - } - - public void testAddNonExisting() { - final SetterConfiguration config = new SetterConfiguration(X6.class); - config.clear(); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.add("bladibla"); - } - }, IllegalArgumentException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.addSetter(DataSource.class); - } - }, IllegalArgumentException.class); - } - - public void testAddByTypeNonUnique() { - final SetterConfiguration config = new SetterConfiguration(X11.class); - config.clear(); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.addSetter(String.class); - } - }, IllegalArgumentException.class); - } - - public void testRemove() { - SetterConfiguration config = new SetterConfiguration(X6.class).initAllSetters(); - config.remove("setPort"); - List required = config.getRequiredInterfaces(); - Collections.sort(required, new RequiredInterfaceComparator()); - assertEquals(1, required.size()); - assertEquals("setHost.0", required.get(0).getName()); - - ProvidedInterface provided0 = new DefaultProvidedInterface("janse", - String.class); - required.get(0).setProvider(provided0); - _scope.publishInterface(provided0, "hello"); - - X6 obj = new X6(); - assertNull(obj.getHost()); - assertNull(obj.getPort()); - - config.inject(_scope, obj); - assertEquals("hello", obj.getHost()); - assertNull(obj.getPort()); - } - - public void testRemoveByMethodObject() throws NoSuchMethodException { - SetterConfiguration config = new SetterConfiguration(X6.class).initAllSetters(); + public void testAddNonExisting() { + final SetterConfiguration config = new SetterConfiguration(X6.class); + config.clear(); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.add("bladibla"); + } + }, IllegalArgumentException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.addSetter(DataSource.class); + } + }, IllegalArgumentException.class); + } + + public void testAddByTypeNonUnique() { + final SetterConfiguration config = new SetterConfiguration(X11.class); + config.clear(); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.addSetter(String.class); + } + }, IllegalArgumentException.class); + } + + public void testRemove() { + SetterConfiguration config = new SetterConfiguration(X6.class) + .initAllSetters(); + config.remove("setPort"); + + List required = config.getRequiredInterfaces(); + Collections.sort(required, new RequiredInterfaceComparator()); + assertEquals(1, required.size()); + assertEquals("setHost.0", required.get(0).getName()); + + ProvidedInterface provided0 = new DefaultProvidedInterface("janse", + String.class); + required.get(0).setProvider(provided0); + Scope scope = getScope(); + scope.publishInterface(provided0, "hello"); + + X6 obj = new X6(); + assertNull(obj.getHost()); + assertNull(obj.getPort()); + + config.inject(scope, obj); + assertEquals("hello", obj.getHost()); + assertNull(obj.getPort()); + } + + public void testRemoveByMethodObject() throws NoSuchMethodException { + SetterConfiguration config = new SetterConfiguration(X6.class) + .initAllSetters(); config.remove(X6.class.getMethod("setPort", Integer.class)); + List required = config.getRequiredInterfaces(); Collections.sort(required, new RequiredInterfaceComparator()); assertEquals(1, required.size()); assertEquals("setHost.0", required.get(0).getName()); ProvidedInterface provided0 = new DefaultProvidedInterface("janse", - String.class); + String.class); required.get(0).setProvider(provided0); - _scope.publishInterface(provided0, "hello"); + Scope scope = getScope(); + scope.publishInterface(provided0, "hello"); X6 obj = new X6(); assertNull(obj.getHost()); assertNull(obj.getPort()); - config.inject(_scope, obj); + config.inject(scope, obj); assertEquals("hello", obj.getHost()); assertNull(obj.getPort()); } - public void testRemoveNonExisting() { - final SetterConfiguration config = new SetterConfiguration(X6.class); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - config.remove("bladibla"); - } - }, IllegalArgumentException.class); - } - - public void testOverridingSetters() { - SetterConfiguration config = new SetterConfiguration(X10.class).initAllSetters(); - assertEquals(2, config.getRequiredInterfaces().size()); - List methods = config.getSetters(); - assertEquals(2, methods.size()); - for (Method method: methods) { - assertEquals(X10.class, method.getDeclaringClass()); - } - - } + public void testRemoveNonExisting() { + final SetterConfiguration config = new SetterConfiguration(X6.class); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + config.remove("bladibla"); + } + }, IllegalArgumentException.class); + } + + public void testOverridingSetters() { + SetterConfiguration config = new SetterConfiguration(X10.class) + .initAllSetters(); + assertEquals(2, config.getRequiredInterfaces().size()); + + List methods = config.getSetters(); + assertEquals(2, methods.size()); + + for (Method method : methods) { + assertEquals(X10.class, method.getDeclaringClass()); + } + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X1.java b/system/general/src/test/java/org/wamblee/system/adapters/X1.java index b17a27c0..62226834 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X1.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X1.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,24 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X1 { - public X1() { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x1()"); - } + /** + * Creates a new X1 object. + */ + public X1() { + AdapterTestCase.getEventTracker().eventOccurred("x1()"); + } - public X1(String aValue) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x1(" + aValue + ")"); - } -} \ No newline at end of file + /** + * Creates a new X1 object. + * + */ + public X1(String aValue) { + AdapterTestCase.getEventTracker().eventOccurred("x1(" + aValue + ")"); + } +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X10.java b/system/general/src/test/java/org/wamblee/system/adapters/X10.java index fc8b90a5..787c9968 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X10.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X10.java @@ -1,26 +1,43 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X10 extends X6 { + @Override + public void setHost(String aHost) { + super.setHost(aHost); + } - - @Override - public void setHost(String aHost) { - super.setHost(aHost); - } - - @Override - public String getHost() { - return super.getHost(); - } - - @Override - public Integer getPort() { - return super.getPort(); - } - - @Override - public void setPort(Integer aPort) { - super.setPort(aPort); - } - + @Override + public String getHost() { + return super.getHost(); + } + + @Override + public Integer getPort() { + return super.getPort(); + } + + @Override + public void setPort(Integer aPort) { + super.setPort(aPort); + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X11.java b/system/general/src/test/java/org/wamblee/system/adapters/X11.java index 4ddc11eb..fa59d97a 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X11.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X11.java @@ -1,14 +1,29 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X11 { - - - public void setX(String aValue) { - - } - - public void setY(String aValue) { - - } + public void setX(String aValue) { + } + public void setY(String aValue) { + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X2.java b/system/general/src/test/java/org/wamblee/system/adapters/X2.java index 50a59027..987a4ee0 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X2.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X2.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,25 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X2 { - public X2(Integer aInteger) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x2(" + aInteger + ")"); - } + /** + * Creates a new X2 object. + * + */ + public X2(Integer aInteger) { + AdapterTestCase.getEventTracker().eventOccurred("x2(" + aInteger + ")"); + } - public X2(String aValue) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x2(" + aValue + ")"); - } -} \ No newline at end of file + /** + * Creates a new X2 object. + * + */ + public X2(String aValue) { + AdapterTestCase.getEventTracker().eventOccurred("x2(" + aValue + ")"); + } +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X3.java b/system/general/src/test/java/org/wamblee/system/adapters/X3.java index 4601a033..60f9e10e 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X3.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X3.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,12 +15,24 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X3 { - public X3() { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x3()"); - } + /** + * Creates a new X3 object. + */ + public X3() { + AdapterTestCase.getEventTracker().eventOccurred("x3()"); + } - protected X3(String aValue) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x3(" + aValue + ")"); - } -} \ No newline at end of file + /** + * Creates a new X3 object. + * + */ + protected X3(String aValue) { + AdapterTestCase.getEventTracker().eventOccurred("x3(" + aValue + ")"); + } +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X4.java b/system/general/src/test/java/org/wamblee/system/adapters/X4.java index 8d086a8b..25ab5394 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X4.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X4.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,16 +15,24 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X4 { + private X1 x1; + + /** + * Creates a new X4 object. + * + */ + public X4(X1 aX1) { + AdapterTestCase.getEventTracker().eventOccurred("x4(x1)"); + x1 = aX1; + } - private X1 _x1; - - public X4(X1 aX1) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x4(x1)"); - _x1 = aX1; - } - - public X1 getX1() { - return _x1; - } + public X1 getX1() { + return x1; + } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X5.java b/system/general/src/test/java/org/wamblee/system/adapters/X5.java index c0a82449..3efd316a 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X5.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X5.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,33 +15,41 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X5 { - - private String _value; - private Integer _xyz; - - public X5() { - - } - - public void setValue(String aValue) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x5.setValue(" + aValue + ")"); - _value = aValue; - } - - public String getValue() { - return _value; + private String value; + + private Integer xyz; + + /** + * Creates a new X5 object. + */ + public X5() { + } + + public void setValue(String aValue) { + AdapterTestCase.getEventTracker().eventOccurred("x5.setValue(" + aValue + + ")"); + value = aValue; + } + + public String getValue() { + return value; + } + + public void doSomething() { + // Empty. + } + + private void setXyz(int aXyz) { + xyz = aXyz; + } + + public Integer getXyz() { + return xyz; } - - public void doSomething() { - // Empty. - } - - private void setXyz(int aXyz) { - _xyz = aXyz; - } - - public Integer getXyz() { - return _xyz; - } -} \ No newline at end of file +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X6.java b/system/general/src/test/java/org/wamblee/system/adapters/X6.java index 06b7b5f5..d21b856a 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X6.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X6.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,28 +15,35 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X6 { - - private String _host; - private Integer _port; - - public X6() { - - } + private String host; + + private Integer port; - public Integer getPort() { - return _port; + /** + * Creates a new X6 object. + */ + public X6() { } - - public void setPort(Integer aPort) { - _port = aPort; + + public Integer getPort() { + return port; } - - public String getHost() { - return _host; + + public void setPort(Integer aPort) { + port = aPort; } - - public void setHost(String aHost) { - _host = aHost; + + public String getHost() { + return host; + } + + public void setHost(String aHost) { + host = aHost; } -} \ No newline at end of file +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X7.java b/system/general/src/test/java/org/wamblee/system/adapters/X7.java index 50520183..00d9d46c 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X7.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X7.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,33 +15,43 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X7 { - - private String _host; - private Integer _port; - private Boolean _boolean; - - public X7(Boolean aBoolean) { - _boolean = aBoolean; - } - - public Boolean getBoolean() { - return _boolean; + private String host; + + private Integer port; + + private Boolean flag; + + /** + * Creates a new X7 object. + * + */ + public X7(Boolean aBoolean) { + flag = aBoolean; } - public Integer getPort() { - return _port; + public Boolean getBoolean() { + return flag; } - - public void setPort(Integer aPort) { - _port = aPort; + + public Integer getPort() { + return port; } - - public String getHost() { - return _host; + + public void setPort(Integer aPort) { + port = aPort; + } + + public String getHost() { + return host; } - - public void setHost(String aHost) { - _host = aHost; + + public void setHost(String aHost) { + host = aHost; } -} \ No newline at end of file +} diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X8.java b/system/general/src/test/java/org/wamblee/system/adapters/X8.java index 84b450f1..5b507e1b 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X8.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X8.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,26 +15,35 @@ */ package org.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X8 { + private X1 x1; + + private X4 x4; + + /** + * Creates a new X8 object. + * + */ + public X8(X1 aX1) { + AdapterTestCase.getEventTracker().eventOccurred("x8(x1)"); + x1 = aX1; + } - private X1 _x1; - private X4 _x4; - - public X8(X1 aX1) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x8(x1)"); - _x1 = aX1; - } - - public void setX4(X4 aX4) { - AdapterTestCase.EVENT_TRACKER.eventOccurred("x8.setX4(x4)"); - _x4 = aX4; + public void setX4(X4 aX4) { + AdapterTestCase.getEventTracker().eventOccurred("x8.setX4(x4)"); + x4 = aX4; } - - public X4 getX4() { - return _x4; + + public X4 getX4() { + return x4; + } + + public X1 getX1() { + return x1; } - - public X1 getX1() { - return _x1; - } } diff --git a/system/general/src/test/java/org/wamblee/system/adapters/X9.java b/system/general/src/test/java/org/wamblee/system/adapters/X9.java index 6b30541a..a63ca5db 100644 --- a/system/general/src/test/java/org/wamblee/system/adapters/X9.java +++ b/system/general/src/test/java/org/wamblee/system/adapters/X9.java @@ -1,18 +1,39 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.system.adapters; +/** + * + * @author $author$ + * @version $Revision$ + */ public class X9 extends X5 { - - private boolean _flag; - - public X9() { - - } + private boolean flag; + + /** + * Creates a new X9 object. + */ + public X9() { + } + + public boolean isFlag() { + return flag; + } - public boolean isFlag() { - return _flag; - } - public void setFlag(boolean aFlag) { - _flag = aFlag; - } + flag = aFlag; + } } diff --git a/system/general/src/test/java/org/wamblee/system/components/DatabaseComponent.java b/system/general/src/test/java/org/wamblee/system/components/DatabaseComponent.java index afcc581a..9f3fc26b 100644 --- a/system/general/src/test/java/org/wamblee/system/components/DatabaseComponent.java +++ b/system/general/src/test/java/org/wamblee/system/components/DatabaseComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,50 +15,63 @@ */ package org.wamblee.system.components; -import java.util.Properties; - import org.wamblee.support.persistence.Database; import org.wamblee.support.persistence.DerbyDatabase; + import org.wamblee.system.components.ORMappingConfig.DatabaseType; import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.Scope; +import java.util.Properties; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatabaseComponent extends AbstractComponent { - - private static ProvidedInterface DB_PROPS = new DefaultProvidedInterface("dbProps", Properties.class); - - private Database _database; - - public DatabaseComponent(String aName, Database aDatabase) { - super(aName); - _database = aDatabase; + private static ProvidedInterface DB_PROPS = new DefaultProvidedInterface( + "dbProps", Properties.class); + + private Database database; + + /** + * Creates a new DatabaseComponent object. + * + */ + public DatabaseComponent(String aName, Database aDatabase) { + super(aName); + database = aDatabase; addProvidedInterface(DB_PROPS); } @Override protected Database doStart(Scope aScope) { - _database.start(); - + database.start(); + Properties props = new Properties(); - if ( _database instanceof DerbyDatabase ) { + + if (database instanceof DerbyDatabase) { props.put("database.type", DatabaseType.DERBY.toString()); - } else { - throw new IllegalArgumentException("Unknown database type " + _database); + } else { + throw new IllegalArgumentException("Unknown database type " + + database); } - //props.put("database.driver", _database.getDriverClassName()); - props.put("database.url", _database.getJdbcUrl()); - props.put("database.username", _database.getUsername()); - props.put("database.password", _database.getPassword()); + + // props.put("database.driver", database.getDriverClassName()); + props.put("database.url", database.getJdbcUrl()); + props.put("database.username", database.getUsername()); + props.put("database.password", database.getPassword()); addInterface(DB_PROPS, props, aScope); - return _database; + + return database; } @Override protected void doStop(Database aRuntime) { - _database.stop(); + database.stop(); } - } diff --git a/system/general/src/test/java/org/wamblee/system/components/DatabaseComponentFactory.java b/system/general/src/test/java/org/wamblee/system/components/DatabaseComponentFactory.java index 4c100fcc..5728b7f3 100644 --- a/system/general/src/test/java/org/wamblee/system/components/DatabaseComponentFactory.java +++ b/system/general/src/test/java/org/wamblee/system/components/DatabaseComponentFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,22 +12,26 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.components; import org.wamblee.support.persistence.DatabaseBuilder; + import org.wamblee.system.container.Container; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatabaseComponentFactory { - public static void addDatabaseConfig(Container aContainer) { try { - aContainer.addComponent(new DatabaseComponent("db", - DatabaseBuilder.getDatabase())); + aContainer.addComponent(new DatabaseComponent("db", DatabaseBuilder + .getDatabase())); } catch (Exception e) { throw new RuntimeException("Could not add database configuration", - e); + e); } } - } diff --git a/system/general/src/test/java/org/wamblee/system/container/Application.java b/system/general/src/test/java/org/wamblee/system/container/Application.java index 9392974f..37f7964e 100644 --- a/system/general/src/test/java/org/wamblee/system/container/Application.java +++ b/system/general/src/test/java/org/wamblee/system/container/Application.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.container; import org.wamblee.system.core.AbstractComponent; @@ -20,81 +20,110 @@ import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; + import org.wamblee.test.EventTracker; +/** + * + * @author $author$ + * @version $Revision$ + */ public class Application extends AbstractComponent { - public static RequiredInterface[] required(boolean aOptional, - String aPrefix) { - return new RequiredInterface[] { - new DefaultRequiredInterface(aPrefix + "string", String.class, - aOptional), - new DefaultRequiredInterface(aPrefix + "integer", - Integer.class, aOptional) }; - } + private EventTracker tracker; - public static RequiredInterface[] required(boolean aOptional) { - return required(aOptional, ""); - } + private String string; + + private Integer integer; - private EventTracker _tracker; - private String _string; - private Integer _integer; - private double _random; + private double random; + /** + * Creates a new Application object. + */ public Application() { this("application"); } + /** + * Creates a new Application object. + * + */ public Application(String aName) { this(aName, ""); } + /** + * Creates a new Application object. + * + */ public Application(String aName, String aPrefix) { - super(aName, new ProvidedInterface[0], required(false, - aPrefix)); - _random = Math.random(); + super(aName, new ProvidedInterface[0], required(false, aPrefix)); + random = Math.random(); } + /** + * Creates a new Application object. + * + */ public Application(boolean aIsOptinal) { super("application", new ProvidedInterface[0], required(true, "")); } + /** + * Creates a new Application object. + * + */ public Application(EventTracker aTracker) { this(); - _tracker = aTracker; + tracker = aTracker; + } + + public static RequiredInterface[] required(boolean aOptional, String aPrefix) { + return new RequiredInterface[] { + new DefaultRequiredInterface(aPrefix + "string", String.class, + aOptional), + new DefaultRequiredInterface(aPrefix + "integer", Integer.class, + aOptional) }; + } + + public static RequiredInterface[] required(boolean aOptional) { + return required(aOptional, ""); } @Override public Object doStart(Scope aScope) { track("start." + getName()); - _string = aScope.getInterfaceImplementation(getRequiredInterfaces() - .get(0).getProvider(), String.class); - _integer = aScope.getInterfaceImplementation(getRequiredInterfaces() - .get(1).getProvider(), Integer.class); - return _random; + string = aScope.getInterfaceImplementation(getRequiredInterfaces().get( + 0).getProvider(), String.class); + integer = aScope.getInterfaceImplementation(getRequiredInterfaces() + .get(1).getProvider(), Integer.class); + + return random; } public String getString() { - return _string; + return string; } public Integer getInteger() { - return _integer; + return integer; } @Override public void doStop(Object aRuntime) { track("stop." + getName()); - if (_random != (Double) aRuntime) { - throw new IllegalArgumentException("Wrong runtime: expected " - + _random + " but got " + aRuntime); + + if (random != (Double) aRuntime) { + throw new IllegalArgumentException("Wrong runtime: expected " + + random + " but got " + aRuntime); } } private void track(String aString) { - if (_tracker == null) { + if (tracker == null) { return; } - _tracker.eventOccurred(aString); + + tracker.eventOccurred(aString); } } diff --git a/system/general/src/test/java/org/wamblee/system/container/ContainerTest.java b/system/general/src/test/java/org/wamblee/system/container/ContainerTest.java index a7589fe4..2721c511 100644 --- a/system/general/src/test/java/org/wamblee/system/container/ContainerTest.java +++ b/system/general/src/test/java/org/wamblee/system/container/ContainerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,16 +12,14 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.container; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - import junit.framework.TestCase; +import org.junit.internal.requests.IgnoredClassRunner; import org.wamblee.general.Pair; + import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; @@ -32,714 +30,740 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.StringComponent; import org.wamblee.system.core.SystemAssemblyException; + import org.wamblee.test.AssertionUtils; import org.wamblee.test.EventTracker; -public class ContainerTest extends TestCase { +import java.io.Serializable; + +import java.util.ArrayList; +import java.util.List; - private EventTracker _tracker; - - @Override - protected void setUp() throws Exception { - super.setUp(); - _tracker = new EventTracker(); - } - - private static class MyMultiple implements Serializable, Runnable { - @Override - public void run() { - // Empty - } - } - - private List> createProvidedInput( - ProvidedInterface[] aProvided, Component aProvider) { - List> result = new ArrayList>(); - for (ProvidedInterface provided : aProvided) { - result.add(new Pair(provided, - aProvider)); - } - return result; - } - - public void testEnvironmentApplication() { - Environment environment = new Environment(_tracker); - Application application = new Application(_tracker); - Container container = new Container("root", new Component[] { - environment, application }, new ProvidedInterface[0], - new RequiredInterface[0]); - Scope scope = container.start(); - assertTrue(container.isSealed()); - AssertionUtils.assertEquals(new String[] { "start.environment", - "start.application" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - assertEquals(0, scope.getProvidedInterfaces().size()); - - assertEquals(environment.getString(), application.getString()); - assertEquals(environment.getInteger(), application.getInteger()); - - } - - public void testEnvironmentApplicationSimpleConstructor() { - Environment environment = new Environment(_tracker); - Application application = new Application(_tracker); - Container container = new Container("root").addComponent(environment) - .addComponent(application); - - Scope scope = container.start(); - AssertionUtils.assertEquals(new String[] { "start.environment", - "start.application" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - assertEquals(0, scope.getProvidedInterfaces().size()); - - assertEquals(environment.getString(), application.getString()); - assertEquals(environment.getInteger(), application.getInteger()); - - } - - public void testApplicationEnvironment() { - try { - Component environment = new Environment(); - Component application = new Application(); - Container container = new Container("root", new Component[] { - application, environment }, new ProvidedInterface[0], - new RequiredInterface[0]); - container.start(); - } catch (SystemAssemblyException e) { - // e.printStackTrace(); - return; - } - fail(); - } - - public void testComposite() { - Component environment = new Environment(_tracker); - Component application = new Application(_tracker); - assertEquals(0, _tracker.getEventCount()); - - Container system = new Container("all", new Component[] { environment, - application }, new ProvidedInterface[0], - new RequiredInterface[0]); - Scope runtime = system.start(); - List required = system.getRequiredInterfaces(); - assertEquals(0, required.size()); - List provided = system.getProvidedInterfaces(); - assertEquals(0, provided.size()); - - AssertionUtils.assertEquals(new String[] { "start.environment", - "start.application" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - _tracker.clear(); - - system.stop(runtime); - AssertionUtils.assertEquals(new String[] { "stop.application", - "stop.environment" }, _tracker - .getEvents(Thread.currentThread()).toArray(new String[0])); - - } - - public void testCompositeWithWrongProvidedInfo() { - try { - Component environment = new Environment(); - Component application = new Application(); - Container system = new Container("all", new Component[] { - environment, application }, - new ProvidedInterface[] { new DefaultProvidedInterface( - "float", Float.class) }, - new DefaultRequiredInterface[0]); - system.validate(); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testCompositeRequiredInterfaceNotProvided() { - try { - Component environment = new Environment(); - Component application = new Application(); - Container system = new Container("all", new Component[] { - environment, application }, new ProvidedInterface[0], - new RequiredInterface[] { new DefaultRequiredInterface( - "string", String.class) }); - system.start(); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testCompositeWithSuperfluousRequiredInfo() { - Component environment = new Environment(); - Component application = new Application(); - Container system = new Container("all", new Component[] { environment, - application }, new ProvidedInterface[0], - new RequiredInterface[] { new DefaultRequiredInterface("float", - Float.class) }); - system.getRequiredInterfaces().get(0).setProvider( - new DefaultProvidedInterface("hallo", Float.class)); - system.start(); - List required = system.getRequiredInterfaces(); - assertEquals(1, required.size()); - List provided = system.getProvidedInterfaces(); - assertEquals(0, provided.size()); - } - - public void testCompositeWithExternalDependencesNotProvided() { - try { - Component application = new Application(); - - Container system = new Container("all", - new Component[] { application }, new ProvidedInterface[0], - application.getRequiredInterfaces().toArray( - new RequiredInterface[0])); - system.start(); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testDuplicateComponent() { - try { - Component comp1 = new Application(); - Component comp2 = new Application(); - Container system = new Container("top"); - system.addComponent(comp1).addComponent(comp2); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testInconsistentHierarchy() { - try { - Component comp = new Application(); - Container system = new Container("top").addComponent(comp); - Container system2 = new Container("top2").addComponent(comp); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testCompositeWithExternalDependencesProvided() { - - Component environment = new Environment(); - Component application = new Application(); - Container system = new Container("all", - new Component[] { application }, new ProvidedInterface[0], - application.getRequiredInterfaces().toArray( - new RequiredInterface[0])); - environment.start(new DefaultScope(new ProvidedInterface[0])); - system.getRequiredInterfaces().get(0).setProvider( - environment.getProvidedInterfaces().get(0)); - system.getRequiredInterfaces().get(1).setProvider( - environment.getProvidedInterfaces().get(1)); - - system.start(); - List required = system.getRequiredInterfaces(); - assertEquals(2, required.size()); - List provided = system.getProvidedInterfaces(); - assertEquals(0, provided.size()); - - } - - public void testAmbiguousInterfaces() { - try { - Component environment1 = new Environment(); - Component environment2 = new Environment(); - Component application = new Application(); - Container container = new Container("root", new Component[] { - environment1, environment2, application }, - new ProvidedInterface[0], new RequiredInterface[0]); - container.start(); - - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testIncompleteRequirements() { - try { - Component application = new Application(); - Container system = new Container("all", - new Component[] { application }, new ProvidedInterface[0], - new RequiredInterface[0]); - system.start(); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testEnvironmentApplicationRollbackOnException() - throws Exception { - Environment environment = new Environment(_tracker); - Application application = new Application() { - @Override - public Object doStart(Scope aScope) { - throw new RuntimeException(); - } - }; - - try { - Container container = new Container("root", new Component[] { - environment, application }, new ProvidedInterface[0], - new RequiredInterface[0]); - - container.start(); - } catch (RuntimeException e) { - AssertionUtils.assertEquals(new String[] { "start.environment", - "stop.environment" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - return; - } - fail(); - } - - public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop() - throws Exception { - - Environment environment = new Environment(_tracker); - // Application 1 will throw an exception while stopping. - Application application1 = new Application("app1") { - @Override - public void doStop(Object aRuntime) { - throw new RuntimeException(); - } - }; - - // application 2 will throw an exception while starting - Application application2 = new Application("app2") { - public Object doStart(Scope aScope) { - throw new RuntimeException(); - } - }; - - try { - Container container = new Container("root", new Component[] { - environment, application1, application2 }, - new ProvidedInterface[0], new RequiredInterface[0]); - - container.start(); - } catch (RuntimeException e) { - AssertionUtils.assertEquals(new String[] { "start.environment", - "stop.environment" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - return; - } - fail(); - } - - public void testOptionalRequiredInterfaceProvidedOptionalInternal() { - Application application = new Application(true); - Container container = new Container("top", - new Component[] { application }, new ProvidedInterface[0], - Application.required(true)); - Environment env = new Environment(); - container.getRequiredInterfaces().get(0).setProvider( - env.getProvidedInterfaces().get(0)); - container.getRequiredInterfaces().get(1).setProvider( - env.getProvidedInterfaces().get(1)); - Scope external = new DefaultScope(env.getProvidedInterfaces()); - env.start(external); - - container.start(external); - assertSame(env.getProvidedInterfaces().get(0), container - .getRequiredInterfaces().get(0).getProvider()); - assertSame(env.getProvidedInterfaces().get(1), container - .getRequiredInterfaces().get(1).getProvider()); - assertSame(env.getProvidedInterfaces().get(0), application - .getRequiredInterfaces().get(0).getProvider()); - assertSame(env.getProvidedInterfaces().get(1), application - .getRequiredInterfaces().get(1).getProvider()); - } - - public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() { - Application application = new Application(true); - Container container = new Container("top", - new Component[] { application }, new ProvidedInterface[0], - Application.required(true)); - Environment env = new Environment(); - container.getRequiredInterfaces().get(0).setProvider( - env.getProvidedInterfaces().get(0)); - Scope external = new DefaultScope(new ProvidedInterface[0]); - external.publishInterface(env.getProvidedInterfaces().get(0), env - .getString()); - container.start(external); - assertSame(env.getProvidedInterfaces().get(0), container - .getRequiredInterfaces().get(0).getProvider()); - assertNull(container.getRequiredInterfaces().get(1).getProvider()); - assertSame(env.getProvidedInterfaces().get(0), application - .getRequiredInterfaces().get(0).getProvider()); - assertNull(application.getRequiredInterfaces().get(1).getProvider()); - } - - public void testOptionalRequiredInterfaceProvidedMandatoryInternal() { - Application application = new Application(); - Container container = new Container("top", - new Component[] { application }, new ProvidedInterface[0], - Application.required(true)); - Environment env = new Environment(); - container.getRequiredInterfaces().get(0).setProvider( - env.getProvidedInterfaces().get(0)); - container.getRequiredInterfaces().get(1).setProvider( - env.getProvidedInterfaces().get(1)); - try { - container.start(); - } catch (SystemAssemblyException e) { - return; - } - fail(); - } - - public void testSealed() { - final Container container = new Container("xx"); - assertFalse(container.isSealed()); - container.start(); - assertTrue(container.isSealed()); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.addComponent(new Application()); - } - }, SystemAssemblyException.class); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectRequiredProvided("x", "y", "a", "b"); - } - }, SystemAssemblyException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalRequired("x", "y", "a"); - } - }, SystemAssemblyException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalProvided("x", "y", "z"); - } - }, SystemAssemblyException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.addProvidedInterface(new DefaultProvidedInterface( - "xx", String.class)); - } - }, SystemAssemblyException.class); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.addRequiredInterface(new DefaultRequiredInterface( - "xx", String.class)); - } - }, SystemAssemblyException.class); - } - - public void testRestriction() { - Environment env1 = new Environment("env1"); - Environment env2 = new Environment("env2"); - Application app = new Application("app"); - Container container = new Container("top").addComponent(env1) - .addComponent(env2).addComponent(app); - container.connectRequiredProvided("app", null, "env1", null); - container.start(); - assertEquals(env1.getString(), app.getString()); - assertEquals(env1.getInteger(), app.getInteger()); - assertFalse(env2.getString().equals(app.getString())); - assertFalse(env2.getInteger().equals(app.getInteger())); - } - - public void testRestrictionWithFromAndToInterfaceName() { - Environment env1 = new Environment("env1"); - Environment env2 = new Environment("env2"); - Application app = new Application("app"); - Container container = new Container("top").addComponent(env1) - .addComponent(env2).addComponent(app); - container.connectRequiredProvided("app", app.getRequiredInterfaces() - .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0) - .getName()); - container.connectRequiredProvided("app", app.getRequiredInterfaces() - .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1) - .getName()); - container.start(); - assertEquals(env1.getString(), app.getString()); - assertEquals(env2.getInteger(), app.getInteger()); - assertFalse(env2.getString().equals(app.getString())); - assertFalse(env1.getInteger().equals(app.getInteger())); - } - - public void testRestrictionWrongComponentNames() { - Environment env1 = new Environment("env1"); - Environment env2 = new Environment("env2"); - Application app = new Application("app"); - final Container container = new Container("top").addComponent(env1) - .addComponent(env2).addComponent(app); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectRequiredProvided("app2", null, "env1", null); - } - }, SystemAssemblyException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectRequiredProvided("app", null, "env3", null); - } - }, SystemAssemblyException.class); - } - - public void testRestrictionWrongInterfaceNames() { - final Environment env1 = new Environment("env1"); - Environment env2 = new Environment("env2"); - final Application app = new Application("app"); - final Container container = new Container("top").addComponent(env1) - .addComponent(env2).addComponent(app); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectRequiredProvided("app", app - .getRequiredInterfaces().get(0).getName() - + "xxx", "env1", null); - } - }, SystemAssemblyException.class); - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectRequiredProvided("app", null, "env1", env1 - .getProvidedInterfaces().get(0).getName() - + "yyy"); - } - }, SystemAssemblyException.class); - } - - public void testProvidedInDifferentScopes() { - // Scoping problem occurred. Externally and internally provided - // components clashed - // because unique id generation in the scope was wrong. - - StringComponent str = new StringComponent("string"); - Application app = new Application("app"); - Container container = new Container("top").addComponent(str) - .addComponent(app); - container.addRequiredInterface(new DefaultRequiredInterface("integer", - Integer.class)); - - ProvidedInterface provided = new DefaultProvidedInterface("hallo", - Integer.class); - container.getRequiredInterfaces().get(0).setProvider(provided); - - Scope external = new DefaultScope(new ProvidedInterface[0]); - external.publishInterface(provided, 100); - Scope scope = container.start(external); - } - - public void testProvidedInterfaces() { - Environment env = new Environment(_tracker); - Container envcontainer = new Container("0").addComponent(env) - .addProvidedInterface( - new DefaultProvidedInterface("string", String.class)) - .addProvidedInterface( - new DefaultProvidedInterface("integer", Integer.class)); - Scope scope = envcontainer.start(); - - AssertionUtils.assertEquals(new String[] { "start.environment" }, - _tracker.getEvents(Thread.currentThread()).toArray( - new String[0])); - - envcontainer.stop(scope); - } - - public void testCoupleTwoContainers() { - Environment env = new Environment(_tracker); - Container envcontainer = new Container("0").addComponent(env) - .addProvidedInterface( - new DefaultProvidedInterface("string", String.class)) - .addProvidedInterface( - new DefaultProvidedInterface("integer", Integer.class)); - - Application app = new Application(_tracker); - Container appcontainer = new Container("1").addComponent(app) - .addRequiredInterface( - new DefaultRequiredInterface("string", String.class)) - .addRequiredInterface( - new DefaultRequiredInterface("integer", Integer.class)); - - Container top = new Container("top"); - top.addComponent(envcontainer).addComponent(appcontainer); - - top.start(); - AssertionUtils.assertEquals(new String[] { "start.environment", - "start.application" }, _tracker.getEvents( - Thread.currentThread()).toArray(new String[0])); - - } - - public void testNonUniqueRequiredInterface() { - final Container container = new Container("top"); - container.addRequiredInterface(new DefaultRequiredInterface("i", - Integer.class)); - container.addRequiredInterface(new DefaultRequiredInterface("x", - String.class)); - container.addRequiredInterface(new DefaultRequiredInterface("y", - String.class)); - - Application app = new Application("1"); - container.addComponent(app); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.start(); - } - }, SystemAssemblyException.class); - - container.connectExternalRequired("1", app.getRequiredInterfaces().get( - 0).getName(), "y"); - - ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class); - ProvidedInterface x = new DefaultProvidedInterface("x", String.class); - ProvidedInterface y = new DefaultProvidedInterface("y", String.class); - - Scope externalScope = new DefaultScope(new ProvidedInterface[0]); - - externalScope.publishInterface(i, 100); - externalScope.publishInterface(x, "x-value"); - externalScope.publishInterface(y, "y-value"); - - container.getRequiredInterfaces().get(0).setProvider(i); - container.getRequiredInterfaces().get(1).setProvider(x); - container.getRequiredInterfaces().get(2).setProvider(y); - - Scope runtime = container.start(externalScope); - - assertEquals("y-value", app.getString()); - - } - - public void testNonUniqueRequiredInterfaceWrongNames() { - final Container container = new Container("top"); - container.addRequiredInterface(new DefaultRequiredInterface("i", - Integer.class)); - container.addRequiredInterface(new DefaultRequiredInterface("x", - String.class)); - container.addRequiredInterface(new DefaultRequiredInterface("y", - String.class)); - - final Application app = new Application("1"); - container.addComponent(app); - - // wrong component name. - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalRequired("2", "x", "y"); - } - }, SystemAssemblyException.class); - - // Wrong interface name of component. - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalRequired("1", app - .getRequiredInterfaces().get(0).getName() - + "xxx", "y"); - } - }, SystemAssemblyException.class); - - // Wrong external interface name of container - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalRequired("1", app - .getRequiredInterfaces().get(0).getName(), "z"); - } - }, SystemAssemblyException.class); - } - - public void testNonUniqueProvidedInterface() { - - final Container container = new Container("top") - .addProvidedInterface(new DefaultProvidedInterface("external", - String.class)); - Environment env1 = new Environment("env1"); - Environment env2 = new Environment("env2"); - - container.addComponent(env1); - container.addComponent(env2); - - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.start(); - } - }, SystemAssemblyException.class); - - // now choose env2 - - container.connectExternalProvided(container.getProvidedInterfaces() - .get(0).getName(), env2.getName(), env2.getProvidedInterfaces() - .get(0).getName()); - - Scope scope = container.start(); - - // check the value of the provided interface of the container - - String value = scope.getInterfaceImplementation(container - .getProvidedInterfaces().get(0), String.class); - assertNotNull(value); - assertEquals(value, env2.getString()); - assertFalse(value.equals(env1.getString())); - } - - public void testNonUniqueProvidedInterfaceWrongNames() { - - final Container container = new Container("top") - .addProvidedInterface(new DefaultProvidedInterface("external", - String.class)); - final Environment env1 = new Environment("env1"); - final Environment env2 = new Environment("env2"); - - container.addComponent(env1); - container.addComponent(env2); - - // Wrong external provided interface name - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalProvided(container - .getProvidedInterfaces().get(0).getName() - + "xx", "env1", env1.getProvidedInterfaces().get(0) - .getName()); - } - }, SystemAssemblyException.class); - - // Wrong provided interface name. - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalProvided(container - .getProvidedInterfaces().get(0).getName(), "env1", env1 - .getProvidedInterfaces().get(0).getName() - + "xx"); - } - }, SystemAssemblyException.class); - - // Wrong provided component - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { - @Override - public void run() throws Exception { - container.connectExternalProvided(container - .getProvidedInterfaces().get(0).getName(), "env3", env1 - .getProvidedInterfaces().get(0).getName()); - } - }, SystemAssemblyException.class); - } +/** + * + * @author $author$ + * @version $Revision$ + */ +public class ContainerTest extends TestCase { + private EventTracker tracker; + + @Override + protected void setUp() throws Exception { + super.setUp(); + tracker = new EventTracker(); + } + + private List> createProvidedInput( + ProvidedInterface[] aProvided, Component aProvider) { + List> result = new ArrayList>(); + + for (ProvidedInterface provided : aProvided) { + result.add(new Pair(provided, + aProvider)); + } + + return result; + } + + public void testEnvironmentApplication() { + Environment environment = new Environment(tracker); + Application application = new Application(tracker); + Container container = new Container("root", new Component[] { + environment, application }, new ProvidedInterface[0], + new RequiredInterface[0]); + Scope scope = container.start(); + assertTrue(container.isSealed()); + AssertionUtils.assertEquals(new String[] { "start.environment", + "start.application" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + assertEquals(0, scope.getProvidedInterfaces().size()); + + assertEquals(environment.getString(), application.getString()); + assertEquals(environment.getInteger(), application.getInteger()); + } + + public void testEnvironmentApplicationSimpleConstructor() { + Environment environment = new Environment(tracker); + Application application = new Application(tracker); + Container container = new Container("root").addComponent(environment) + .addComponent(application); + + Scope scope = container.start(); + AssertionUtils.assertEquals(new String[] { "start.environment", + "start.application" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + assertEquals(0, scope.getProvidedInterfaces().size()); + + assertEquals(environment.getString(), application.getString()); + assertEquals(environment.getInteger(), application.getInteger()); + } + + public void testApplicationEnvironment() { + try { + Component environment = new Environment(); + Component application = new Application(); + Container container = new Container("root", new Component[] { + application, environment }, new ProvidedInterface[0], + new RequiredInterface[0]); + container.start(); + } catch (SystemAssemblyException e) { + // e.printStackTrace(); + return; + } + + fail(); + } + + public void testComposite() { + Component environment = new Environment(tracker); + Component application = new Application(tracker); + assertEquals(0, tracker.getEventCount()); + + Container system = new Container("all", new Component[] { environment, + application }, new ProvidedInterface[0], new RequiredInterface[0]); + Scope runtime = system.start(); + List required = system.getRequiredInterfaces(); + assertEquals(0, required.size()); + + List provided = system.getProvidedInterfaces(); + assertEquals(0, provided.size()); + + AssertionUtils.assertEquals(new String[] { "start.environment", + "start.application" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + tracker.clear(); + + system.stop(runtime); + AssertionUtils.assertEquals(new String[] { "stop.application", + "stop.environment" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + } + + public void testCompositeWithWrongProvidedInfo() { + try { + Component environment = new Environment(); + Component application = new Application(); + Container system = new Container("all", new Component[] { + environment, application }, + new ProvidedInterface[] { new DefaultProvidedInterface("float", + Float.class) }, new DefaultRequiredInterface[0]); + system.validate(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testCompositeRequiredInterfaceNotProvided() { + try { + Component environment = new Environment(); + Component application = new Application(); + Container system = new Container("all", new Component[] { + environment, application }, new ProvidedInterface[0], + new RequiredInterface[] { new DefaultRequiredInterface( + "string", String.class) }); + system.start(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testCompositeWithSuperfluousRequiredInfo() { + Component environment = new Environment(); + Component application = new Application(); + Container system = new Container("all", new Component[] { environment, + application }, new ProvidedInterface[0], + new RequiredInterface[] { new DefaultRequiredInterface("float", + Float.class) }); + system.getRequiredInterfaces().get(0).setProvider( + new DefaultProvidedInterface("hallo", Float.class)); + system.start(); + + List required = system.getRequiredInterfaces(); + assertEquals(1, required.size()); + + List provided = system.getProvidedInterfaces(); + assertEquals(0, provided.size()); + } + + public void testCompositeWithExternalDependencesNotProvided() { + try { + Component application = new Application(); + + Container system = new Container("all", + new Component[] { application }, new ProvidedInterface[0], + application.getRequiredInterfaces().toArray( + new RequiredInterface[0])); + system.start(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testDuplicateComponent() { + try { + Component comp1 = new Application(); + Component comp2 = new Application(); + Container system = new Container("top"); + system.addComponent(comp1).addComponent(comp2); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testInconsistentHierarchy() { + try { + Component comp = new Application(); + Container system = new Container("top").addComponent(comp); + Container system2 = new Container("top2").addComponent(comp); + + ignoredVariable(system); + ignoredVariable(system2); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + private static void ignoredVariable(Object aObject) { + // for findbugs. + } + + public void testCompositeWithExternalDependencesProvided() { + Component environment = new Environment(); + Component application = new Application(); + Container system = new Container("all", + new Component[] { application }, new ProvidedInterface[0], + application.getRequiredInterfaces().toArray( + new RequiredInterface[0])); + environment.start(new DefaultScope(new ProvidedInterface[0])); + system.getRequiredInterfaces().get(0).setProvider( + environment.getProvidedInterfaces().get(0)); + system.getRequiredInterfaces().get(1).setProvider( + environment.getProvidedInterfaces().get(1)); + + system.start(); + + List required = system.getRequiredInterfaces(); + assertEquals(2, required.size()); + + List provided = system.getProvidedInterfaces(); + assertEquals(0, provided.size()); + } + + public void testAmbiguousInterfaces() { + try { + Component environment1 = new Environment(); + Component environment2 = new Environment(); + Component application = new Application(); + Container container = new Container("root", new Component[] { + environment1, environment2, application }, + new ProvidedInterface[0], new RequiredInterface[0]); + container.start(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testIncompleteRequirements() { + try { + Component application = new Application(); + Container system = new Container("all", + new Component[] { application }, new ProvidedInterface[0], + new RequiredInterface[0]); + system.start(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testEnvironmentApplicationRollbackOnException() + throws Exception { + Environment environment = new Environment(tracker); + Application application = new Application() { + @Override + public Object doStart(Scope aScope) { + throw new RuntimeException(); + } + }; + + try { + Container container = new Container("root", new Component[] { + environment, application }, new ProvidedInterface[0], + new RequiredInterface[0]); + + container.start(); + } catch (RuntimeException e) { + AssertionUtils.assertEquals(new String[] { "start.environment", + "stop.environment" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + + return; + } + + fail(); + } + + public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop() + throws Exception { + Environment environment = new Environment(tracker); + + // Application 1 will throw an exception while stopping. + Application application1 = new Application("app1") { + @Override + public void doStop(Object aRuntime) { + throw new RuntimeException(); + } + }; + + // application 2 will throw an exception while starting + Application application2 = new Application("app2") { + public Object doStart(Scope aScope) { + throw new RuntimeException(); + } + }; + + try { + Container container = new Container("root", new Component[] { + environment, application1, application2 }, + new ProvidedInterface[0], new RequiredInterface[0]); + + container.start(); + } catch (RuntimeException e) { + AssertionUtils.assertEquals(new String[] { "start.environment", + "stop.environment" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + + return; + } + + fail(); + } + + public void testOptionalRequiredInterfaceProvidedOptionalInternal() { + Application application = new Application(true); + Container container = new Container("top", + new Component[] { application }, new ProvidedInterface[0], + Application.required(true)); + Environment env = new Environment(); + container.getRequiredInterfaces().get(0).setProvider( + env.getProvidedInterfaces().get(0)); + container.getRequiredInterfaces().get(1).setProvider( + env.getProvidedInterfaces().get(1)); + + Scope external = new DefaultScope(env.getProvidedInterfaces()); + env.start(external); + + container.start(external); + assertSame(env.getProvidedInterfaces().get(0), container + .getRequiredInterfaces().get(0).getProvider()); + assertSame(env.getProvidedInterfaces().get(1), container + .getRequiredInterfaces().get(1).getProvider()); + assertSame(env.getProvidedInterfaces().get(0), application + .getRequiredInterfaces().get(0).getProvider()); + assertSame(env.getProvidedInterfaces().get(1), application + .getRequiredInterfaces().get(1).getProvider()); + } + + public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() { + Application application = new Application(true); + Container container = new Container("top", + new Component[] { application }, new ProvidedInterface[0], + Application.required(true)); + Environment env = new Environment(); + container.getRequiredInterfaces().get(0).setProvider( + env.getProvidedInterfaces().get(0)); + + Scope external = new DefaultScope(new ProvidedInterface[0]); + external.publishInterface(env.getProvidedInterfaces().get(0), env + .getString()); + container.start(external); + assertSame(env.getProvidedInterfaces().get(0), container + .getRequiredInterfaces().get(0).getProvider()); + assertNull(container.getRequiredInterfaces().get(1).getProvider()); + assertSame(env.getProvidedInterfaces().get(0), application + .getRequiredInterfaces().get(0).getProvider()); + assertNull(application.getRequiredInterfaces().get(1).getProvider()); + } + + public void testOptionalRequiredInterfaceProvidedMandatoryInternal() { + Application application = new Application(); + Container container = new Container("top", + new Component[] { application }, new ProvidedInterface[0], + Application.required(true)); + Environment env = new Environment(); + container.getRequiredInterfaces().get(0).setProvider( + env.getProvidedInterfaces().get(0)); + container.getRequiredInterfaces().get(1).setProvider( + env.getProvidedInterfaces().get(1)); + + try { + container.start(); + } catch (SystemAssemblyException e) { + return; + } + + fail(); + } + + public void testSealed() { + final Container container = new Container("xx"); + assertFalse(container.isSealed()); + container.start(); + assertTrue(container.isSealed()); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.addComponent(new Application()); + } + }, SystemAssemblyException.class); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectRequiredProvided("x", "y", "a", "b"); + } + }, SystemAssemblyException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalRequired("x", "y", "a"); + } + }, SystemAssemblyException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalProvided("x", "y", "z"); + } + }, SystemAssemblyException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.addProvidedInterface(new DefaultProvidedInterface( + "xx", String.class)); + } + }, SystemAssemblyException.class); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.addRequiredInterface(new DefaultRequiredInterface( + "xx", String.class)); + } + }, SystemAssemblyException.class); + } + + public void testRestriction() { + Environment env1 = new Environment("env1"); + Environment env2 = new Environment("env2"); + Application app = new Application("app"); + Container container = new Container("top").addComponent(env1) + .addComponent(env2).addComponent(app); + container.connectRequiredProvided("app", null, "env1", null); + container.start(); + assertEquals(env1.getString(), app.getString()); + assertEquals(env1.getInteger(), app.getInteger()); + assertFalse(env2.getString().equals(app.getString())); + assertFalse(env2.getInteger().equals(app.getInteger())); + } + + public void testRestrictionWithFromAndToInterfaceName() { + Environment env1 = new Environment("env1"); + Environment env2 = new Environment("env2"); + Application app = new Application("app"); + Container container = new Container("top").addComponent(env1) + .addComponent(env2).addComponent(app); + container.connectRequiredProvided("app", app.getRequiredInterfaces() + .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0) + .getName()); + container.connectRequiredProvided("app", app.getRequiredInterfaces() + .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1) + .getName()); + container.start(); + assertEquals(env1.getString(), app.getString()); + assertEquals(env2.getInteger(), app.getInteger()); + assertFalse(env2.getString().equals(app.getString())); + assertFalse(env1.getInteger().equals(app.getInteger())); + } + + public void testRestrictionWrongComponentNames() { + Environment env1 = new Environment("env1"); + Environment env2 = new Environment("env2"); + Application app = new Application("app"); + final Container container = new Container("top").addComponent(env1) + .addComponent(env2).addComponent(app); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectRequiredProvided("app2", null, "env1", null); + } + }, SystemAssemblyException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectRequiredProvided("app", null, "env3", null); + } + }, SystemAssemblyException.class); + } + + public void testRestrictionWrongInterfaceNames() { + final Environment env1 = new Environment("env1"); + Environment env2 = new Environment("env2"); + final Application app = new Application("app"); + final Container container = new Container("top").addComponent(env1) + .addComponent(env2).addComponent(app); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectRequiredProvided("app", app + .getRequiredInterfaces().get(0).getName() + + "xxx", "env1", null); + } + }, SystemAssemblyException.class); + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectRequiredProvided("app", null, "env1", env1 + .getProvidedInterfaces().get(0).getName() + + "yyy"); + } + }, SystemAssemblyException.class); + } + + public void testProvidedInDifferentScopes() { + // Scoping problem occurred. Externally and internally provided + // components clashed + // because unique id generation in the scope was wrong. + StringComponent str = new StringComponent("string"); + Application app = new Application("app"); + Container container = new Container("top").addComponent(str) + .addComponent(app); + container.addRequiredInterface(new DefaultRequiredInterface("integer", + Integer.class)); + + ProvidedInterface provided = new DefaultProvidedInterface("hallo", + Integer.class); + container.getRequiredInterfaces().get(0).setProvider(provided); + + Scope external = new DefaultScope(new ProvidedInterface[0]); + external.publishInterface(provided, 100); + + container.start(external); + } + + public void testProvidedInterfaces() { + Environment env = new Environment(tracker); + Container envcontainer = new Container("0").addComponent(env) + .addProvidedInterface( + new DefaultProvidedInterface("string", String.class)) + .addProvidedInterface( + new DefaultProvidedInterface("integer", Integer.class)); + Scope scope = envcontainer.start(); + + AssertionUtils.assertEquals(new String[] { "start.environment" }, + tracker.getEvents(Thread.currentThread()).toArray(new String[0])); + + envcontainer.stop(scope); + } + + public void testCoupleTwoContainers() { + Environment env = new Environment(tracker); + Container envcontainer = new Container("0").addComponent(env) + .addProvidedInterface( + new DefaultProvidedInterface("string", String.class)) + .addProvidedInterface( + new DefaultProvidedInterface("integer", Integer.class)); + + Application app = new Application(tracker); + Container appcontainer = new Container("1").addComponent(app) + .addRequiredInterface( + new DefaultRequiredInterface("string", String.class)) + .addRequiredInterface( + new DefaultRequiredInterface("integer", Integer.class)); + + Container top = new Container("top"); + top.addComponent(envcontainer).addComponent(appcontainer); + + top.start(); + AssertionUtils.assertEquals(new String[] { "start.environment", + "start.application" }, tracker.getEvents(Thread.currentThread()) + .toArray(new String[0])); + } + + public void testNonUniqueRequiredInterface() { + final Container container = new Container("top"); + container.addRequiredInterface(new DefaultRequiredInterface("i", + Integer.class)); + container.addRequiredInterface(new DefaultRequiredInterface("x", + String.class)); + container.addRequiredInterface(new DefaultRequiredInterface("y", + String.class)); + + Application app = new Application("1"); + container.addComponent(app); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.start(); + } + }, SystemAssemblyException.class); + + container.connectExternalRequired("1", app.getRequiredInterfaces().get( + 0).getName(), "y"); + + ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class); + ProvidedInterface x = new DefaultProvidedInterface("x", String.class); + ProvidedInterface y = new DefaultProvidedInterface("y", String.class); + + Scope externalScope = new DefaultScope(new ProvidedInterface[0]); + + externalScope.publishInterface(i, 100); + externalScope.publishInterface(x, "x-value"); + externalScope.publishInterface(y, "y-value"); + + container.getRequiredInterfaces().get(0).setProvider(i); + container.getRequiredInterfaces().get(1).setProvider(x); + container.getRequiredInterfaces().get(2).setProvider(y); + + container.start(externalScope); + + assertEquals("y-value", app.getString()); + } + + public void testNonUniqueRequiredInterfaceWrongNames() { + final Container container = new Container("top"); + container.addRequiredInterface(new DefaultRequiredInterface("i", + Integer.class)); + container.addRequiredInterface(new DefaultRequiredInterface("x", + String.class)); + container.addRequiredInterface(new DefaultRequiredInterface("y", + String.class)); + + final Application app = new Application("1"); + container.addComponent(app); + + // wrong component name. + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalRequired("2", "x", "y"); + } + }, SystemAssemblyException.class); + + // Wrong interface name of component. + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalRequired("1", app + .getRequiredInterfaces().get(0).getName() + + "xxx", "y"); + } + }, SystemAssemblyException.class); + + // Wrong external interface name of container + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalRequired("1", app + .getRequiredInterfaces().get(0).getName(), "z"); + } + }, SystemAssemblyException.class); + } + + public void testNonUniqueProvidedInterface() { + final Container container = new Container("top") + .addProvidedInterface(new DefaultProvidedInterface("external", + String.class)); + Environment env1 = new Environment("env1"); + Environment env2 = new Environment("env2"); + + container.addComponent(env1); + container.addComponent(env2); + + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.start(); + } + }, SystemAssemblyException.class); + + // now choose env2 + container.connectExternalProvided(container.getProvidedInterfaces() + .get(0).getName(), env2.getName(), env2.getProvidedInterfaces() + .get(0).getName()); + + Scope scope = container.start(); + + // check the value of the provided interface of the container + String value = scope.getInterfaceImplementation(container + .getProvidedInterfaces().get(0), String.class); + assertNotNull(value); + assertEquals(value, env2.getString()); + assertFalse(value.equals(env1.getString())); + } + + public void testNonUniqueProvidedInterfaceWrongNames() { + final Container container = new Container("top") + .addProvidedInterface(new DefaultProvidedInterface("external", + String.class)); + final Environment env1 = new Environment("env1"); + final Environment env2 = new Environment("env2"); + + container.addComponent(env1); + container.addComponent(env2); + + // Wrong external provided interface name + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container + .connectExternalProvided(container.getProvidedInterfaces() + .get(0).getName() + + "xx", "env1", env1.getProvidedInterfaces().get(0) + .getName()); + } + }, SystemAssemblyException.class); + + // Wrong provided interface name. + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalProvided(container + .getProvidedInterfaces().get(0).getName(), "env1", env1 + .getProvidedInterfaces().get(0).getName() + + "xx"); + } + }, SystemAssemblyException.class); + + // Wrong provided component + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + @Override + public void run() throws Exception { + container.connectExternalProvided(container + .getProvidedInterfaces().get(0).getName(), "env3", env1 + .getProvidedInterfaces().get(0).getName()); + } + }, SystemAssemblyException.class); + } + + private static class MyMultiple implements Serializable, Runnable { + @Override + public void run() { + // Empty + } + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/AbstractComponentTest.java b/system/general/src/test/java/org/wamblee/system/core/AbstractComponentTest.java index 2fd48f6e..8402b280 100644 --- a/system/general/src/test/java/org/wamblee/system/core/AbstractComponentTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/AbstractComponentTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,45 +12,54 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; import junit.framework.TestCase; +/** + * + * @author $author$ + * @version $Revision$ + */ public class AbstractComponentTest extends TestCase { + public void testNotAllInterfacesStarted() { + try { + Component component = new AbstractComponent("xx", + new ProvidedInterface[] { new DefaultProvidedInterface("xxx", + String.class) }, new RequiredInterface[0]) { + @Override + protected Object doStart(Scope aScope) { + // Empty, not starting service. + return null; + } - public void testNotAllInterfacesStarted() { - try { - Component component = new AbstractComponent("xx", - new ProvidedInterface[] { new DefaultProvidedInterface( - "xxx", String.class) }, new RequiredInterface[0]) { - @Override - protected Object doStart(Scope aScope) { - // Empty, not starting service. - return null; - } + @Override + protected void doStop(Object aRuntime) { + // Empty. + } + }; + + component + .start(new DefaultScope(component.getProvidedInterfaces())); + } catch (SystemAssemblyException e) { + // e.printStackTrace(); + return; + } - @Override - protected void doStop(Object aRuntime) { - // Empty. - } - }; - component.start(new DefaultScope(component.getProvidedInterfaces())); - } catch (SystemAssemblyException e) { - //e.printStackTrace(); - return; - } - fail(); - } - - public void testUnexpectedServicesStarted() { - try { + fail(); + } + + public void testUnexpectedServicesStarted() { + try { Component component = new AbstractComponent("xx", - new ProvidedInterface[0], new RequiredInterface[0]) { + new ProvidedInterface[0], new RequiredInterface[0]) { @Override protected Object doStart(Scope aScope) { - addInterface(new DefaultProvidedInterface("x", Integer.class), 100, aScope); - return null; + addInterface(new DefaultProvidedInterface("x", + Integer.class), 100, aScope); + + return null; } @Override @@ -58,11 +67,14 @@ public class AbstractComponentTest extends TestCase { // Empty. } }; - component.start(new DefaultScope(component.getProvidedInterfaces())); + + component + .start(new DefaultScope(component.getProvidedInterfaces())); } catch (SystemAssemblyException e) { - //e.printStackTrace(); + // e.printStackTrace(); return; } + fail(); - } + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/DefaultInterfaceDescriptorTest.java b/system/general/src/test/java/org/wamblee/system/core/DefaultInterfaceDescriptorTest.java index 5bfca072..4b868bff 100644 --- a/system/general/src/test/java/org/wamblee/system/core/DefaultInterfaceDescriptorTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/DefaultInterfaceDescriptorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,82 +15,95 @@ */ package org.wamblee.system.core; -import java.io.Serializable; +import junit.framework.TestCase; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; -import junit.framework.TestCase; +import java.io.Serializable; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultInterfaceDescriptorTest extends TestCase { + public void testOneRequiredOneProvidedMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + String.class); + RequiredInterface required = new DefaultRequiredInterface("name", + String.class); + assertTrue(required.implementedBy(provided)); + } + + public void testOneRequiredOneProvidedMatchSubClass() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + Integer.class); + RequiredInterface required = new DefaultRequiredInterface("name", + Number.class); + assertTrue(required.implementedBy(provided)); + } + + public void testOneRequiredOneProvidedNoMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + String.class); + RequiredInterface required = new DefaultRequiredInterface("name", + Number.class); + assertFalse(required.implementedBy(provided)); + } + + public void testOneRequiredMultipleProvidedMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + new Class[] { String.class, Integer.class }); + RequiredInterface required = new DefaultRequiredInterface("name", + String.class); + assertTrue(required.implementedBy(provided)); + } + + public void testMultipleRequiredOneProvidedMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + MyMultiple.class); + RequiredInterface required = new DefaultRequiredInterface("name", + new Class[] { Runnable.class, Serializable.class }); + assertTrue(required.implementedBy(provided)); + } + + public void testMultipleRequiredOneProvidedNoMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + MyMultiple.class); + RequiredInterface required = new DefaultRequiredInterface("name", + new Class[] { String.class, Runnable.class }); + assertFalse(required.implementedBy(provided)); + } + + public void testMultipleRequiredMultipleProvidedMatch() { + ProvidedInterface provided = new DefaultProvidedInterface("name", + new Class[] { Runnable.class, Serializable.class, String.class }); + RequiredInterface required = new DefaultRequiredInterface("name", + new Class[] { Runnable.class, Serializable.class }); + assertTrue(required.implementedBy(provided)); + } + + public void testPrimitiveAndWrapperType() { + RequiredInterface req1 = new DefaultRequiredInterface("req1", int.class); + RequiredInterface req2 = new DefaultRequiredInterface("req1", + Integer.class); + ProvidedInterface prov1 = new DefaultProvidedInterface("prov1", + int.class); + ProvidedInterface prov2 = new DefaultProvidedInterface("prov2", + Integer.class); + assertTrue(req1.implementedBy(prov1)); + assertTrue(req2.implementedBy(prov1)); + assertTrue(req1.implementedBy(prov2)); + assertTrue(req2.implementedBy(prov2)); + } - public void testOneRequiredOneProvidedMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", String.class); - RequiredInterface required = new DefaultRequiredInterface("name", String.class); - assertTrue(required.implementedBy(provided)); - } - - public void testOneRequiredOneProvidedMatchSubClass() { - ProvidedInterface provided = new DefaultProvidedInterface("name", Integer.class); - RequiredInterface required = new DefaultRequiredInterface("name", Number.class); - assertTrue(required.implementedBy(provided)); - } - - public void testOneRequiredOneProvidedNoMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", String.class); - RequiredInterface required = new DefaultRequiredInterface("name", Number.class); - assertFalse(required.implementedBy(provided)); - } - - public void testOneRequiredMultipleProvidedMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", - new Class[] { String.class, Integer.class} ); - RequiredInterface required = new DefaultRequiredInterface("name", String.class); - assertTrue(required.implementedBy(provided)); - } - - private static class MyMultiple implements Runnable, Serializable { - @Override - public void run() { - // Empty - } - } - - public void testMultipleRequiredOneProvidedMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", - MyMultiple.class ); - RequiredInterface required = new DefaultRequiredInterface("name", - new Class[] {Runnable.class, Serializable.class} ); - assertTrue(required.implementedBy(provided)); - } - - public void testMultipleRequiredOneProvidedNoMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", - MyMultiple.class ); - RequiredInterface required = new DefaultRequiredInterface("name", - new Class[] { String.class, Runnable.class} ); - assertFalse(required.implementedBy(provided)); - } - - public void testMultipleRequiredMultipleProvidedMatch() { - ProvidedInterface provided = new DefaultProvidedInterface("name", - new Class[] { Runnable.class, Serializable.class, String.class} ); - RequiredInterface required = new DefaultRequiredInterface("name", - new Class[] {Runnable.class, Serializable.class} ); - assertTrue(required.implementedBy(provided)); - } - - public void testPrimitiveAndWrapperType() { - RequiredInterface req1 = new DefaultRequiredInterface("req1", int.class); - RequiredInterface req2 = new DefaultRequiredInterface("req1", Integer.class); - ProvidedInterface prov1 = new DefaultProvidedInterface("prov1", int.class); - ProvidedInterface prov2 = new DefaultProvidedInterface("prov2", Integer.class); - assertTrue(req1.implementedBy(prov1)); - assertTrue(req2.implementedBy(prov1)); - assertTrue(req1.implementedBy(prov2)); - assertTrue(req2.implementedBy(prov2)); - } - + private static class MyMultiple implements Runnable, Serializable { + @Override + public void run() { + // Empty + } + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/DefaultRequiredInterfaceTest.java b/system/general/src/test/java/org/wamblee/system/core/DefaultRequiredInterfaceTest.java index 139de7d3..a29c2e7b 100644 --- a/system/general/src/test/java/org/wamblee/system/core/DefaultRequiredInterfaceTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/DefaultRequiredInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,16 +12,19 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; import junit.framework.TestCase; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultRequiredInterfaceTest extends TestCase { - public void testEquals() { assertFalse(new DefaultRequiredInterface("a", String.class) - .equals(new DefaultRequiredInterface("a", String.class))); + .equals(new DefaultRequiredInterface("a", String.class))); } - } diff --git a/system/general/src/test/java/org/wamblee/system/core/DefaultScopeTest.java b/system/general/src/test/java/org/wamblee/system/core/DefaultScopeTest.java index 7199c6fb..5ad4dd58 100644 --- a/system/general/src/test/java/org/wamblee/system/core/DefaultScopeTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/DefaultScopeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,31 +17,40 @@ package org.wamblee.system.core; import junit.framework.TestCase; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DefaultScopeTest extends TestCase { - - public void testLookup() { - ProvidedInterface provider = new DefaultProvidedInterface("x", Integer.class); - Scope scope = new DefaultScope(new ProvidedInterface[0]); - + public void testLookup() { + ProvidedInterface provider = new DefaultProvidedInterface("x", + Integer.class); + Scope scope = new DefaultScope(new ProvidedInterface[0]); + scope.publishInterface(provider, 100); - assertEquals(100, scope.getInterfaceImplementation(provider, Integer.class).intValue()); + assertEquals(100, scope.getInterfaceImplementation(provider, + Integer.class).intValue()); } - - public void testNestedLookup() { - ProvidedInterface provider1 = new DefaultProvidedInterface("x", Integer.class); + + public void testNestedLookup() { + ProvidedInterface provider1 = new DefaultProvidedInterface("x", + Integer.class); Scope parent = new DefaultScope(new ProvidedInterface[0]); - + parent.publishInterface(provider1, 100); - - ProvidedInterface provider2 = new DefaultProvidedInterface("y", String.class); + + ProvidedInterface provider2 = new DefaultProvidedInterface("y", + String.class); Scope child = new DefaultScope(new ProvidedInterface[0], parent); - + child.publishInterface(provider2, "hallo"); - + assertFalse(provider1.equals(provider2)); - - assertEquals(100, child.getInterfaceImplementation(provider1, Integer.class).intValue()); - assertEquals("hallo", child.getInterfaceImplementation(provider2, String.class)); - } + assertEquals(100, child.getInterfaceImplementation(provider1, + Integer.class).intValue()); + assertEquals("hallo", child.getInterfaceImplementation(provider2, + String.class)); + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/Environment.java b/system/general/src/test/java/org/wamblee/system/core/Environment.java index 4b791d05..6a39b645 100644 --- a/system/general/src/test/java/org/wamblee/system/core/Environment.java +++ b/system/general/src/test/java/org/wamblee/system/core/Environment.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,81 +12,104 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; -import javax.sql.DataSource; - import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; + import org.wamblee.test.EventTracker; +import javax.sql.DataSource; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class Environment extends AbstractComponent { + private static int COUNT = 0; + + private EventTracker tracker; + + private double random; + + private int integer; - private static final ProvidedInterface[] provided(String aPrefix) { - return new ProvidedInterface[] { - new DefaultProvidedInterface(aPrefix + "datasource", String.class), - new DefaultProvidedInterface(aPrefix + "integer", Integer.class) }; - } - - private static int COUNT = 0; - - private EventTracker _tracker; - private double _random; - private int _integer; - - public Environment() { - this("environment"); - } - - public Environment(String aName) { - this(aName, ""); + /** + * Creates a new Environment object. + */ + public Environment() { + this("environment"); } - - public Environment(String aName, String aPrefix) { + + /** + * Creates a new Environment object. + * + */ + public Environment(String aName) { + this(aName, ""); + } + + /** + * Creates a new Environment object. + * + */ + public Environment(String aName, String aPrefix) { super(aName, provided(aPrefix), new RequiredInterface[0]); - _random = Math.random(); - _integer = COUNT++; + random = Math.random(); + integer = COUNT++; } + /** + * Creates a new Environment object. + * + */ + public Environment(EventTracker aTracker) { + this(); + tracker = aTracker; + } + + private static final ProvidedInterface[] provided(String aPrefix) { + return new ProvidedInterface[] { + new DefaultProvidedInterface(aPrefix + "datasource", String.class), + new DefaultProvidedInterface(aPrefix + "integer", Integer.class) }; + } + + public Integer getInteger() { + return integer; + } + + public String getString() { + return getName() + ".hello"; + } + @Override + protected Object doStart(Scope aScope) { + addInterface(getProvidedInterfaces().get(0), getString(), aScope); + addInterface(getProvidedInterfaces().get(1), getInteger(), aScope); + track("start." + getName()); - public Environment(EventTracker aTracker) { - this(); - _tracker = aTracker; - } - - public Integer getInteger() { - return _integer; - } - - public String getString() { - return getName() + ".hello"; - } - - @Override - protected Object doStart(Scope aScope) { - addInterface(getProvidedInterfaces().get(0), getString(), aScope); - addInterface(getProvidedInterfaces().get(1), getInteger(), aScope); - track("start." + getName()); - return _random; - } - - @Override - protected void doStop(Object aRuntime) { - track("stop." + getName()); - if (_random != (Double) aRuntime) { - throw new IllegalArgumentException("Wrong runtime: expected " - + _random + " but got " + aRuntime); - } - } - - private void track(String aString) { - if (_tracker == null) { - return; - } - _tracker.eventOccurred(aString); - } + return random; + } + + @Override + protected void doStop(Object aRuntime) { + track("stop." + getName()); + + if (random != (Double) aRuntime) { + throw new IllegalArgumentException("Wrong runtime: expected " + + random + " but got " + aRuntime); + } + } + + private void track(String aString) { + if (tracker == null) { + return; + } + + tracker.eventOccurred(aString); + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/IntegerComponent.java b/system/general/src/test/java/org/wamblee/system/core/IntegerComponent.java index acf683fe..c560d6e6 100644 --- a/system/general/src/test/java/org/wamblee/system/core/IntegerComponent.java +++ b/system/general/src/test/java/org/wamblee/system/core/IntegerComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,71 +12,93 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; -import javax.sql.DataSource; - import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; + import org.wamblee.test.EventTracker; +import javax.sql.DataSource; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class IntegerComponent extends AbstractComponent { + private EventTracker tracker; - private static final ProvidedInterface[] provided(String aPrefix) { - return new ProvidedInterface[] { - new DefaultProvidedInterface(aPrefix + "integer", Integer.class) }; - } + private double random; - private EventTracker _tracker; - private double _random; + /** + * Creates a new IntegerComponent object. + */ + public IntegerComponent() { + this("environment"); + } - public IntegerComponent() { - this("environment"); - } - - public IntegerComponent(String aName) { - this(aName, ""); + /** + * Creates a new IntegerComponent object. + * + */ + public IntegerComponent(String aName) { + this(aName, ""); } - - public IntegerComponent(String aName, String aPrefix) { + + /** + * Creates a new IntegerComponent object. + * + */ + public IntegerComponent(String aName, String aPrefix) { super(aName, provided(aPrefix), new RequiredInterface[0]); - _random = Math.random(); + random = Math.random(); + } + + /** + * Creates a new IntegerComponent object. + * + */ + public IntegerComponent(EventTracker aTracker) { + this(); + tracker = aTracker; + } + + private static final ProvidedInterface[] provided(String aPrefix) { + return new ProvidedInterface[] { new DefaultProvidedInterface(aPrefix + + "integer", Integer.class) }; } + public Integer getInteger() { + return 2; + } + + @Override + protected Object doStart(Scope aScope) { + addInterface(getProvidedInterfaces().get(1), getInteger(), aScope); + track("start." + getName()); + return random; + } - public IntegerComponent(EventTracker aTracker) { - this(); - _tracker = aTracker; - } - - public Integer getInteger() { - return 2; - } - - @Override - protected Object doStart(Scope aScope) { - addInterface(getProvidedInterfaces().get(1), getInteger(), aScope); - track("start." + getName()); - return _random; - } - - @Override - protected void doStop(Object aRuntime) { - track("stop." + getName()); - if (_random != (Double) aRuntime) { - throw new IllegalArgumentException("Wrong runtime: expected " - + _random + " but got " + aRuntime); - } - } - - private void track(String aString) { - if (_tracker == null) { - return; - } - _tracker.eventOccurred(aString); - } + @Override + protected void doStop(Object aRuntime) { + track("stop." + getName()); + + if (random != (Double) aRuntime) { + throw new IllegalArgumentException("Wrong runtime: expected " + + random + " but got " + aRuntime); + } + } + + private void track(String aString) { + if (tracker == null) { + return; + } + + tracker.eventOccurred(aString); + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/RequiredInterfaceComparator.java b/system/general/src/test/java/org/wamblee/system/core/RequiredInterfaceComparator.java index 404fec70..79bd2c1a 100644 --- a/system/general/src/test/java/org/wamblee/system/core/RequiredInterfaceComparator.java +++ b/system/general/src/test/java/org/wamblee/system/core/RequiredInterfaceComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,14 +15,21 @@ */ package org.wamblee.system.core; +import java.io.Serializable; import java.util.Comparator; +/** + * + * @author $author$ + * @version $Revision$ + */ public class RequiredInterfaceComparator implements - Comparator { + Comparator, Serializable { + + private static final long serialVersionUID = 7631587103378238574L; @Override public int compare(RequiredInterface aO1, RequiredInterface aO2) { return aO1.getName().compareTo(aO2.getName()); } - } diff --git a/system/general/src/test/java/org/wamblee/system/core/StringComponent.java b/system/general/src/test/java/org/wamblee/system/core/StringComponent.java index 7701c20b..e79a394d 100644 --- a/system/general/src/test/java/org/wamblee/system/core/StringComponent.java +++ b/system/general/src/test/java/org/wamblee/system/core/StringComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,75 +12,97 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.core; -import javax.sql.DataSource; - import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; + import org.wamblee.test.EventTracker; +import javax.sql.DataSource; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class StringComponent extends AbstractComponent { + private EventTracker tracker; - private static final ProvidedInterface[] provided(String aPrefix) { - return new ProvidedInterface[] { - new DefaultProvidedInterface(aPrefix + "datasource", String.class) }; - } + private double random; - private EventTracker _tracker; - private double _random; + /** + * Creates a new StringComponent object. + */ + public StringComponent() { + this("environment"); + } - public StringComponent() { - this("environment"); - } - - public StringComponent(String aName) { - this(aName, ""); + /** + * Creates a new StringComponent object. + * + */ + public StringComponent(String aName) { + this(aName, ""); } - - public StringComponent(String aName, String aPrefix) { + + /** + * Creates a new StringComponent object. + * + */ + public StringComponent(String aName, String aPrefix) { super(aName, provided(aPrefix), new RequiredInterface[0]); - _random = Math.random(); + random = Math.random(); + } + + /** + * Creates a new StringComponent object. + * + */ + public StringComponent(EventTracker aTracker) { + this(); + tracker = aTracker; } + private static final ProvidedInterface[] provided(String aPrefix) { + return new ProvidedInterface[] { new DefaultProvidedInterface(aPrefix + + "datasource", String.class) }; + } + + public Integer getInteger() { + return 2; + } + + public String getString() { + return getName() + ".hello"; + } + + @Override + protected Object doStart(Scope aScope) { + addInterface(getProvidedInterfaces().get(0), getString(), aScope); + track("start." + getName()); + return random; + } + + @Override + protected void doStop(Object aRuntime) { + track("stop." + getName()); + + if (random != (Double) aRuntime) { + throw new IllegalArgumentException("Wrong runtime: expected " + + random + " but got " + aRuntime); + } + } + + private void track(String aString) { + if (tracker == null) { + return; + } - public StringComponent(EventTracker aTracker) { - this(); - _tracker = aTracker; - } - - public Integer getInteger() { - return 2; - } - - public String getString() { - return getName() + ".hello"; - } - - @Override - protected Object doStart(Scope aScope) { - addInterface(getProvidedInterfaces().get(0), getString(), aScope); - track("start." + getName()); - return _random; - } - - @Override - protected void doStop(Object aRuntime) { - track("stop." + getName()); - if (_random != (Double) aRuntime) { - throw new IllegalArgumentException("Wrong runtime: expected " - + _random + " but got " + aRuntime); - } - } - - private void track(String aString) { - if (_tracker == null) { - return; - } - _tracker.eventOccurred(aString); - } + tracker.eventOccurred(aString); + } } diff --git a/system/general/src/test/java/org/wamblee/system/graph/CompositeEdgeFilterTest.java b/system/general/src/test/java/org/wamblee/system/graph/CompositeEdgeFilterTest.java index c76ff97e..3f169531 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/CompositeEdgeFilterTest.java +++ b/system/general/src/test/java/org/wamblee/system/graph/CompositeEdgeFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,9 @@ */ package org.wamblee.system.graph; +import junit.framework.TestCase; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; -import junit.framework.TestCase; import org.wamblee.system.container.Application; import org.wamblee.system.core.Component; @@ -27,75 +27,83 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.graph.component.ProvidedInterfaceNode; import org.wamblee.system.graph.component.RequiredInterfaceNode; +/** + * + * @author $author$ + * @version $Revision$ + */ public class CompositeEdgeFilterTest extends TestCase { - private Application _app = new Application(); - private Environment _env = new Environment(); - - private Edge createEdge(Component aClient, RequiredInterface aRequired, - Component aServer, ProvidedInterface aProvided) { + private Application app = new Application(); + + private Environment env = new Environment(); + + private Edge createEdge(Component aClient, RequiredInterface aRequired, + Component aServer, ProvidedInterface aProvided) { Node from = new RequiredInterfaceNode(aClient, aRequired); Node to = new ProvidedInterfaceNode(aServer, aProvided); + return new DefaultEdge(from, to); } - public void testEmpty() { - EdgeFilter restriction = new CompositeEdgeFilter(); - assertFalse(restriction.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); + public void testEmpty() { + EdgeFilter restriction = new CompositeEdgeFilter(); + assertFalse(restriction.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); } - - private void configureRestriction(EdgeFilter base, boolean aResult) { - stub(base.isViolated((Edge)anyObject())).toReturn(aResult); + + private void configureRestriction(EdgeFilter aBase, boolean aResult) { + stub(aBase.isViolated((Edge) anyObject())).toReturn(aResult); } - - public void testOneRestriction() { + + public void testOneRestriction() { EdgeFilter base = mock(EdgeFilter.class); CompositeEdgeFilter composite = new CompositeEdgeFilter(); composite.add(base); - - // First let the base return false and verify the result. - + + // First let the base return false and verify the result. configureRestriction(base, false); - - assertFalse(composite.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); - + + assertFalse(composite.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); + // Second let the base return true and verify the result. configureRestriction(base, true); - - assertTrue(composite.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); + + assertTrue(composite.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); } - - - public void testTwoRestrictions() { + public void testTwoRestrictions() { EdgeFilter base1 = mock(EdgeFilter.class); CompositeEdgeFilter composite = new CompositeEdgeFilter(); composite.add(base1); + EdgeFilter base2 = mock(EdgeFilter.class); composite.add(base2); - - // 1. base1 not violated and base 2 not violated -> not violated. - + + // 1. base1 not violated and base 2 not violated -> not violated. configureRestriction(base1, false); configureRestriction(base2, false); - assertFalse(composite.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); - + assertFalse(composite.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); + // 2. base 1 not violated but base 2 violated -> violated configureRestriction(base1, false); configureRestriction(base2, true); - - assertTrue(composite.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); - - // 3. base 1 violated -> violated and base 2 not called. + + assertTrue(composite.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); + + // 3. base 1 violated -> violated and base 2 not called. configureRestriction(base1, true); // base 2 should not be called. - - assertTrue(composite.isViolated(createEdge(_app, _app.getRequiredInterfaces().get(0), - _env, _env.getProvidedInterfaces().get(0)))); + assertTrue(composite.isViolated(createEdge(app, app + .getRequiredInterfaces().get(0), env, env.getProvidedInterfaces() + .get(0)))); } - } diff --git a/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java b/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java index 675a06bd..4fd75a55 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java +++ b/system/general/src/test/java/org/wamblee/system/graph/GraphTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,20 +12,23 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph; -import java.util.Arrays; -import java.util.List; - +import junit.framework.TestCase; import static org.mockito.Mockito.*; -import org.wamblee.test.AssertionUtils; +import org.wamblee.test.AssertionUtils; -import junit.framework.TestCase; +import java.util.Arrays; +import java.util.List; +/** + * + * @author $author$ + * @version $Revision$ + */ public class GraphTest extends TestCase { - public void testNodeMgt() { final Graph graph = new Graph(); assertTrue(graph.getNodes().isEmpty()); @@ -40,130 +43,137 @@ public class GraphTest extends TestCase { assertTrue(graph.removeNode(x)); assertTrue(graph.getNodes().isEmpty()); - // Empty node set. + // Empty node set. assertFalse(graph.removeNode(x)); - - Node y = new DefaultNode("y"); - graph.addNodes(Arrays.asList(new Node[] { x, y} )); + + Node y = new DefaultNode("y"); + graph.addNodes(Arrays.asList(new Node[] { x, y })); assertEquals(2, graph.getNodes().size()); - + // duplicate node - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { - graph.addNode(new DefaultNode("x")); + graph.addNode(new DefaultNode("x")); } }, IllegalArgumentException.class); } - public void testEdgeMgt() { + public void testEdgeMgt() { final Graph graph = new Graph(); - final Node x = new DefaultNode("x"); - final Node y = new DefaultNode("y"); + final Node x = new DefaultNode("x"); + final Node y = new DefaultNode("y"); graph.addNode(x); graph.addNode(y); - final Edge e = new DefaultEdge(x, y); + + final Edge e = new DefaultEdge(x, y); graph.addEdge(e); assertEquals(Arrays.asList(new Edge[] { e }), graph.getEdges()); - + // duplicate edge. - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { - graph.addEdge(e); + graph.addEdge(e); } }, IllegalArgumentException.class); - + // Remove node when edge is still present - AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { + AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { graph.removeNode(x); } }, IllegalArgumentException.class); - - + Node a = new DefaultNode("a"); graph.addNode(a); - graph.addEdges(Arrays.asList(new Edge[] { new DefaultEdge(x, a), new DefaultEdge(y, a) })); + graph.addEdges(Arrays.asList(new Edge[] { new DefaultEdge(x, a), + new DefaultEdge(y, a) })); assertEquals(3, graph.getEdges().size()); } - - public void testExtend() { - Graph graph = new Graph(); - graph.addNode(new MyNode("x", new String[] { "a", "b"})); - graph.addNode(new MyNode("y", new String[] { "b", "c"})); - graph.addNode(new MyNode("z", new String[] { "a", "c"})); + + public void testExtend() { + Graph graph = new Graph(); + graph.addNode(new MyNode("x", new String[] { "a", "b" })); + graph.addNode(new MyNode("y", new String[] { "b", "c" })); + graph.addNode(new MyNode("z", new String[] { "a", "c" })); graph.extend(new MyEdgeFactory()); - - List edges = graph.getEdges(); + + List edges = graph.getEdges(); assertEquals(12, edges.size()); // 2 outgoing and 2 incoming nodes. } - - public void testApplyFilter() { - Graph graph = new Graph(); + + public void testApplyFilter() { + Graph graph = new Graph(); graph.addNode(new DefaultNode("x")); graph.addNode(new DefaultNode("y")); graph.addNode(new DefaultNode("z")); - graph.addEdge(new DefaultEdge(graph.findNode("x"), graph.findNode("y"))); - graph.addEdge(new DefaultEdge(graph.findNode("y"), graph.findNode("z"))); - graph.addEdge(new DefaultEdge(graph.findNode("z"), graph.findNode("x"))); - + graph + .addEdge(new DefaultEdge(graph.findNode("x"), graph.findNode("y"))); + graph + .addEdge(new DefaultEdge(graph.findNode("y"), graph.findNode("z"))); + graph + .addEdge(new DefaultEdge(graph.findNode("z"), graph.findNode("x"))); + assertEquals(3, graph.getEdges().size()); - - graph.applyFilter(new EdgeFilter() { + + graph.applyFilter(new EdgeFilter() { @Override public boolean isViolated(Edge aEdge) { - if (aEdge.getFrom().getName().equals("x")) { - return false; + if (aEdge.getFrom().getName().equals("x")) { + return false; } - return true; + + return true; } - }); - + }); + assertEquals(1, graph.getEdges().size()); assertEquals("x", graph.getEdges().get(0).getFrom().getName()); - } - - public void testFindIncomingOutgoing() { + + public void testFindIncomingOutgoing() { Graph graph = new Graph(); Node x = new DefaultNode("x"); - Node y = new DefaultNode("y"); + Node y = new DefaultNode("y"); graph.addNode(x); graph.addNode(y); - Edge e = new DefaultEdge(x,y); + + Edge e = new DefaultEdge(x, y); graph.addEdge(e); - + List incoming = graph.findIncoming(x); - assertTrue(incoming.isEmpty()); + assertTrue(incoming.isEmpty()); + List outgoing = graph.findOutgoing(x); assertEquals(1, outgoing.size()); assertSame(e, outgoing.get(0)); - + incoming = graph.findIncoming(y); assertEquals(1, incoming.size()); assertSame(e, incoming.get(0)); - + outgoing = graph.findOutgoing(y); - assertTrue(outgoing.isEmpty()); + assertTrue(outgoing.isEmpty()); } - + public void testAccept() { - Graph graph = new Graph(); - Node x = new DefaultNode("x"); - Node y = new DefaultNode("y"); + Graph graph = new Graph(); + Node x = new DefaultNode("x"); + Node y = new DefaultNode("y"); Edge e = new DefaultEdge(x, y); graph.addNode(x); graph.addNode(y); graph.addEdge(e); - Visitor visitor = mock(Visitor.class); - + + Visitor visitor = mock(Visitor.class); + graph.accept(visitor); verify(visitor).visitNode(x); verify(visitor).visitNode(y); verify(visitor).visitEdge(e); - + verifyNoMoreInteractions(visitor); } } diff --git a/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java b/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java index daddccd6..fef2f058 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java +++ b/system/general/src/test/java/org/wamblee/system/graph/MyEdgeFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,24 +18,31 @@ package org.wamblee.system.graph; import java.util.ArrayList; import java.util.List; +/** + * + * @author $author$ + * @version $Revision$ + */ public class MyEdgeFactory implements EdgeFactory { - - public MyEdgeFactory() { + /** + * Creates a new MyEdgeFactory object. + */ + public MyEdgeFactory() { // Empty. } @Override public List create(MyNode aFrom, MyNode aTo) { List result = new ArrayList(); - for (String fromPort: aFrom.getPorts()) { - for (String toPort: aTo.getPorts()) { - if ( fromPort.equals(toPort)) { + + for (String fromPort : aFrom.getPorts()) { + for (String toPort : aTo.getPorts()) { + if (fromPort.equals(toPort)) { result.add(new DefaultEdge(aFrom, aTo)); } } } - - return result; - } + return result; + } } diff --git a/system/general/src/test/java/org/wamblee/system/graph/MyNode.java b/system/general/src/test/java/org/wamblee/system/graph/MyNode.java index 0090c3f9..b0588967 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/MyNode.java +++ b/system/general/src/test/java/org/wamblee/system/graph/MyNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,19 +12,45 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph; +import java.util.Arrays; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class MyNode extends DefaultNode { + private String[] ports; - private String[] _ports; - + /** + * Creates a new MyNode object. + * + */ public MyNode(String aName, String[] aPorts) { super(aName); - _ports = aPorts; + ports = Arrays.copyOf(aPorts, aPorts.length); } - + public String[] getPorts() { - return _ports; + return Arrays.copyOf(ports, ports.length); + } + + @Override + public boolean equals(Object aObj) { + if (!super.equals(aObj)) { + return false; + } + if (!(aObj instanceof MyNode)) { + return false; + } + return Arrays.equals(ports, ((MyNode) aObj).ports); + } + + @Override + public int hashCode() { + return super.hashCode(); } } diff --git a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedEdgeFilterTest.java b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedEdgeFilterTest.java index 5f45f551..0ba053b5 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedEdgeFilterTest.java +++ b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectExternalProvidedProvidedEdgeFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import junit.framework.TestCase; @@ -26,69 +26,75 @@ import org.wamblee.system.graph.DefaultNode; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.EdgeFilter; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConnectExternalProvidedProvidedEdgeFilterTest extends TestCase { + private Container container; + + private Component internal; + + private String externalInterfaceName; + + private String internalComponentName; + + private String internalInterfaceName; - private Container _container; - private Component _internal; - private String _externalInterfaceName; - private String _internalComponentName; - private String _internalInterfaceName; - private Edge _edge; + private Edge edge; @Override protected void setUp() throws Exception { - _container = new Container("container") - .addProvidedInterface(new DefaultProvidedInterface("string", - String.class)); - _internal = new Environment("env1"); - - _externalInterfaceName = _container.getProvidedInterfaces().get(0) - .getName(); - _internalComponentName = _internal.getName(); - _internalInterfaceName = _internal.getProvidedInterfaces().get(0).getName(); - - _edge = new DefaultEdge(new ExternalProvidedInterfaceNode(_container, - _container.getProvidedInterfaces().get(0)), - new ProvidedInterfaceNode(_internal, _internal - .getProvidedInterfaces().get(0))); + container = new Container("container") + .addProvidedInterface(new DefaultProvidedInterface("string", + String.class)); + internal = new Environment("env1"); + + externalInterfaceName = container.getProvidedInterfaces().get(0) + .getName(); + internalComponentName = internal.getName(); + internalInterfaceName = internal.getProvidedInterfaces().get(0) + .getName(); + + edge = new DefaultEdge(new ExternalProvidedInterfaceNode(container, + container.getProvidedInterfaces().get(0)), + new ProvidedInterfaceNode(internal, internal + .getProvidedInterfaces().get(0))); } public void testWrongExternal() { EdgeFilter filter = new ConnectExternalProvidedProvidedFilter( - _externalInterfaceName + "x", _internalComponentName, - _internalInterfaceName); - assertFalse(filter.isViolated(_edge)); + externalInterfaceName + "x", internalComponentName, + internalInterfaceName); + assertFalse(filter.isViolated(edge)); } public void testRightExternalWrongComponent() { EdgeFilter filter = new ConnectExternalProvidedProvidedFilter( - _externalInterfaceName, _internalComponentName + "x", - _internalInterfaceName); - assertTrue(filter.isViolated(_edge)); + externalInterfaceName, internalComponentName + "x", + internalInterfaceName); + assertTrue(filter.isViolated(edge)); } public void testRightExternalWrongInternal() { EdgeFilter filter = new ConnectExternalProvidedProvidedFilter( - _externalInterfaceName, _internalComponentName, - _internalInterfaceName + "x"); - assertTrue(filter.isViolated(_edge)); + externalInterfaceName, internalComponentName, + internalInterfaceName + "x"); + assertTrue(filter.isViolated(edge)); } - - public void testEverythingRight() { + + public void testEverythingRight() { EdgeFilter filter = new ConnectExternalProvidedProvidedFilter( - _externalInterfaceName, _internalComponentName, - _internalInterfaceName); - assertFalse(filter.isViolated(_edge)); + externalInterfaceName, internalComponentName, internalInterfaceName); + assertFalse(filter.isViolated(edge)); } - public void testWrongEdgeType() { EdgeFilter filter = new ConnectExternalProvidedProvidedFilter( - _externalInterfaceName, _internalComponentName, - _internalInterfaceName); + externalInterfaceName, internalComponentName, internalInterfaceName); DefaultEdge edge = new DefaultEdge(new DefaultNode("x"), - new DefaultNode("y")); + new DefaultNode("y")); assertFalse(filter.isViolated(edge)); } - } diff --git a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilterTest.java b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilterTest.java index 7e8e02ce..167d5caa 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilterTest.java +++ b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredExternallyRequiredEdgeFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.graph.component; import junit.framework.TestCase; @@ -27,60 +27,66 @@ import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.EdgeFilter; import org.wamblee.system.graph.Node; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConnectRequiredExternallyRequiredEdgeFilterTest extends TestCase { + private Component comp; + + private Container container; - private Component _comp; - private Container _container; - private Edge _edge; + private Edge edge; @Override protected void setUp() throws Exception { - _comp = new Application(); - _container = new Container("container") - .addRequiredInterface(new DefaultRequiredInterface("x", - String.class)); - Node req = new RequiredInterfaceNode(_comp, _comp - .getRequiredInterfaces().get(0)); - Node external = new ExternalRequiredInterfaceNode(_container, - _container.getRequiredInterfaces().get(0)); - _edge = new DefaultEdge(req, external); + comp = new Application(); + container = new Container("container") + .addRequiredInterface(new DefaultRequiredInterface("x", + String.class)); + + Node req = new RequiredInterfaceNode(comp, comp.getRequiredInterfaces() + .get(0)); + Node external = new ExternalRequiredInterfaceNode(container, container + .getRequiredInterfaces().get(0)); + edge = new DefaultEdge(req, external); } public void testRightComponentRightInterface() { EdgeFilter filter = new ConnectRequiredExternallyRequiredEdgeFilter( - _comp.getName(), _comp.getRequiredInterfaces().get(0).getName(), - _container.getRequiredInterfaces().get(0).getName()); - assertFalse(filter.isViolated(_edge)); + comp.getName(), comp.getRequiredInterfaces().get(0).getName(), + container.getRequiredInterfaces().get(0).getName()); + assertFalse(filter.isViolated(edge)); } public void testWrongInterface() { EdgeFilter filter = new ConnectRequiredExternallyRequiredEdgeFilter( - _comp.getName(), _comp.getRequiredInterfaces().get(0).getName() - + "xx", _container.getRequiredInterfaces().get(0).getName()); - assertFalse(filter.isViolated(_edge)); + comp.getName(), comp.getRequiredInterfaces().get(0).getName() + + "xx", container.getRequiredInterfaces().get(0).getName()); + assertFalse(filter.isViolated(edge)); } public void testWrongComponent() { EdgeFilter filter = new ConnectRequiredExternallyRequiredEdgeFilter( - _comp.getName() + "xx", _comp.getRequiredInterfaces().get(0) - .getName(), _container.getRequiredInterfaces().get(0) - .getName()); - assertFalse(filter.isViolated(_edge)); + comp.getName() + "xx", comp.getRequiredInterfaces().get(0) + .getName(), container.getRequiredInterfaces().get(0).getName()); + assertFalse(filter.isViolated(edge)); } public void testWrongExternalInterface() { EdgeFilter filter = new ConnectRequiredExternallyRequiredEdgeFilter( - _comp.getName(), _comp.getRequiredInterfaces().get(0).getName(), - _container.getRequiredInterfaces().get(0).getName() + "xx"); - assertTrue(filter.isViolated(_edge)); + comp.getName(), comp.getRequiredInterfaces().get(0).getName(), + container.getRequiredInterfaces().get(0).getName() + "xx"); + assertTrue(filter.isViolated(edge)); } public void testWrongEdgeType() { DefaultEdge edge = new DefaultEdge(new DefaultNode("x"), - new DefaultNode("y")); + new DefaultNode("y")); EdgeFilter filter = new ConnectRequiredExternallyRequiredEdgeFilter( - _comp.getName(), _comp.getRequiredInterfaces().get(0).getName(), - _container.getRequiredInterfaces().get(0).getName()); + comp.getName(), comp.getRequiredInterfaces().get(0).getName(), + container.getRequiredInterfaces().get(0).getName()); assertFalse(filter.isViolated(edge)); } } diff --git a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilterTest.java b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilterTest.java index 0cb9013b..90c318b0 100644 --- a/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilterTest.java +++ b/system/general/src/test/java/org/wamblee/system/graph/component/ConnectRequiredProvidedEdgeFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,7 @@ */ package org.wamblee.system.graph.component; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import junit.framework.TestCase; import org.wamblee.system.container.Application; import org.wamblee.system.core.Environment; @@ -25,79 +23,92 @@ import org.wamblee.system.graph.DefaultEdge; import org.wamblee.system.graph.Edge; import org.wamblee.system.graph.EdgeFilter; import org.wamblee.system.graph.Node; + import org.wamblee.test.AssertionUtils; -import junit.framework.TestCase; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConnectRequiredProvidedEdgeFilterTest extends TestCase { + private Application app1 = new Application("app1", "pf1."); - private Application _app1 = new Application("app1", "pf1."); - private Application _app2 = new Application("app2", "pf2."); - - private Environment _env1 = new Environment("env1", "pf3."); - private Environment _env2 = new Environment("env2", "pf4."); - - - private void compare(Boolean[] aExpected, EdgeFilter aRestriction) { - List result = new ArrayList(); - - - - // order will be: - // env1, app1 - // env1, app2 - // env2, app1 - // env2, app2 - for (Environment env: new Environment[] { _env1, _env2} ) { - for (Application app: new Application[] { _app1, _app2} ) { - Node from = new RequiredInterfaceNode( - app, app.getRequiredInterfaces().get(0)); - Node to = new ProvidedInterfaceNode( - env, env.getProvidedInterfaces().get(0)); - Edge edge = new DefaultEdge(from, to); - result.add(aRestriction.isViolated(edge)); - } - } - - - assertEquals(Arrays.asList(aExpected), result); + private Application app2 = new Application("app2", "pf2."); + + private Environment env1 = new Environment("env1", "pf3."); + + private Environment env2 = new Environment("env2", "pf4."); + + private void compare(Boolean[] aExpected, EdgeFilter aRestriction) { + List result = new ArrayList(); + + // order will be: + // env1, app1 + // env1, app2 + // env2, app1 + // env2, app2 + for (Environment env : new Environment[] { env1, env2 }) { + for (Application app : new Application[] { app1, app2 }) { + Node from = new RequiredInterfaceNode(app, app + .getRequiredInterfaces().get(0)); + Node to = new ProvidedInterfaceNode(env, env + .getProvidedInterfaces().get(0)); + Edge edge = new DefaultEdge(from, to); + result.add(aRestriction.isViolated(edge)); + } + } + + assertEquals(Arrays.asList(aExpected), result); } - public void testNoRestriction() { + public void testNoRestriction() { AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { - EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter(null, null, null, null); - + EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter( + null, null, null, null); + ignoredVariable(restriction); } }, IllegalArgumentException.class); AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { @Override public void run() throws Exception { - EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter(null, null, "x", "y"); + EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter( + null, null, "x", "y"); + ignoredVariable(restriction); } }, IllegalArgumentException.class); } - public void testClientServer() { - EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter("app1", null, "env1", null); - compare(new Boolean[] { false, false, true, false}, restriction); + private static final void ignoredVariable(Object aObject) { + // for findbugs. } - - public void testNoConnectionsAtAll() { - EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter("app1", null, null, null); - compare(new Boolean[] { true, false, true, false}, restriction); + + public void testClientServer() { + EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter("app1", + null, "env1", null); + compare(new Boolean[] { false, false, true, false }, restriction); } - - public void testExplicitConfig() { - _app1 = new Application("app1"); - _app2 = new Application("app2"); - _env1 = new Environment("env1"); - _env2 = new Environment("env2"); - - EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter( - "app2", "string", "env1", "datasource"); - compare(new Boolean[] { false, false, false, true}, restriction); - + + public void testNoConnectionsAtAll() { + EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter("app1", + null, null, null); + compare(new Boolean[] { true, false, true, false }, restriction); + } + + public void testExplicitConfig() { + app1 = new Application("app1"); + app2 = new Application("app2"); + env1 = new Environment("env1"); + env2 = new Environment("env2"); + + EdgeFilter restriction = new ConnectRequiredProvidedEdgeFilter("app2", + "string", "env1", "datasource"); + compare(new Boolean[] { false, false, false, true }, restriction); } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/ConfiguredProperties.java b/system/spring/src/main/java/org/wamblee/system/spring/ConfiguredProperties.java index 7443b57c..c472d3e6 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/ConfiguredProperties.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/ConfiguredProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,13 +18,23 @@ package org.wamblee.system.spring; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; + import java.util.Properties; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConfiguredProperties extends Properties { - - public ConfiguredProperties(String aProps) throws IOException { - InputStream is = new ByteArrayInputStream(aProps.getBytes()); - load(is); + /** + * Creates a new ConfiguredProperties object. + * + * + */ + public ConfiguredProperties(String aProps) throws IOException { + InputStream is = new ByteArrayInputStream(aProps.getBytes()); + load(is); is.close(); } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java b/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java index f88c4054..5483968b 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,37 +15,40 @@ */ package org.wamblee.system.spring; -import java.util.Properties; - import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; +import java.util.Properties; + /** - * Bean that provides postprocessing of the bean factory based on - * a given set of properties. + * Bean that provides postprocessing of the bean factory based on a given set of + * properties. * * @author Erik Brakkee */ class PropertySetter extends PropertyPlaceholderConfigurer { - - /** - * Constructs the property setter. - * @param aProps Properties. - */ - public PropertySetter(Properties aProps) { - String propFile = createPropertyFile(aProps); - setLocation(new StringResource(propFile)); - } + /** + * Constructs the property setter. + * + * @param aProps + * Properties. + */ + public PropertySetter(Properties aProps) { + String propFile = createPropertyFile(aProps); + setLocation(new StringResource(propFile)); + } public static String createPropertyFile(Properties aProps) { - StringBuffer buf = new StringBuffer(); - for (Object key: aProps.keySet()) { - buf.append(key); - buf.append("="); - buf.append(aProps.get(key)); - buf.append("\n"); - } + StringBuffer buf = new StringBuffer(); + + for (Object key : aProps.keySet()) { + buf.append(key); + buf.append("="); + buf.append(aProps.get(key)); + buf.append("\n"); + } + return buf.toString(); } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java b/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java index 71ac3085..133e3aa2 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,51 +15,57 @@ */ package org.wamblee.system.spring; -import java.util.List; - import org.springframework.beans.factory.FactoryBean; + import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.SystemAssemblyException; +import java.util.List; + /** - * Bean which adds a service required by the spring component to - * the application context so that other spring beans can use it. - * + * Bean which adds a service required by the spring component to the application + * context so that other spring beans can use it. + * * @author Erik Brakkee */ class RequiredServiceBean implements FactoryBean { - - private RequiredInterface _required; - - /** - * Constructs the bean. - * @param aId Id of the bean in the service registry. - */ - public RequiredServiceBean(String aId) { - List required = SpringComponent.THIS.get().getRequiredInterfaces(); - for ( RequiredInterface intf: required) { - if ( intf.getName().equals(aId)) { - _required = intf; - return; - } - } - throw new SystemAssemblyException("Cannot resolve required component '" + aId + "'"); - } + private RequiredInterface required; + + /** + * Constructs the bean. + * + * @param aId + * Id of the bean in the service registry. + */ + public RequiredServiceBean(String aId) { + List requiredInterfaces = SpringComponent.THIS.get() + .getRequiredInterfaces(); + + for (RequiredInterface intf : requiredInterfaces) { + if (intf.getName().equals(aId)) { + required = intf; + + return; + } + } - @Override - public Object getObject() throws Exception { - return SpringComponent.SCOPE.get().getInterfaceImplementation( - _required.getProvider(), Object.class); - } + throw new SystemAssemblyException( + "Cannot resolve required component '" + aId + "'"); + } - @Override - public Class getObjectType() { - return null; - } + @Override + public Object getObject() throws Exception { + return SpringComponent.SCOPE.get().getInterfaceImplementation( + required.getProvider(), Object.class); + } - @Override - public boolean isSingleton() { - return true; - } + @Override + public Class getObjectType() { + return null; + } + @Override + public boolean isSingleton() { + return true; + } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java b/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java index 88746a5e..92668209 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,17 +15,15 @@ */ package org.wamblee.system.spring; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - import org.springframework.beans.MutablePropertyValues; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.support.RootBeanDefinition; + import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.GenericApplicationContext; + import org.wamblee.system.core.AbstractComponent; import org.wamblee.system.core.DefaultScope; import org.wamblee.system.core.ProvidedInterface; @@ -33,6 +31,10 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + /** * Represents a system configured based on spring. The spring config files that * are configured should not contain any PropertyPlaceholderConfigurer objects. @@ -40,163 +42,176 @@ import org.wamblee.system.core.SystemAssemblyException; * @author Erik Brakkee */ public class SpringComponent extends AbstractComponent { + private static final String CONTEXT_KEY = "context"; + + static final ThreadLocal THIS = new ThreadLocal(); + + static final ThreadLocal SCOPE = new ThreadLocal(); + + private Properties properties; + + private String[] configFiles; + + private Map provided; + + private Map required; + + private Map propertyObjects; + + /** + * Constructs a spring system. + * + * @param aName + * Name of the system. + * @param aConfigFil + * Spring config files to read. + * @param aProvided + * Map of bean name to service descriptor describing the bean + * names that the spring config files use for each required + * service. + * @param aRequired + * Map of bean name to service descriptor describing the bean + * names that the spring config files use for each required + * service. + */ + public SpringComponent(String aName, String[] aConfigFiles, + Map aProvided, + Map aRequired) { + super(aName, aProvided.values().toArray(new ProvidedInterface[0]), + aRequired.keySet().toArray(new RequiredInterface[0])); + properties = new Properties(); + configFiles = aConfigFiles; + provided = aProvided; + required = aRequired; + propertyObjects = new HashMap(); + } + + /** + * Must be called to make a property available in the application context. + * + * @param aKey + * Property key. + * @param aValue + * Property value. + */ + public void setProperty(String aKey, String aValue) { + properties.put(aKey, aValue); + } + + public void addProperties(Properties aProperties) { + for (Object key : aProperties.keySet()) { + setProperty((String) key, aProperties.getProperty((String) key)); + } + } + + public void addProperties(String aBeanname, Properties aProperties) { + propertyObjects.put(aBeanname, aProperties); + } + + public Properties getProperties(String aBeanname) { + return propertyObjects.get(aBeanname); + } + + @Override + protected Scope doStart(Scope aExternalScope) { + SpringComponent old = THIS.get(); + Scope oldScope = SCOPE.get(); + THIS.set(this); + + Scope scope = new DefaultScope(getProvidedInterfaces().toArray( + new ProvidedInterface[0]), aExternalScope); + SCOPE.set(scope); + + try { + GenericApplicationContext parentContext = new GenericApplicationContext(); + + registerRequiredServices(parentContext); + registerPropertyObjects(parentContext); + + parentContext.refresh(); - private static final String CONTEXT_KEY = "context"; - - static final ThreadLocal THIS = new ThreadLocal(); - static final ThreadLocal SCOPE = new ThreadLocal(); - - private Properties _properties; - private String[] _configFiles; - private Map _provided; - private Map _required; - private Map _propertyObjects; - - /** - * Constructs a spring system. - * - * @param aName - * Name of the system. - * @param aConfigFil - * Spring config files to read. - * @param aProvided - * Map of bean name to service descriptor describing the bean - * names that the spring config files use for each required - * service. - * @param aRequired - * Map of bean name to service descriptor describing the bean - * names that the spring config files use for each required - * service. - */ - public SpringComponent(String aName, String[] aConfigFiles, - Map aProvided, - Map aRequired) { - super(aName, aProvided.values().toArray(new ProvidedInterface[0]), - aRequired.keySet().toArray(new RequiredInterface[0])); - _properties = new Properties(); - _configFiles = aConfigFiles; - _provided = aProvided; - _required = aRequired; - _propertyObjects = new HashMap(); - - } - - /** - * Must be called to make a property available in the application context. - * - * @param aKey - * Property key. - * @param aValue - * Property value. - */ - public void setProperty(String aKey, String aValue) { - _properties.put(aKey, aValue); - } - - public void addProperties(Properties aProperties) { - for (Object key : aProperties.keySet()) { - setProperty((String) key, aProperties.getProperty((String) key)); - } - } - - public void addProperties(String aBeanname, Properties aProperties) { - _propertyObjects.put(aBeanname, aProperties); - } - - public Properties getProperties(String aBeanname) { - return _propertyObjects.get(aBeanname); - } - - @Override - protected Scope doStart(Scope aExternalScope) { - - SpringComponent old = THIS.get(); - Scope oldScope = SCOPE.get(); - THIS.set(this); - Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope); - SCOPE.set(scope); - try { - GenericApplicationContext parentContext = new GenericApplicationContext(); - - registerRequiredServices(parentContext); - registerPropertyObjects(parentContext); - - parentContext.refresh(); - - System.out.println("Parent context " + parentContext); - - AbstractApplicationContext context = parseConfigFiles(parentContext); - - context - .addBeanFactoryPostProcessor(new PropertySetter(_properties)); - context.refresh(); - - exposeProvidedServices(context, aExternalScope); - - scope.put(CONTEXT_KEY, context); - return scope; - } catch (Exception e) { - throw new SystemAssemblyException( - "Failed to assemble spring system " + getName(), e); - } finally { - THIS.set(old); - SCOPE.set(oldScope); - } - } - - private void exposeProvidedServices(AbstractApplicationContext aContext, Scope aScope) { - // Call addService for each provided service. - - for (String name : _provided.keySet()) { - Object svc = aContext.getBean(name); - if (svc == null) { - throw new IllegalArgumentException(getQualifiedName() + ": service '" - + name + "' is null"); - } - addInterface(_provided.get(name), svc, aScope); - System.out.println("addService " + _provided.get(name) + " " + svc); - } - } - - private AbstractApplicationContext parseConfigFiles(GenericApplicationContext aParentContext) { - // Parse spring config files - - return new ClassPathXmlApplicationContext((String[]) _configFiles, - false, aParentContext); - } - - private void registerRequiredServices(GenericApplicationContext aParentContext) { - // Register required services in a parent context - for (RequiredInterface required: getRequiredInterfaces()) { - String beanName = _required.get(required); - if ( beanName != null && beanName.length() > 0) { - ConstructorArgumentValues cargs = new ConstructorArgumentValues(); - cargs.addGenericArgumentValue(required.getName()); - BeanDefinition definition = new RootBeanDefinition( - RequiredServiceBean.class, cargs, - new MutablePropertyValues()); - aParentContext.registerBeanDefinition(beanName, definition); - } else { - // The required interface is not required by the spring config but by the sub-class directly. - } - } - } - - private void registerPropertyObjects(GenericApplicationContext aParentContext) { - for (String beanName: _propertyObjects.keySet()) { + System.out.println("Parent context " + parentContext); + + AbstractApplicationContext context = parseConfigFiles(parentContext); + + context.addBeanFactoryPostProcessor(new PropertySetter(properties)); + context.refresh(); + + exposeProvidedServices(context, aExternalScope); + + scope.put(CONTEXT_KEY, context); + + return scope; + } catch (Exception e) { + throw new SystemAssemblyException( + "Failed to assemble spring system " + getName(), e); + } finally { + THIS.set(old); + SCOPE.set(oldScope); + } + } + + private void exposeProvidedServices(AbstractApplicationContext aContext, + Scope aScope) { + // Call addService for each provided service. + for (String name : provided.keySet()) { + Object svc = aContext.getBean(name); + + if (svc == null) { + throw new IllegalArgumentException(getQualifiedName() + + ": service '" + name + "' is null"); + } + + addInterface(provided.get(name), svc, aScope); + System.out.println("addService " + provided.get(name) + " " + svc); + } + } + + private AbstractApplicationContext parseConfigFiles( + GenericApplicationContext aParentContext) { + // Parse spring config files + return new ClassPathXmlApplicationContext((String[]) configFiles, + false, aParentContext); + } + + private void registerRequiredServices( + GenericApplicationContext aParentContext) { + // Register required services in a parent context + for (RequiredInterface requiredIntf : getRequiredInterfaces()) { + String beanName = required.get(requiredIntf); + + if ((beanName != null) && (beanName.length() > 0)) { + ConstructorArgumentValues cargs = new ConstructorArgumentValues(); + cargs.addGenericArgumentValue(requiredIntf.getName()); + + BeanDefinition definition = new RootBeanDefinition( + RequiredServiceBean.class, cargs, + new MutablePropertyValues()); + aParentContext.registerBeanDefinition(beanName, definition); + } else { + // The required interface is not required by the spring config + // but by the sub-class directly. + } + } + } + + private void registerPropertyObjects( + GenericApplicationContext aParentContext) { + for (String beanName : propertyObjects.keySet()) { ConstructorArgumentValues cargs = new ConstructorArgumentValues(); - cargs.addGenericArgumentValue(PropertySetter.createPropertyFile(_propertyObjects.get(beanName))); + cargs.addGenericArgumentValue(PropertySetter + .createPropertyFile(propertyObjects.get(beanName))); + BeanDefinition definition = new RootBeanDefinition( - ConfiguredProperties.class, cargs, - new MutablePropertyValues()); + ConfiguredProperties.class, cargs, new MutablePropertyValues()); aParentContext.registerBeanDefinition(beanName, definition); } } - - @Override - protected void doStop(Scope aRuntime) { - AbstractApplicationContext context = (AbstractApplicationContext)aRuntime.get(CONTEXT_KEY); - context.close(); - } + @Override + protected void doStop(Scope aRuntime) { + AbstractApplicationContext context = (AbstractApplicationContext) aRuntime + .get(CONTEXT_KEY); + context.close(); + } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java b/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java index 3f9a7919..2f5cbb5d 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,60 +15,68 @@ */ package org.wamblee.system.spring; +import org.springframework.core.io.Resource; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URL; -import org.springframework.core.io.Resource; +import java.net.URL; +/** + * + * @author $author$ + * @version $Revision$ + */ class StringResource implements Resource { - - private String _value; - - public StringResource(String aValue) { - _value = aValue; - } + private String value; - @Override - public Resource createRelative(String aRelativePath) throws IOException { - throw new IOException("No relative resource possible"); - } + /** + * Creates a new StringResource object. + * + */ + public StringResource(String aValue) { + value = aValue; + } - @Override - public boolean exists() { - return false; - } + @Override + public Resource createRelative(String aRelativePath) throws IOException { + throw new IOException("No relative resource possible"); + } - @Override - public String getDescription() { - return "Properties of a spring component"; - } + @Override + public boolean exists() { + return false; + } - @Override - public File getFile() throws IOException { - throw new IOException(); - } + @Override + public String getDescription() { + return "Properties of a spring component"; + } - @Override - public String getFilename() { - return "springcomponent.properties"; - } + @Override + public File getFile() throws IOException { + throw new IOException(); + } - @Override - public URL getURL() throws IOException { - throw new IOException(); - } + @Override + public String getFilename() { + return "springcomponent.properties"; + } - @Override - public boolean isOpen() { - return false; - } + @Override + public URL getURL() throws IOException { + throw new IOException(); + } - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(_value.getBytes()); - } + @Override + public boolean isOpen() { + return false; + } + @Override + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(value.getBytes()); + } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/component/DatasourceComponent.java b/system/spring/src/main/java/org/wamblee/system/spring/component/DatasourceComponent.java index a8d53d46..2b21a37b 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/component/DatasourceComponent.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/component/DatasourceComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.spring.component; -import java.io.IOException; -import java.util.Map; -import java.util.Properties; -import java.util.TreeMap; - -import javax.sql.DataSource; - import org.springframework.core.io.ClassPathResource; + import org.springframework.jdbc.datasource.DriverManagerDataSource; + import org.wamblee.system.components.ORMappingConfig; import org.wamblee.system.components.ORMappingConfig.DatabaseType; import org.wamblee.system.core.AbstractComponent; @@ -34,43 +29,64 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.spring.SpringComponent; +import java.io.IOException; + +import java.util.Map; +import java.util.Properties; +import java.util.TreeMap; + +import javax.sql.DataSource; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatasourceComponent extends AbstractComponent { + private static RequiredInterface PROPS = new DefaultRequiredInterface( + "dbprops", Properties.class); + + private static ProvidedInterface DATASOURCE = new DefaultProvidedInterface( + "datasource", DataSource.class); - private static RequiredInterface PROPS = new DefaultRequiredInterface("dbprops", Properties.class); - private static ProvidedInterface DATASOURCE = new DefaultProvidedInterface("datasource", - DataSource.class); - private static ProvidedInterface ORM_CONFIG = new DefaultProvidedInterface("ormconfig", - ORMappingConfig.class); - + private static ProvidedInterface ORM_CONFIG = new DefaultProvidedInterface( + "ormconfig", ORMappingConfig.class); + + /** + * Creates a new DatasourceComponent object. + * + * + */ public DatasourceComponent(String aName) throws IOException { - super(aName); - + super(aName); + addRequiredInterface(PROPS); addProvidedInterface(DATASOURCE); addProvidedInterface(ORM_CONFIG); } - @Override protected DataSource doStart(Scope aScope) { - Properties dbProps = aScope.getInterfaceImplementation( - PROPS.getProvider(), Properties.class); - DriverManagerDataSource ds = new DriverManagerDataSource( - dbProps.getProperty("database.url"), - dbProps.getProperty("database.username"), - dbProps.getProperty("database.password")); - addInterface(DATASOURCE, ds, aScope); - DatabaseType type = DatabaseType.valueOf(dbProps.getProperty("database.type")); - - ORMappingConfig config = new ORMappingConfig(true, type); - - addInterface(ORM_CONFIG, config, aScope); - - return ds; + Properties dbProps = aScope.getInterfaceImplementation(PROPS + .getProvider(), Properties.class); + DriverManagerDataSource ds = new DriverManagerDataSource(dbProps + .getProperty("database.url"), dbProps + .getProperty("database.username"), dbProps + .getProperty("database.password")); + addInterface(DATASOURCE, ds, aScope); + + DatabaseType type = DatabaseType.valueOf(dbProps + .getProperty("database.type")); + + ORMappingConfig config = new ORMappingConfig(true, type); + + addInterface(ORM_CONFIG, config, aScope); + + return ds; } @Override protected void doStop(DataSource aRuntime) { - // Empty. + // Empty. } } diff --git a/system/spring/src/main/java/org/wamblee/system/spring/component/HibernateComponent.java b/system/spring/src/main/java/org/wamblee/system/spring/component/HibernateComponent.java index 4b256254..3f172094 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/component/HibernateComponent.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/component/HibernateComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,19 +15,17 @@ */ package org.wamblee.system.spring.component; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import javax.sql.DataSource; - import org.hibernate.SessionFactory; + import org.hibernate.dialect.DerbyDialect; import org.hibernate.dialect.MySQLInnoDBDialect; + import org.springframework.orm.hibernate3.HibernateTemplate; + import org.springframework.transaction.PlatformTransactionManager; + import org.wamblee.persistence.hibernate.HibernateMappingFiles; + import org.wamblee.system.components.ORMappingConfig; import org.wamblee.system.components.ORMappingConfig.DatabaseType; import org.wamblee.system.core.DefaultProvidedInterface; @@ -37,69 +35,95 @@ import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.spring.SpringComponent; -public class HibernateComponent extends SpringComponent { +import java.io.IOException; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.sql.DataSource; +/** + * + * @author $author$ + * @version $Revision$ + */ +public class HibernateComponent extends SpringComponent { private static final String HIBERNATE_DIALECT_PROP = "hibernate.dialect"; + private static final String HIBERNATE_SCHEMAUPDATE_PROP = "hibernate.schemaupdate"; + private static final String HIBERNATE_PROPS_KEY = "hibernateProperties"; + private static final String HIBERNATE_SPRING_CONFIG = "spring/org.wamblee.system.spring.component.hibernate.xml"; - - private final RequiredInterface CONFIG = new DefaultRequiredInterface("config", ORMappingConfig.class); - - public HibernateComponent(String aName) throws IOException { - super(aName, new String[] { HIBERNATE_SPRING_CONFIG}, - createProvided(), createRequired()); - - Properties props = new Properties(); + + private final RequiredInterface config = new DefaultRequiredInterface( + "config", ORMappingConfig.class); + + /** + * Creates a new HibernateComponent object. + * + * + */ + public HibernateComponent(String aName) throws IOException { + super(aName, new String[] { HIBERNATE_SPRING_CONFIG }, + createProvided(), createRequired()); + + Properties props = new Properties(); addProperties(HIBERNATE_PROPS_KEY, props); - - addRequiredInterface(CONFIG); + + addRequiredInterface(config); } - + @Override protected Scope doStart(Scope aExternalScope) { - - ORMappingConfig config = aExternalScope.getInterfaceImplementation(CONFIG.getProvider(), ORMappingConfig.class); - setProperty(HIBERNATE_SCHEMAUPDATE_PROP, "" + config.isSchemaUpdate()); - - DatabaseType db = config.getType(); - String dialect = db.handleCases(new DatabaseType.Switch() { + ORMappingConfig orMappingConfig = aExternalScope.getInterfaceImplementation( + config.getProvider(), ORMappingConfig.class); + setProperty(HIBERNATE_SCHEMAUPDATE_PROP, "" + orMappingConfig.isSchemaUpdate()); + + DatabaseType db = orMappingConfig.getType(); + String dialect = db.handleCases(new DatabaseType.Switch() { @Override public String handleMySqlInnoDb() { - return MySQLInnoDBDialect.class.getName(); + return MySQLInnoDBDialect.class.getName(); } + @Override public String handleDerby() { - return DerbyDialect.class.getName(); + return DerbyDialect.class.getName(); } }); + getHibernateProperties().put(HIBERNATE_DIALECT_PROP, dialect); - - + return super.doStart(aExternalScope); } - - private Properties getHibernateProperties() { + + private Properties getHibernateProperties() { return getProperties(HIBERNATE_PROPS_KEY); } private static Map createRequired() { - Map required = new HashMap(); - required.put(new DefaultRequiredInterface("datasource", DataSource.class), "dataSource"); - required.put(new DefaultRequiredInterface("mappingFiles", HibernateMappingFiles.class), - "hibernateMappingFiles"); + Map required = new HashMap(); + required.put(new DefaultRequiredInterface("datasource", + DataSource.class), "dataSource"); + required.put(new DefaultRequiredInterface("mappingFiles", + HibernateMappingFiles.class), "hibernateMappingFiles"); + return required; } private static Map createProvided() { - Map provided = new HashMap(); - + Map provided = new HashMap(); + provided.put("transactionManager", new DefaultProvidedInterface( - "transactionMgr", PlatformTransactionManager.class)); + "transactionMgr", PlatformTransactionManager.class)); provided.put("sessionFactory", new DefaultProvidedInterface( - "sessionFactory", SessionFactory.class)); - provided.put("org.springframework.orm.hibernate3.HibernateTemplate", new DefaultProvidedInterface( - "hibernateTemplate", HibernateTemplate.class)); + "sessionFactory", SessionFactory.class)); + provided.put("org.springframework.orm.hibernate3.HibernateTemplate", + new DefaultProvidedInterface("hibernateTemplate", + HibernateTemplate.class)); + return provided; } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java b/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java index 5bbafa1d..5975b8a0 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/BlaService.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,21 +15,31 @@ */ package org.wamblee.system.spring; +/** + * + * @author $author$ + * @version $Revision$ + */ public class BlaService { - private HelloService _hello; - - public BlaService(HelloService aService) { - if ( aService == null ) { - throw new IllegalArgumentException("helloService is null"); - } - _hello = aService; - } - - public String execute() { - return _hello.say(); - } - - public void stop() { - System.out.println("Blaservice stopping"); - } + private HelloService hello; + + /** + * Creates a new BlaService object. + * + */ + public BlaService(HelloService aService) { + if (aService == null) { + throw new IllegalArgumentException("helloService is null"); + } + + hello = aService; + } + + public String execute() { + return hello.say(); + } + + public void stop() { + System.out.println("Blaservice stopping"); + } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/ConfiguredPropertiesTest.java b/system/spring/src/test/java/org/wamblee/system/spring/ConfiguredPropertiesTest.java index 00002de1..0677e4c2 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/ConfiguredPropertiesTest.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/ConfiguredPropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,24 +15,28 @@ */ package org.wamblee.system.spring; +import junit.framework.TestCase; + import java.io.IOException; -import java.util.Properties; -import junit.framework.TestCase; +import java.util.Properties; +/** + * + * @author $author$ + * @version $Revision$ + */ public class ConfiguredPropertiesTest extends TestCase { - - public void testProps() throws IOException { + public void testProps() throws IOException { Properties props = new Properties(); props.put("x", "y"); - props.put("a", "b"); - - ConfiguredProperties props2 = new ConfiguredProperties( - PropertySetter.createPropertyFile(props)); - - assertEquals(props.size(), props2.size()); + props.put("a", "b"); + + ConfiguredProperties props2 = new ConfiguredProperties(PropertySetter + .createPropertyFile(props)); + + assertEquals(props.size(), props2.size()); assertEquals(props.get("x"), props2.get("x")); assertEquals(props.get("a"), props2.get("a")); } } - diff --git a/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java b/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java index cfa5bae6..c3e623ce 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/HelloService.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,16 +15,24 @@ */ package org.wamblee.system.spring; +/** + * + * @author $author$ + * @version $Revision$ + */ public class HelloService { - - private String _msg; - - public HelloService(String aMsg) { - SpringComponentTest.EVENT_TRACKER.eventOccurred(aMsg); - _msg = aMsg; - } - - public String say() { - return _msg; - } + private String msg; + + /** + * Creates a new HelloService object. + * + */ + public HelloService(String aMsg) { + SpringComponentTest.getEventTracker().eventOccurred(aMsg); + msg = aMsg; + } + + public String say() { + return msg; + } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/HelloService2.java b/system/spring/src/test/java/org/wamblee/system/spring/HelloService2.java index e9c77080..5fa815fd 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/HelloService2.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/HelloService2.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,20 +12,28 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.spring; import java.util.Properties; +/** + * + * @author $author$ + * @version $Revision$ + */ public class HelloService2 { + private Properties props; - private Properties _props; - + /** + * Creates a new HelloService2 object. + * + */ public HelloService2(Properties aProps) { - _props = aProps; + props = aProps; } - public Properties getProperties() { - return _props; + public Properties getProperties() { + return props; } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java b/system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java index 1cc95c11..2e0bf5c0 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,18 +12,13 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.system.spring; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - import junit.framework.TestCase; import org.wamblee.io.ClassPathResource; + import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.DefaultScope; @@ -31,36 +26,55 @@ import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; + import org.wamblee.test.EventTracker; -public class SpringComponentTest extends TestCase { +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * + * @author $author$ + * @version $Revision$ + */ +public class SpringComponentTest extends TestCase { private static final String HELLO_SERVICE_SPRING_XML = "test.org.wamblee.system.spring.xml"; + private static final String HELLO_SERVICE_SPRING_WITH_REQS_XML = "test.org.wamblee.system.springWithRequirements.xml"; + private static final String HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML = "test.org.wamblee.system.springWithProperties.xml"; + private static final String HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML2 = "test.org.wamblee.system.springWithProperties2.xml"; private static final String PROPERTY_FILE = "test.org.wamblee.system.spring.properties"; - public static EventTracker EVENT_TRACKER; + private static EventTracker EVENT_TRACKER; - private Scope _externalScope; + private Scope externalScope; + public static EventTracker getEventTracker() { + return EVENT_TRACKER; + } + @Override protected void setUp() throws Exception { super.setUp(); EVENT_TRACKER = new EventTracker(); - _externalScope = new DefaultScope(new ProvidedInterface[0]); + externalScope = new DefaultScope(new ProvidedInterface[0]); } public void testBlackboxSystem() { SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_XML }, - new HashMap(), - new HashMap()); + new String[] { HELLO_SERVICE_SPRING_XML }, + new HashMap(), + new HashMap()); - Scope runtime = system.start(_externalScope); - assertEquals(0, _externalScope.getProvidedInterfaces().size()); + Scope runtime = system.start(externalScope); + assertEquals(0, externalScope.getProvidedInterfaces().size()); system.stop(runtime); } @@ -68,23 +82,24 @@ public class SpringComponentTest extends TestCase { public void testOneProvidedService() { Map provided = new HashMap(); provided.put("helloService", new DefaultProvidedInterface("hello", - HelloService.class)); + HelloService.class)); SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_XML }, provided, - new HashMap()); - Scope runtime = system.start(_externalScope); + new String[] { HELLO_SERVICE_SPRING_XML }, provided, + new HashMap()); + Scope runtime = system.start(externalScope); List services = runtime.getProvidedInterfaces(); assertEquals(1, services.size()); + Object service = runtime.getInterfaceImplementation(services.get(0), - Object.class); + Object.class); assertTrue(service instanceof HelloService); // BUG; Provided services should be made available in the external // scope. - Object service2 = _externalScope.getInterfaceImplementation(provided - .get("helloService"), Object.class); + Object service2 = externalScope.getInterfaceImplementation(provided + .get("helloService"), Object.class); assertSame(service, service2); assertEquals("Hello world!", ((HelloService) service).say()); @@ -94,69 +109,74 @@ public class SpringComponentTest extends TestCase { public void testWithProperties() throws IOException { Map provided = new HashMap(); provided.put("helloService", new DefaultProvidedInterface("hello", - HelloService.class)); + HelloService.class)); + SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML }, - provided, new HashMap()); + new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML }, + provided, new HashMap()); Properties props = new Properties(); props.load(new ClassPathResource(PROPERTY_FILE).getInputStream()); system.addProperties(props); - Scope scope = system.start(_externalScope); + Scope scope = system.start(externalScope); // BUG: Hello service was constructed multiple times. Once with the // unprocessed property // and another time with the processed property. assertEquals(1, EVENT_TRACKER.getEventCount()); + List services = scope.getProvidedInterfaces(); assertEquals("Property Value", scope.getInterfaceImplementation( - services.get(0), HelloService.class).say()); + services.get(0), HelloService.class).say()); } public void testWithPropertiesAsBean() throws IOException { Map provided = new HashMap(); provided.put("helloService", new DefaultProvidedInterface("hello", - HelloService2.class)); + HelloService2.class)); + SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML2 }, - provided, new HashMap()); + new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML2 }, + provided, new HashMap()); Properties props = new Properties(); props.load(new ClassPathResource(PROPERTY_FILE).getInputStream()); system.addProperties("properties", props); - Scope scope = system.start(_externalScope); + Scope scope = system.start(externalScope); List services = scope.getProvidedInterfaces(); Properties props2 = scope.getInterfaceImplementation(services.get(0), - HelloService2.class).getProperties(); + HelloService2.class).getProperties(); assertEquals(props, props2); } public void testWithMissingRequirement() { try { SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, - new HashMap(), - new HashMap()); - system.start(_externalScope); + new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, + new HashMap(), + new HashMap()); + system.start(externalScope); } catch (SystemAssemblyException e) { // e.printStackTrace(); return; } + fail(); } public void testWithRequirement() { Map required = new HashMap(); required.put(new DefaultRequiredInterface("hello", HelloService.class), - "helloService"); + "helloService"); + SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, - new HashMap(), required); + new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, + new HashMap(), required); HelloService helloObject = new HelloService("ladida"); ProvidedInterface helloService = new DefaultProvidedInterface("hello", - HelloService.class); + HelloService.class); Scope scope = new DefaultScope(new ProvidedInterface[] { helloService }); scope.publishInterface(helloService, helloObject); system.getRequiredInterfaces().get(0).setProvider(helloService); @@ -168,26 +188,28 @@ public class SpringComponentTest extends TestCase { public void testWithRequirementAndProvidedService() { Map required = new HashMap(); required.put(new DefaultRequiredInterface("hello", HelloService.class), - "helloService"); + "helloService"); + Map provided = new HashMap(); provided.put("blaService", new DefaultProvidedInterface("bla", - BlaService.class)); + BlaService.class)); SpringComponent system = new SpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, provided, - required); + new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, provided, + required); HelloService helloObject = new HelloService("ladida"); ProvidedInterface helloService = new DefaultProvidedInterface("hello", - HelloService.class); + HelloService.class); Scope scope = new DefaultScope(new ProvidedInterface[] { helloService }); scope.publishInterface(helloService, helloObject); system.getRequiredInterfaces().get(0).setProvider(helloService); + Scope runtime = system.start(scope); ProvidedInterface started = runtime.getProvidedInterfaces().get(0); Object impl = runtime.getInterfaceImplementation(started, - BlaService.class); + BlaService.class); assertNotNull(impl); assertTrue(impl instanceof BlaService); assertEquals("ladida", ((BlaService) impl).execute()); @@ -202,28 +224,29 @@ public class SpringComponentTest extends TestCase { public void testWithProvidedFromSubClassNotFromConfig() { Map provided = new HashMap(); provided.put("helloService", new DefaultProvidedInterface("hello", - HelloService.class)); + HelloService.class)); SubSpringComponent system = new SubSpringComponent("system", - new String[] { HELLO_SERVICE_SPRING_XML }, provided, - new HashMap()); + new String[] { HELLO_SERVICE_SPRING_XML }, provided, + new HashMap()); - Scope runtime = system.start(_externalScope); + Scope runtime = system.start(externalScope); List services = runtime.getProvidedInterfaces(); assertEquals(2, services.size()); + Object service = runtime.getInterfaceImplementation(services.get(0), - Object.class); + Object.class); assertTrue(service instanceof HelloService); // BUG; Provided services should be made available in the external // scope. - Object service2 = _externalScope.getInterfaceImplementation(provided - .get("helloService"), Object.class); + Object service2 = externalScope.getInterfaceImplementation(provided + .get("helloService"), Object.class); assertSame(service, service2); - Object floatsvc = _externalScope.getInterfaceImplementation(system - .getProvidedInterfaces().get(1), Object.class); + Object floatsvc = externalScope.getInterfaceImplementation(system + .getProvidedInterfaces().get(1), Object.class); assertTrue(floatsvc instanceof Float); assertTrue((((Float) floatsvc).floatValue() - 100.345f) < 0.00001); @@ -232,23 +255,25 @@ public class SpringComponentTest extends TestCase { } /** - * Tests the spring component with an additional requirement from the subclass - * which is not required by the spring config files inside. + * Tests the spring component with an additional requirement from the + * subclass which is not required by the spring config files inside. */ public void testWithRequirementFromSubClass() { Map required = new HashMap(); required.put(new DefaultRequiredInterface("hello", HelloService.class), - "helloService"); + "helloService"); + SpringComponent system = new SubSpringComponent2("system", - new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, - new HashMap(), required); + new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML }, + new HashMap(), required); HelloService helloObject = new HelloService("ladida"); ProvidedInterface helloService = new DefaultProvidedInterface("hello", - HelloService.class); - - ProvidedInterface floatService = new DefaultProvidedInterface("float", Float.class); - + HelloService.class); + + ProvidedInterface floatService = new DefaultProvidedInterface("float", + Float.class); + Scope scope = new DefaultScope(new ProvidedInterface[] { helloService }); scope.publishInterface(helloService, helloObject); scope.publishInterface(floatService, 100.234f); @@ -257,8 +282,8 @@ public class SpringComponentTest extends TestCase { Scope runtime = system.start(scope); system.stop(runtime); - - assertEquals(100.234f, ((Float)runtime.get("floatValue")).floatValue(), 0.0001f); - } + assertEquals(100.234f, + ((Float) runtime.get("floatValue")).floatValue(), 0.0001f); + } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent.java b/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent.java index 5e79a7ad..59df10d8 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,30 +15,38 @@ */ package org.wamblee.system.spring; -import java.util.Map; - - import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; +import java.util.Map; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class SubSpringComponent extends SpringComponent { - - private static ProvidedInterface PROVIDED = new DefaultProvidedInterface("provided", Float.class); + private static ProvidedInterface PROVIDED = new DefaultProvidedInterface( + "provided", Float.class); + /** + * Creates a new SubSpringComponent object. + * + */ public SubSpringComponent(String aName, String[] aConfigFiles, - Map aProvided, - Map aRequired) { + Map aProvided, + Map aRequired) { super(aName, aConfigFiles, aProvided, aRequired); addProvidedInterface(PROVIDED); } - + @Override protected Scope doStart(Scope aExternalScope) { - Scope scope = super.doStart(aExternalScope); addInterface(PROVIDED, 100.345f, aExternalScope); + return scope; } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent2.java b/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent2.java index 7b67cc42..9fdccf16 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent2.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/SubSpringComponent2.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,31 +15,41 @@ */ package org.wamblee.system.spring; -import java.util.Map; - import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; +import java.util.Map; + +/** + * + * @author $author$ + * @version $Revision$ + */ public class SubSpringComponent2 extends SpringComponent { - - private static RequiredInterface REQUIRED = new DefaultRequiredInterface("required", Float.class); + private static RequiredInterface REQUIRED = new DefaultRequiredInterface( + "required", Float.class); + /** + * Creates a new SubSpringComponent2 object. + * + */ public SubSpringComponent2(String aName, String[] aConfigFiles, - Map aProvided, - Map aRequired) { + Map aProvided, + Map aRequired) { super(aName, aConfigFiles, aProvided, aRequired); addRequiredInterface(REQUIRED); } - + @Override protected Scope doStart(Scope aExternalScope) { - Scope scope = super.doStart(aExternalScope); - - float value = aExternalScope.getInterfaceImplementation(REQUIRED.getProvider(), Float.class); + + float value = aExternalScope.getInterfaceImplementation(REQUIRED + .getProvider(), Float.class); scope.put("floatValue", value); + return scope; } } diff --git a/system/spring/src/test/java/org/wamblee/system/spring/component/DatabaseTesterComponent.java b/system/spring/src/test/java/org/wamblee/system/spring/component/DatabaseTesterComponent.java index b988107b..f4972f26 100644 --- a/system/spring/src/test/java/org/wamblee/system/spring/component/DatabaseTesterComponent.java +++ b/system/spring/src/test/java/org/wamblee/system/spring/component/DatabaseTesterComponent.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,40 +12,37 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ - + */ package org.wamblee.system.spring.component; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import javax.sql.DataSource; - import junit.framework.TestCase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.dbunit.DatabaseUnitException; + import org.dbunit.database.DatabaseConnection; import org.dbunit.database.DatabaseSequenceFilter; import org.dbunit.database.IDatabaseConnection; + import org.dbunit.dataset.FilteredDataSet; import org.dbunit.dataset.IDataSet; import org.dbunit.dataset.filter.ITableFilter; + import org.dbunit.operation.DatabaseOperation; + import org.hibernate.SessionFactory; + import org.springframework.beans.factory.NoSuchBeanDefinitionException; + import org.springframework.context.ApplicationContext; + import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceUtils; + import org.springframework.orm.hibernate3.HibernateTemplate; + import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; @@ -53,17 +50,30 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; + import org.wamblee.test.spring.TestTransactionCallback; import org.wamblee.test.spring.TestTransactionCallbackWithoutResult; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import javax.sql.DataSource; + /** * Test support class for database testing. Currently, this still requires the * spring platform transaction manager and hibernate template. */ public class DatabaseTesterComponent { - private static final Log LOG = LogFactory - .getLog(DatabaseTesterComponent.class); + .getLog(DatabaseTesterComponent.class); /** * Schema pattern. @@ -73,33 +83,37 @@ public class DatabaseTesterComponent { /** * Cached spring application context. */ - private ApplicationContext _context; + private ApplicationContext context; - private HibernateTemplate _hibernateTemplate; + private HibernateTemplate hibernateTemplate; - private PlatformTransactionManager _transactionManager; + private PlatformTransactionManager transactionManager; - private DataSource _dataSource; + private DataSource dataSource; + /** + * Creates a new DatabaseTesterComponent object. + * + */ public DatabaseTesterComponent(HibernateTemplate aHibernateTemplate, - PlatformTransactionManager aTransactionManager, - DataSource aDataSource) { - _hibernateTemplate = aHibernateTemplate; - _transactionManager = aTransactionManager; - _dataSource = aDataSource; + PlatformTransactionManager aTransactionManager, DataSource aDataSource) { + hibernateTemplate = aHibernateTemplate; + transactionManager = aTransactionManager; + dataSource = aDataSource; } /** + * * @return Hibernate session factory. */ protected SessionFactory getSessionFactory() { - return _hibernateTemplate.getSessionFactory(); + return hibernateTemplate.getSessionFactory(); } /** * Performs common initialization for test cases: *
    - *
  • Cleaning the database.
  • + *
  • Cleaning the database.
  • *
* * @throws Exception @@ -121,13 +135,15 @@ public class DatabaseTesterComponent { } /** + * * @return Transaction manager */ protected PlatformTransactionManager getTransactionManager() { - return _transactionManager; + return transactionManager; } /** + * * @return Starts a new transaction. */ protected TransactionStatus getTransaction() { @@ -144,13 +160,12 @@ public class DatabaseTesterComponent { * @return Hibernate template. */ public HibernateTemplate getTemplate() { - return _hibernateTemplate; + return hibernateTemplate; } /** * Flushes the session. Should be called after some Hibernate work and * before JDBC is used to check results. - * */ public void flush() { getTemplate().flush(); @@ -160,7 +175,6 @@ public class DatabaseTesterComponent { * Flushes the session first and then removes all objects from the Session * cache. Should be called after some Hibernate work and before JDBC is used * to check results. - * */ public void clear() { flush(); @@ -189,7 +203,6 @@ public class DatabaseTesterComponent { } public void cleanDatabase() throws SQLException { - if (!isDatabaseConfigured()) { return; } @@ -198,10 +211,10 @@ public class DatabaseTesterComponent { try { IDatabaseConnection connection = new DatabaseConnection( - getConnection()); + getConnection()); ITableFilter filter = new DatabaseSequenceFilter(connection, tables); IDataSet dataset = new FilteredDataSet(filter, connection - .createDataSet(tables)); + .createDataSet(tables)); DatabaseOperation.DELETE_ALL.execute(connection, dataset); } catch (DatabaseUnitException e) { @@ -212,42 +225,49 @@ public class DatabaseTesterComponent { } /** + * + * * @throws SQLException */ public String[] getTableNames() throws SQLException { - List result = new ArrayList(); - LOG.debug("Getting database table names to clean (schema: '" - + SCHEMA_PATTERN + "'"); + LOG.debug("Getting database table names to clean (schema: '" + + SCHEMA_PATTERN + "'"); ResultSet tables = getConnection().getMetaData().getTables(null, - SCHEMA_PATTERN, "%", new String[] { "TABLE" }); + SCHEMA_PATTERN, "%", new String[] { "TABLE" }); + while (tables.next()) { String table = tables.getString("TABLE_NAME"); + // Make sure we do not touch hibernate's specific // infrastructure tables. if (!table.toLowerCase().startsWith("hibernate")) { result.add(table); - LOG.debug("Adding " + table - + " to list of tables to be cleaned."); + LOG.debug("Adding " + table + + " to list of tables to be cleaned."); } } + return (String[]) result.toArray(new String[0]); } /** - * @return + * + * * @throws SQLException */ public void emptyTables(List aTableList) throws SQLException { Iterator liTable = aTableList.iterator(); + while (liTable.hasNext()) { emptyTable((String) liTable.next()); } } /** - * @return + * + * * @throws SQLException */ public void emptyTable(String aTable) throws SQLException { @@ -255,7 +275,8 @@ public class DatabaseTesterComponent { } /** - * @return + * + * * @throws SQLException */ public void dropTable(String aTable) throws SQLException { @@ -267,6 +288,7 @@ public class DatabaseTesterComponent { * * @param aSql * SQL statement. + * * @return Return code of the corresponding JDBC call. */ public int executeSql(final String aSql) { @@ -282,6 +304,7 @@ public class DatabaseTesterComponent { * SQL statement. * @param aArg * Argument of the sql statement. + * * @return Return code of the corresponding JDBC call. */ public int executeSql(final String aSql, final Object aArg) { @@ -297,6 +320,7 @@ public class DatabaseTesterComponent { * SQL query to execute. * @param aArgs * Arguments. + * * @return Number of rows updated. */ public int executeSql(final String aSql, final Object[] aArgs) { @@ -320,11 +344,13 @@ public class DatabaseTesterComponent { * * @param aCallback * Callback to do your transactional work. + * * @return Result. */ public Object executeTransaction(TransactionCallback aCallback) { TransactionTemplate lTemplate = new TransactionTemplate( - getTransactionManager()); + getTransactionManager()); + return lTemplate.execute(aCallback); } @@ -336,7 +362,7 @@ public class DatabaseTesterComponent { */ public void executeTransaction(TransactionCallbackWithoutResult aCallback) { TransactionTemplate template = new TransactionTemplate( - getTransactionManager()); + getTransactionManager()); template.execute(aCallback); } @@ -346,7 +372,9 @@ public class DatabaseTesterComponent { * * @param aCallback * Code to be executed within the transaction. + * * @return Result. + * */ public Map executeTransaction(final TestTransactionCallback aCallback) { return (Map) executeTransaction(new TransactionCallback() { @@ -368,9 +396,10 @@ public class DatabaseTesterComponent { * * @param aCallback * Code to be executed within the transaction. + * */ public void executeTransaction( - final TestTransactionCallbackWithoutResult aCallback) { + final TestTransactionCallbackWithoutResult aCallback) { executeTransaction(new TransactionCallbackWithoutResult() { public void doInTransactionWithoutResult(TransactionStatus aArg) { try { @@ -388,6 +417,7 @@ public class DatabaseTesterComponent { * * @param aSql * Query to execute. + * * @return Result set. */ public ResultSet executeQuery(String aSql) { @@ -403,6 +433,7 @@ public class DatabaseTesterComponent { * Query. * @param aArg * Argument. + * * @return Result set. */ public ResultSet executeQuery(String aSql, Object aArg) { @@ -418,7 +449,9 @@ public class DatabaseTesterComponent { * Sql query. * @param aArgs * Arguments to the query. + * * @return Result set. + * */ public ResultSet executeQuery(final String aSql, final Object[] aArgs) { try { @@ -442,10 +475,11 @@ public class DatabaseTesterComponent { * Arguments to the prepared statement. * @param aStatement * Prepared statement + * * @throws SQLException */ private void setPreparedParams(final Object[] aArgs, - PreparedStatement aStatement) throws SQLException { + PreparedStatement aStatement) throws SQLException { for (int i = 1; i <= aArgs.length; i++) { setPreparedParam(i, aStatement, aArgs[i - 1]); } @@ -459,11 +493,12 @@ public class DatabaseTesterComponent { * @param aStatement * Prepared statement. * @param aObject - * Value Must be of type Integer, Long, or String. + * Value Must be of type Integer, Long, or String. + * * @throws SQLException */ private void setPreparedParam(int aIndex, PreparedStatement aStatement, - Object aObject) throws SQLException { + Object aObject) throws SQLException { if (aObject instanceof Integer) { aStatement.setInt(aIndex, ((Integer) aObject).intValue()); } else if (aObject instanceof Long) { @@ -471,9 +506,9 @@ public class DatabaseTesterComponent { } else if (aObject instanceof String) { aStatement.setString(aIndex, (String) aObject); } else { - TestCase.fail("Unsupported object type for prepared statement: " - + aObject.getClass() + " value: " + aObject - + " statement: " + aStatement); + TestCase.fail("Unsupported object type for prepared statement: " + + aObject.getClass() + " value: " + aObject + " statement: " + + aStatement); } } @@ -483,28 +518,33 @@ public class DatabaseTesterComponent { } catch (NoSuchBeanDefinitionException e) { return false; } + return true; } /** + * * @return Returns the dataSource. */ public DataSource getDataSource() { - return _dataSource; + return dataSource; } /** + * + * * @return + * * @throws SQLException */ public int getTableSize(final String aTable) throws SQLException { - ResultSet resultSet = executeQuery("select * from " + aTable); int count = 0; while (resultSet.next()) { count++; } + return count; } @@ -517,5 +557,4 @@ public class DatabaseTesterComponent { return count; } - } diff --git a/test/README.txt b/test/README.txt new file mode 100644 index 00000000..48a58473 --- /dev/null +++ b/test/README.txt @@ -0,0 +1,4 @@ + +Behavior which requires a persistence provider but does not use the persistence provider +extensively is only tested with hibernate. + diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java index 856b0519..36862965 100644 --- a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java +++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkJpaCustomizer.java @@ -1,30 +1,53 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.eclipselink; -import java.util.Map; - import org.dbunit.dataset.filter.ITableFilterSimple; + import org.wamblee.support.persistence.JpaCustomizer; import org.wamblee.support.persistence.PersistenceUnitDescription; -public class EclipselinkJpaCustomizer implements JpaCustomizer { +import java.util.Map; - public EclipselinkJpaCustomizer() { +/** + * + * @author $author$ + * @version $Revision$ + */ +public class EclipselinkJpaCustomizer implements JpaCustomizer { + /** + * Creates a new EclipselinkJpaCustomizer object. + */ + public EclipselinkJpaCustomizer() { // Empty } - + @Override - public void customize(PersistenceUnitDescription aPersistenceUnit, Map aJpaProperties) { + public void customize(PersistenceUnitDescription aPersistenceUnit, + Map aJpaProperties) { // Hack to make JNDI lookup of the datasource work with toplink - aJpaProperties.put("eclipselink.session.customizer", JndiSessionCustomizer.class - .getName()); - + aJpaProperties.put("eclipselink.session.customizer", + JndiSessionCustomizer.class.getName()); + // DDL generation for toplink - aJpaProperties.put("eclipselink.ddl-generation", "create-tables"); + aJpaProperties.put("eclipselink.ddl-generation", "create-tables"); } - + @Override public ITableFilterSimple getJpaTables() { return new EclipselinkTables(); } - } diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java index d4df0ddd..29872d01 100644 --- a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java +++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/EclipselinkTables.java @@ -1,20 +1,34 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.eclipselink; -import java.util.Arrays; -import java.util.List; - import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.filter.ITableFilterSimple; +import java.util.Arrays; +import java.util.List; + /** - * Toplink-specific tables. + * Toplink-specific tables. */ public class EclipselinkTables implements ITableFilterSimple { + private static final List TABLES = Arrays + .asList(new String[] { "SEQUENCE" }); - private static final List TABLES = Arrays.asList(new String[] { "SEQUENCE" } ); - - public boolean accept(String aTableName) throws DataSetException { - return TABLES.contains(aTableName); - } - + public boolean accept(String aTableName) throws DataSetException { + return TABLES.contains(aTableName); + } } diff --git a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java index 9b856f05..ca74ec5c 100644 --- a/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java +++ b/test/eclipselink/src/main/java/org/wamblee/support/persistence/eclipselink/JndiSessionCustomizer.java @@ -1,59 +1,86 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.eclipselink; -import javax.naming.Context; -import javax.naming.InitialContext; - import org.eclipse.persistence.config.SessionCustomizer; import org.eclipse.persistence.sessions.DatabaseLogin; import org.eclipse.persistence.sessions.JNDIConnector; import org.eclipse.persistence.sessions.Session; import org.eclipse.persistence.sessions.server.ServerSession; - + +import javax.naming.Context; +import javax.naming.InitialContext; + /** - * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) Use for clients that would like to use a - * JTA SE pu instead of a RESOURCE_LOCAL SE pu. - * - * This utility also makes sure that using a persistence.xml with a JTA datasource works in a standalone Java SE - * environment together with our JNDI stub. + * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) + * Use for clients that would like to use a JTA SE pu instead of a + * RESOURCE_LOCAL SE pu. This utility also makes sure that using a + * persistence.xml with a JTA datasource works in a standalone Java SE + * environment together with our JNDI stub. */ -public class JndiSessionCustomizer - implements SessionCustomizer { - - public JndiSessionCustomizer() { - // Empty. - } - - /** - * Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP - */ - public void customize(Session session) throws Exception { - JNDIConnector connector = null; - Context context = null; - try { - context = new InitialContext(); - if(null != context) { - connector = (JNDIConnector)session.getLogin().getConnector(); // possible CCE - // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP - // Note: if both jta and non-jta elements exist this will only change the first one - and may still result in - // the COMPOSITE_NAME_LOOKUP being set - // Make sure only jta-data-source is in persistence.xml with no non-jta-data-source property set - connector.setLookupType(JNDIConnector.STRING_LOOKUP); - - // Or, if you are specifying both JTA and non-JTA in your persistence.xml then set both connectors to be safe - JNDIConnector writeConnector = (JNDIConnector)session.getLogin().getConnector(); - writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP); - JNDIConnector readConnector = - (JNDIConnector)((DatabaseLogin)((ServerSession)session).getReadConnectionPool().getLogin()).getConnector(); - readConnector.setLookupType(JNDIConnector.STRING_LOOKUP); - - System.out.println("JndiSessionCustomizer: configured " + connector.getName()); - } - else { - throw new Exception("JndiSessionCustomizer: Context is null"); - } +public class JndiSessionCustomizer implements SessionCustomizer { + /** + * Creates a new JndiSessionCustomizer object. + */ + public JndiSessionCustomizer() { + // Empty. } - catch(Exception e) { - e.printStackTrace(); + + /** + * Get a dataSource connection and set it on the session with + * lookupType=STRING_LOOKUP + * + * + */ + public void customize(Session aSession) throws Exception { + JNDIConnector connector = null; + Context context = null; + + try { + context = new InitialContext(); + + if (null != context) { + connector = (JNDIConnector) aSession.getLogin().getConnector(); // possible + // CCE + // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP + // Note: if both jta and non-jta elements exist this will only + // change the first one - and may still result in + // the COMPOSITE_NAME_LOOKUP being set + // Make sure only jta-data-source is in persistence.xml with no + // non-jta-data-source property set + + connector.setLookupType(JNDIConnector.STRING_LOOKUP); + + // Or, if you are specifying both JTA and non-JTA in your + // persistence.xml then set both connectors to be safe + JNDIConnector writeConnector = (JNDIConnector) aSession + .getLogin().getConnector(); + writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP); + + JNDIConnector readConnector = (JNDIConnector) ((DatabaseLogin) ((ServerSession) aSession) + .getReadConnectionPool().getLogin()).getConnector(); + readConnector.setLookupType(JNDIConnector.STRING_LOOKUP); + + System.out.println("JndiSessionCustomizer: configured " + + connector.getName()); + } else { + throw new Exception("JndiSessionCustomizer: Context is null"); + } + } catch (Exception e) { + e.printStackTrace(); + } } - } -} \ No newline at end of file +} diff --git a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java index 870e20a2..b2113694 100644 --- a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java +++ b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/DatabaseUtilsTest.java @@ -1,23 +1,47 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.eclipselink; import static junit.framework.Assert.assertEquals; -import javax.persistence.EntityManager; -import javax.sql.DataSource; - import org.dbunit.IDatabaseTester; + import org.dbunit.dataset.ITable; + import org.junit.After; import org.junit.Before; import org.junit.Test; + import org.wamblee.support.persistence.Database; import org.wamblee.support.persistence.DatabaseBuilder; import org.wamblee.support.persistence.DatabaseUtils; import org.wamblee.support.persistence.DatabaseUtilsTestBase; import org.wamblee.support.persistence.JpaBuilder; -import org.wamblee.support.persistence.PersistenceUnitDescription; import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; +import org.wamblee.support.persistence.PersistenceUnitDescription; + +import javax.persistence.EntityManager; + +import javax.sql.DataSource; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatabaseUtilsTest extends DatabaseUtilsTestBase { - // Empty, all tests inherited + // Empty, all tests inherited } diff --git a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java index 84c3fff5..84a90d21 100644 --- a/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java +++ b/test/eclipselink/src/test/java/org/wamblee/support/persistence/eclipselink/MyEntityExampleTest.java @@ -1,28 +1,46 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.eclipselink; -import javax.persistence.EntityManager; -import javax.persistence.Persistence; -import javax.sql.DataSource; +import static junit.framework.Assert.*; import org.dbunit.DataSourceDatabaseTester; import org.dbunit.DatabaseTestCase; import org.dbunit.IDatabaseTester; + import org.dbunit.dataset.ITable; import org.dbunit.dataset.filter.ITableFilterSimple; + import org.junit.After; import org.junit.Before; import org.junit.Test; + import org.wamblee.support.persistence.DatabaseUtils; import org.wamblee.support.persistence.JpaBuilder; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; import org.wamblee.support.persistence.JpaTester; import org.wamblee.support.persistence.MyEntityExampleTestBase; -import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; -import static junit.framework.Assert.*; +import javax.persistence.EntityManager; +import javax.persistence.Persistence; +import javax.sql.DataSource; /** - * This class shows an example of how to test an entity using jpa. + * This class shows an example of how to test an entity using jpa. */ public class MyEntityExampleTest extends MyEntityExampleTestBase { // Empty, all tests are inherited diff --git a/test/enterprise/src/main/java/org/wamblee/support/ThreadSpecificProxyFactory.java b/test/enterprise/src/main/java/org/wamblee/support/ThreadSpecificProxyFactory.java new file mode 100644 index 00000000..e47c037a --- /dev/null +++ b/test/enterprise/src/main/java/org/wamblee/support/ThreadSpecificProxyFactory.java @@ -0,0 +1,96 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + * Thread-specific proxy is used to create implementations of interfaces that + * delegate to a thread-specific implementation of the service. + * + * It is used for instance to pass a transaction scoped entity manager around. + * + * @param T + * Interface to proxy. + * @author Erik Brakkee + * + */ +public class ThreadSpecificProxyFactory { + private class ThreadSpecificInvocationHandler implements InvocationHandler { + + @Override + public Object invoke(Object aProxy, Method aMethod, Object[] aArgs) + throws Throwable { + try { + return aMethod.invoke(svc.get(), aArgs); + } catch (InvocationTargetException e) { + throw e.getCause(); + } + } + } + + private ThreadLocal svc = new ThreadLocal(); + private Class clazz; + + /** + * Constructs the factory. + * + * @param aClass + * Interface class of the service to proxy. + */ + public ThreadSpecificProxyFactory(Class aClass) { + if (!aClass.isInterface()) { + throw new IllegalArgumentException("Class " + aClass.getName() + + " is not an interface"); + } + clazz = aClass; + } + + /** + * Sets the thread-specific service. + * + * @param aService + * Service, use null value to reset. + */ + public void set(T aService) { + svc.set(aService); + } + + /** + * Gets the proxy that delegates to the thread-specific instance set by + * {@link #set(Object)} + * + * @return Proxy. + */ + public T getProxy() { + InvocationHandler handler = new ThreadSpecificInvocationHandler(); + Class proxyClass = Proxy.getProxyClass(clazz.getClassLoader(), + new Class[] { clazz }); + T proxy; + try { + proxy = (T) proxyClass.getConstructor( + new Class[] { InvocationHandler.class }).newInstance( + new Object[] { handler }); + return proxy; + } catch (Exception e) { + throw new RuntimeException("Could not create proxy for " + + clazz.getName(), e); + } + } +} diff --git a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java index a7e4c965..4db8a112 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java +++ b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContext.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.jndi; import java.util.HashMap; @@ -8,24 +23,24 @@ import javax.naming.Name; import javax.naming.NamingException; public class StubInitialContext extends InitialContext { - private Map bindings = new HashMap(); + private Map bindings = new HashMap(); - public StubInitialContext() throws NamingException { - super(true); - } - - @Override - public void bind(String name, Object obj) throws NamingException { - bindings.put(name, obj); - } + public StubInitialContext() throws NamingException { + super(true); + } - @Override - public Object lookup(String name) throws NamingException { - return bindings.get(name); - } - - @Override - public Object lookup(Name name) throws NamingException { - return super.lookup(name.toString()); - } + @Override + public void bind(String aName, Object aObj) throws NamingException { + bindings.put(aName, aObj); + } + + @Override + public Object lookup(String aName) throws NamingException { + return bindings.get(aName); + } + + @Override + public Object lookup(Name aName) throws NamingException { + return super.lookup(aName.toString()); + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java index c7e4e2fd..d65968a2 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java +++ b/test/enterprise/src/main/java/org/wamblee/support/jndi/StubInitialContextFactory.java @@ -1,11 +1,23 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.jndi; -import java.util.HashMap; import java.util.Hashtable; -import java.util.Map; import javax.naming.Context; -import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.spi.InitialContextFactory; @@ -23,41 +35,41 @@ import javax.naming.spi.InitialContextFactory; */ public class StubInitialContextFactory implements InitialContextFactory { - private static Context context; - - private static void initialize() { - try { - context = new StubInitialContext(); - } catch (NamingException e) { // can't happen. - throw new RuntimeException(e); - } - } - - /** - * This method must be called to register this initial context factory as - * the default implementation for JNDI. - * - * @throws Exception - */ - public static void register() { - // sets up the InitialContextFactoryForTest as default factory. - System.setProperty(Context.INITIAL_CONTEXT_FACTORY, - StubInitialContextFactory.class.getName()); - if (context == null) { - initialize(); - } - } - - /** - * Unregisters the initial context factory - */ - public static void unregister() { - System.setProperty(Context.INITIAL_CONTEXT_FACTORY, ""); - context = null; - } - - public Context getInitialContext(Hashtable environment) - throws NamingException { - return context; - } + private static Context CONTEXT; + + private static void initialize() { + try { + CONTEXT = new StubInitialContext(); + } catch (NamingException e) { // can't happen. + throw new RuntimeException(e); + } + } + + /** + * This method must be called to register this initial context factory as + * the default implementation for JNDI. + * + * @throws Exception + */ + public static void register() { + // sets up the InitialContextFactoryForTest as default factory. + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, + StubInitialContextFactory.class.getName()); + if (CONTEXT == null) { + initialize(); + } + } + + /** + * Unregisters the initial context factory + */ + public static void unregister() { + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, ""); + CONTEXT = null; + } + + public Context getInitialContext(Hashtable aEnvironment) + throws NamingException { + return CONTEXT; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java index 59f3d776..0fc871f1 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabase.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import javax.sql.DataSource; @@ -9,70 +24,78 @@ import org.apache.commons.dbcp.PoolingDataSource; import org.apache.commons.pool.impl.GenericObjectPool; public abstract class AbstractDatabase implements Database { - private static final int CONNECTION_POOL_SIZE = 16; + private static final int CONNECTION_POOL_SIZE = 16; - private DataSource itsDataSource; - - private boolean started; - - protected AbstractDatabase() { - started = false; - } - - protected abstract void doStart(); - - protected abstract void doStop(); - - /** - * This method must be called from the start method. - */ - protected final void createDataSource() { - GenericObjectPool connectionPool = new GenericObjectPool(null); - connectionPool.setMaxActive(CONNECTION_POOL_SIZE); - ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(getJdbcUrl(), getUsername(), getPassword()); - // The following line must be kept in although it does not appear to be used, the constructor regsiters the - // constructed object at the connection pool. - PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,connectionPool,null,null,false,true); - itsDataSource = new PoolingDataSource(connectionPool); - } - - - /// BELOW THIS LINE IS NOT OF INTEREST TO SUBCLASSES. - - public final DataSource start() { - if ( started ) { - throw new RuntimeException("Database already started"); - } - started = true; - doStart(); - return getDatasource(); - } - - public final void stop() { - if ( ! started ) { - return; // nothing to do. - } - started = false; - doStop(); - } + private DataSource itsDataSource; - private final DataSource getDatasource() { - if ( !started) { - throw new RuntimeException("Database is not started!"); - } - return itsDataSource; - } - - protected String getProperty(String aName) { - String value = System.getProperty(aName); - if ( value != null ) { - return value; - } - value = System.getenv(aName); - if ( value != null ) { - return value; - } - throw new RuntimeException("This class expects the '" + aName + "' property to be set"); - } + private boolean started; + + protected AbstractDatabase() { + started = false; + } + + protected abstract void doStart(); + + protected abstract void doStop(); + + /** + * This method must be called from the start method. + */ + protected final void createDataSource() { + GenericObjectPool connectionPool = new GenericObjectPool(null); + connectionPool.setMaxActive(CONNECTION_POOL_SIZE); + ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( + getJdbcUrl(), getUsername(), getPassword()); + // The following line must be kept in although it does not appear to be + // used, the constructor regsiters the + // constructed object at the connection pool. + PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory( + connectionFactory, connectionPool, null, null, false, true); + ingoredVariable(poolableConnectionFactory); + itsDataSource = new PoolingDataSource(connectionPool); + } + + private static void ingoredVariable(PoolableConnectionFactory aFactory) { + // Empty + } + + // / BELOW THIS LINE IS NOT OF INTEREST TO SUBCLASSES. + + public final DataSource start() { + if (started) { + throw new RuntimeException("Database already started"); + } + started = true; + doStart(); + return getDatasource(); + } + + public final void stop() { + if (!started) { + return; // nothing to do. + } + started = false; + doStop(); + } + + private final DataSource getDatasource() { + if (!started) { + throw new RuntimeException("Database is not started!"); + } + return itsDataSource; + } + + protected String getProperty(String aName) { + String value = System.getProperty(aName); + if (value != null) { + return value; + } + value = System.getenv(aName); + if (value != null) { + return value; + } + throw new RuntimeException("This class expects the '" + aName + + "' property to be set"); + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java index 6ed9d6cb..65cca2b0 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/AbstractDatabaseProvider.java @@ -1,18 +1,33 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.List; public abstract class AbstractDatabaseProvider implements DatabaseProvider { - protected abstract List getCapabilities(); + protected abstract List getCapabilities(); - public final boolean supportsCapabilities(String[] aCapabilities) { - for (String capability: aCapabilities) { - if ( !getCapabilities().contains(capability)) { - return false; - } - } - return true; - } + public final boolean supportsCapabilities(String[] aCapabilities) { + for (String capability : aCapabilities) { + if (!getCapabilities().contains(capability)) { + return false; + } + } + return true; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java index fc6ecc7c..cdc264d7 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaCustomizer.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.List; @@ -6,28 +21,29 @@ import java.util.Map; import org.dbunit.dataset.filter.ITableFilterSimple; public class CompositeJpaCustomizer implements JpaCustomizer { - - private List _customizers; - private CompositeJpaTables _tables; - - public CompositeJpaCustomizer(List aCustomizers) { - _customizers = aCustomizers; - _tables = new CompositeJpaTables(); - for (JpaCustomizer customizer: _customizers) { - _tables.add(customizer.getJpaTables()); - } + + private List customizers; + private CompositeJpaTables tables; + + public CompositeJpaCustomizer(List aCustomizers) { + customizers = aCustomizers; + tables = new CompositeJpaTables(); + for (JpaCustomizer customizer : customizers) { + tables.add(customizer.getJpaTables()); + } } - + @Override - public void customize(PersistenceUnitDescription aPersistenceUnit, Map aJpaProperties) { - for (JpaCustomizer customizer: _customizers) { - customizer.customize(aPersistenceUnit, aJpaProperties); + public void customize(PersistenceUnitDescription aPersistenceUnit, + Map aJpaProperties) { + for (JpaCustomizer customizer : customizers) { + customizer.customize(aPersistenceUnit, aJpaProperties); } } @Override public ITableFilterSimple getJpaTables() { - return _tables; + return tables; } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java index 7a7e8de6..25f4894d 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/CompositeJpaTables.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.ArrayList; @@ -7,25 +22,25 @@ import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.filter.ITableFilterSimple; public class CompositeJpaTables implements ITableFilterSimple { - - private List _tables; - - public CompositeJpaTables() { - _tables = new ArrayList(); + + private List tables; + + public CompositeJpaTables() { + tables = new ArrayList(); } - - public void add(ITableFilterSimple aFilter) { - _tables.add(aFilter); + + public void add(ITableFilterSimple aFilter) { + tables.add(aFilter); } @Override public boolean accept(String aTableName) throws DataSetException { - for (ITableFilterSimple filter: _tables) { - if (filter.accept(aTableName)) { - return true; + for (ITableFilterSimple filter : tables) { + if (filter.accept(aTableName)) { + return true; } } - return false; + return false; } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java index f37474ea..987646ec 100755 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/Database.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - */ + */ package org.wamblee.support.persistence; import javax.sql.DataSource; @@ -23,13 +23,13 @@ import javax.sql.DataSource; * @author Erik Brakkee */ public interface Database { - + /** * Starts a database. This call should not block and return as soon as the * database has been started. */ DataSource start(); - + /** * Gets the Jdbc Url to connect to this database. * diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java index 9c599a0a..d8807c38 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.ArrayList; @@ -9,9 +24,9 @@ import java.util.logging.Logger; /** * DatabaseBuilder is used from unit test to obtain a reference to a database * from unit test. This database is either an inmemory database or represents an - * external database. Purpose of this utility is to make test code independent of the - * particular database used and specifically to be able to run database tests without - * any configuration at all (using an inmemory database). + * external database. Purpose of this utility is to make test code independent + * of the particular database used and specifically to be able to run database + * tests without any configuration at all (using an inmemory database). * * The type of database to use can be overridden by specifying either a system * property or an environment variable ({@link #DB_CAPABILITIES_PROP}) that @@ -19,98 +34,95 @@ import java.util.logging.Logger; * provides its own capabilities (see {@link DatabaseProvider} implementations}. * * - * There are currently two database types available: + * There are currently two database types available: *
    - *
  • Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This is the default. - *
  • - *
  • External: An arbitrary external database configured using system properties or environment variables - * in the usual way using a JDBC URL, username, and password. - *
  • + *
  • Derby: AN inmemory derby. Provided by {@link DerbyDatabaseProvider}. This + * is the default.
  • + *
  • External: An arbitrary external database configured using system + * properties or environment variables in the usual way using a JDBC URL, + * username, and password.
  • *
* - * The DatabaseBuilder uses the {@link ServiceLoader} mechanism to find implementations - * of {@link DatabaseProvider} on the classpath. In the {@link #getDatabase(String...)} method a number of - * capabilities are passed. The database providers are then searched in (arbitrary) order and the first one that - * has all required capabilities is returned. + * The DatabaseBuilder uses the {@link ServiceLoader} mechanism to + * find implementations of {@link DatabaseProvider} on the classpath. In the + * {@link #getDatabase(String...)} method a number of capabilities are passed. + * The database providers are then searched in (arbitrary) order and the first + * one that has all required capabilities is returned. * - * {@link #getSupportedDatabases()} gives a list of all available databases. + * {@link #getSupportedDatabases()} gives a list of all available databases. */ public class DatabaseBuilder { - private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class - .getName()); - - /** - * Environmment variable by which capabilities of the requested database can - * be defined - */ - private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES"; + private static final Logger LOGGER = Logger.getLogger(DatabaseBuilder.class + .getName()); - private static ServiceLoader LOADER = null; + /** + * Environmment variable by which capabilities of the requested database can + * be defined + */ + private static final String DB_CAPABILITIES_PROP = "TEST_DB_CAPABILITIES"; - private DatabaseBuilder() { - // Empty. - } + private static ServiceLoader LOADER = + ServiceLoader.load(DatabaseProvider.class); - private static String[] parseCapabilities(String aValue) { - return aValue.split(","); - } + private DatabaseBuilder() { + // Empty. + } - /** - * Gets the first database that has all required capabilities. - * @param aCapabilities Capabilities. - * @return Database to use. - */ - public static Database getDatabase(String... aCapabilities) { - if (aCapabilities.length == 0) { - LOGGER.info("Examining database capabilities"); - LOGGER.info(" Checking system property " + DB_CAPABILITIES_PROP); - String capabilities = System.getProperty(DB_CAPABILITIES_PROP); - if (capabilities != null) { - aCapabilities = parseCapabilities(capabilities); - } else { - LOGGER.info(" Checking environment variable " - + DB_CAPABILITIES_PROP); - capabilities = System.getenv(DB_CAPABILITIES_PROP); - if (capabilities != null) { - aCapabilities = parseCapabilities(capabilities); - } else { - LOGGER.info(" Using default capabilities"); - aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY }; - } - } - LOGGER.info("Using capabilities: " + aCapabilities); - } - synchronized (DatabaseBuilder.class) { - initLoader(); - for (DatabaseProvider db : LOADER) { - if (db.supportsCapabilities(aCapabilities)) { - return db.create(); - } - } - } - throw new RuntimeException( - "No database found that satisfies capabilities: " - + Arrays.asList(aCapabilities)); - } + private static String[] parseCapabilities(String aValue) { + return aValue.split(","); + } - /** - * Gets a list of available databases. - * @return List of databases. - */ - public static List getSupportedDatabases() { - initLoader(); - List descriptions = new ArrayList(); - for (DatabaseProvider db : LOADER) { - descriptions.add(db.getDescription()); - } - return descriptions; - } + /** + * Gets the first database that has all required capabilities. + * + * @param aCapabilities + * Capabilities. + * @return Database to use. + */ + public static Database getDatabase(String... aCapabilities) { + if (aCapabilities.length == 0) { + LOGGER.info("Examining database capabilities"); + LOGGER.info(" Checking system property " + DB_CAPABILITIES_PROP); + String capabilities = System.getProperty(DB_CAPABILITIES_PROP); + if (capabilities != null) { + aCapabilities = parseCapabilities(capabilities); + } else { + LOGGER.info(" Checking environment variable " + + DB_CAPABILITIES_PROP); + capabilities = System.getenv(DB_CAPABILITIES_PROP); + if (capabilities != null) { + aCapabilities = parseCapabilities(capabilities); + } else { + LOGGER.info(" Using default capabilities"); + aCapabilities = new String[] { DatabaseProvider.CAPABILITY_IN_MEMORY }; + } + } + LOGGER.info("Using capabilities: " + Arrays.asList(aCapabilities)); + } + synchronized (DatabaseBuilder.class) { + for (DatabaseProvider db : LOADER) { + if (db.supportsCapabilities(aCapabilities)) { + return db.create(); + } + } + } + throw new RuntimeException( + "No database found that satisfies capabilities: " + + Arrays.asList(aCapabilities)); + } - private static void initLoader() { - if (LOADER == null) { - LOADER = ServiceLoader.load(DatabaseProvider.class); - } - } + /** + * Gets a list of available databases. + * + * @return List of databases. + */ + public static List getSupportedDatabases() { + List descriptions = new ArrayList(); + for (DatabaseProvider db : LOADER) { + descriptions.add(db.getDescription()); + } + return descriptions; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java index c31427bc..8427c1d8 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseDescription.java @@ -1,41 +1,60 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; /** - * Description of a specific database. + * Description of a specific database. */ public class DatabaseDescription { - private String[] itsCapabilities; - private String itsDatabase; - private String itsOther; - - /** - * Constructs the description. - * @param aCapabilities List of all capabilities. - * @param aDatabase Database. - * @param aOther Other information. - */ - public DatabaseDescription(String[] aCapabilities, String aDatabase, String aOther) { - itsCapabilities = aCapabilities; - itsDatabase = aDatabase; - itsOther = aOther; - } - - @Override - public String toString() { - return "\n Database " + itsDatabase + - "\n Capabilities: " + printCapabilities() + - "\n Other info: " + itsOther; - } - - private String printCapabilities() { - String res = ""; - for (int i = 0; i < itsCapabilities.length; i++) { - res += "" + itsCapabilities[i]; - if ( i < itsCapabilities.length -1 ) { - res += ", "; - } - } - return res; - } + private String[] itsCapabilities; + private String itsDatabase; + private String itsOther; + + /** + * Constructs the description. + * + * @param aCapabilities + * List of all capabilities. + * @param aDatabase + * Database. + * @param aOther + * Other information. + */ + public DatabaseDescription(String[] aCapabilities, String aDatabase, + String aOther) { + itsCapabilities = aCapabilities; + itsDatabase = aDatabase; + itsOther = aOther; + } + + @Override + public String toString() { + return "\n Database " + itsDatabase + "\n Capabilities: " + + printCapabilities() + "\n Other info: " + itsOther; + } + + private String printCapabilities() { + StringBuffer res = new StringBuffer(); + for (int i = 0; i < itsCapabilities.length; i++) { + res.append(itsCapabilities[i]); + if (i < itsCapabilities.length - 1) { + res.append(", "); + } + } + return res.toString(); + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java index f6736aa1..965a2b4f 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseProvider.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; /** @@ -11,32 +26,37 @@ package org.wamblee.support.persistence; */ public interface DatabaseProvider { - /** - * Capability that all databases that run inmemory have. - */ - String CAPABILITY_IN_MEMORY = "INMEMORY"; + /** + * Capability that all databases that run inmemory have. + */ + String CAPABILITY_IN_MEMORY = "INMEMORY"; - /** - * Capability that all databases that are external have. - */ - String CAPABILITY_EXTERNAL = "EXTERNAL"; + /** + * Capability that all databases that are external have. + */ + String CAPABILITY_EXTERNAL = "EXTERNAL"; - /** - * Determines if the database has all capabilities that are requested. - * @param aCapabilities Capabilities it must ahve - * @return True if it has all capabilities. - */ - boolean supportsCapabilities(String[] aCapabilities); + /** + * Determines if the database has all capabilities that are requested. + * + * @param aCapabilities + * Capabilities it must ahve + * @return True if it has all capabilities. + */ + boolean supportsCapabilities(String[] aCapabilities); - /** - * Gets the description for the database. - * @return Description. - */ - DatabaseDescription getDescription(); + /** + * Gets the description for the database. + * + * @return Description. + */ + DatabaseDescription getDescription(); - /** - * Creates a database instance that represents a running instance of that database. - * @return Database. - */ - Database create(); + /** + * Creates a database instance that represents a running instance of that + * database. + * + * @return Database. + */ + Database create(); } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java index 44294e35..45e96499 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseStarter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,6 @@ */ package org.wamblee.support.persistence; - /** * This class is used for starting the database from ant. */ @@ -24,7 +23,7 @@ public class DatabaseStarter { /** * Database class which encapsulates management of the database. */ - private Class _databaseClass; + private Class databaseClass; /** * Execution as a main program. Commandline @@ -32,22 +31,21 @@ public class DatabaseStarter { *
      * 
      *    DatabaseStarter <databaseClassName>
-     *  
+     * 
      * 
* * where the database class name must be the name of a concrete subclass of * {@link Database}. * - * @param args + * @param aArgs */ - public static void main( String[] args ) throws Exception { - String clazz = args[0]; + public static void main(String[] aArgs) throws Exception { + String clazz = aArgs[0]; try { - new DatabaseStarter( Class.forName( clazz ) ).start( ); - } catch ( Exception e ) { - e.printStackTrace( ); - System.out - .println( "\nUsage: ant dbClass "); + new DatabaseStarter(Class.forName(clazz)).start(); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("\nUsage: ant dbClass "); } } @@ -58,13 +56,12 @@ public class DatabaseStarter { * Classname of the database class to use. * @throws Exception */ - public DatabaseStarter( Class aClass ) throws Exception { - if ( !Database.class.isAssignableFrom( aClass ) ) { - throw new IllegalArgumentException( "Class '" - + aClass.getName( ) - + "' is not a subclass of Database" ); + public DatabaseStarter(Class aClass) throws Exception { + if (!Database.class.isAssignableFrom(aClass)) { + throw new IllegalArgumentException("Class '" + aClass.getName() + + "' is not a subclass of Database"); } - _databaseClass = aClass; + databaseClass = aClass; } /** @@ -72,8 +69,8 @@ public class DatabaseStarter { * * @throws Exception */ - public DatabaseStarter( ) throws Exception { - this( DerbyDatabase.class ); + public DatabaseStarter() throws Exception { + this(DerbyDatabase.class); } /** @@ -81,26 +78,26 @@ public class DatabaseStarter { * * @throws Exception */ - public void start( ) throws Exception { - Database lDatabase = (Database) _databaseClass.newInstance( ); - lDatabase.start( ); - System.out.println( "Database has been started. " ); - System.out.println( ); - System.out.println("======================================================="); - System.out.println( "Connection details:" ); - // System.out.println( " Driver class: " - // + lDatabase.getDriverClassName( ) ); - System.out.println( " JDBC URL: " - + lDatabase.getExternalJdbcUrl( ) ); - System.out.println( " username: '" + lDatabase.getUsername( ) - + "'" ); - System.out.println( " password: '" + lDatabase.getPassword( ) - + "'" ); - System.out.println( "Interrupt the program to stop the database." ); - System.out.println("======================================================="); - System.out.println("You must now populate the database with a schema. Use 'ant help' for information."); - for ( ;; ) { - Thread.sleep( 1000 ); + public void start() throws Exception { + Database lDatabase = (Database) databaseClass.newInstance(); + lDatabase.start(); + System.out.println("Database has been started. "); + System.out.println(); + System.out + .println("======================================================="); + System.out.println("Connection details:"); + // System.out.println( " Driver class: " + // + lDatabase.getDriverClassName( ) ); + System.out.println(" JDBC URL: " + lDatabase.getExternalJdbcUrl()); + System.out.println(" username: '" + lDatabase.getUsername() + "'"); + System.out.println(" password: '" + lDatabase.getPassword() + "'"); + System.out.println("Interrupt the program to stop the database."); + System.out + .println("======================================================="); + System.out + .println("You must now populate the database with a schema. Use 'ant help' for information."); + for (;;) { + Thread.sleep(1000); } } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java index 312e38a0..311d2da3 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DatabaseUtils.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.sql.Connection; @@ -29,361 +44,366 @@ import org.dbunit.operation.DatabaseOperation; */ public class DatabaseUtils { - public static interface TableSet { - boolean contains(String aTableName); - } - - public static interface JdbcUnitOfWork { - T execute(Connection aConnection) throws Exception; - } - - public static interface TableSetOperation { - void execute(String aTable) throws Exception; - } - - private static final Logger LOG = Logger.getLogger(DatabaseUtils.class - .getName()); - - /** - * Schema pattern. - */ - private static final String SCHEMA_PATTERN = "%"; - private DataSource dataSource; - private ITableFilterSimple tables; - - - public DatabaseUtils(DataSource aDataSource, ITableFilterSimple aTables) { - dataSource = aDataSource; - tables = aTables; - } - - public IDatabaseTester createDbTester() throws Exception { - return createDbTester(getTableNames(tables)); - } - - public IDatabaseTester createDbTester(String[] aTables) throws Exception { - IDatabaseTester dbtester = new DataSourceDatabaseTester(dataSource); - dbtester.setDataSet(dbtester.getConnection().createDataSet(aTables)); - return dbtester; - } - - public void cleanDatabase() throws Exception { - cleanDatabase(tables); - } - - public void executeOnTables(ITableFilterSimple aTables, - final TableSetOperation aOperation) throws Exception { - final String[] tables = getTableNames(aTables); - executeInTransaction(new JdbcUnitOfWork() { - public Void execute(Connection aConnection) throws Exception { - for (int i = tables.length - 1; i >= 0; i--) { - aOperation.execute(tables[i]); - } - return null; - } - }); - for (String table : tables) { - - } - } - - public void cleanDatabase(ITableFilterSimple aSelection) throws Exception { - - final String[] tables = getTableNames(aSelection); - executeInTransaction(new JdbcUnitOfWork() { - - public Void execute(Connection aConnection) throws Exception { - IDatabaseConnection connection = new DatabaseConnection( - aConnection); - ITableFilter filter = new DatabaseSequenceFilter(connection, - tables); - IDataSet dataset = new FilteredDataSet(filter, connection - .createDataSet(tables)); - DatabaseOperation.DELETE_ALL.execute(connection, dataset); - return null; - } - }); - - } - - public T executeInTransaction(JdbcUnitOfWork aCallback) - throws Exception { - Connection connection = dataSource.getConnection(); - try { - T value = aCallback.execute(connection); - connection.commit(); - return value; - } finally { - connection.close(); - } - } - - public String[] getTableNames() throws Exception { - return getTableNames(tables); - } - - /** - * @throws SQLException - */ - public String[] getTableNames(ITableFilterSimple aSelection) - throws Exception { - - List result = new ArrayList(); - LOG.fine("Getting database table names to clean (schema: '" - + SCHEMA_PATTERN + "'"); - - ResultSet tables = dataSource.getConnection().getMetaData().getTables( - null, SCHEMA_PATTERN, "%", new String[] { "TABLE" }); - while (tables.next()) { - String table = tables.getString("TABLE_NAME"); - if (aSelection.accept(table)) { - result.add(table); - } - } - return (String[]) result.toArray(new String[0]); - } - - public void emptyTables() throws Exception { - executeOnTables(tables, new TableSetOperation() { - public void execute(String aTable) throws Exception { - emptyTable(aTable); - } - }); - } - - /** - * @return - * @throws SQLException - */ - public void emptyTables(final ITableFilterSimple aSelection) - throws Exception { - executeOnTables(aSelection, new TableSetOperation() { - public void execute(String aTable) throws Exception { - emptyTable(aTable); - } - }); - } - - /** - * @return - * @throws SQLException - */ - public void emptyTable(String aTable) throws Exception { - executeSql("delete from " + aTable); - } - - public void dropTables() throws Exception { - executeOnTables(tables, new TableSetOperation() { - - public void execute(String aTable) throws Exception { - dropTable(aTable); - } - }); - } - - - public void dropTables(ITableFilterSimple aTables) throws Exception { - executeOnTables(aTables, new TableSetOperation() { - - public void execute(String aTable) throws Exception { - dropTable(aTable); - } - }); - } - - /** - * @return - * @throws SQLException - */ - public void dropTable(final String aTable) throws Exception { - executeInTransaction(new JdbcUnitOfWork() { - public Void execute(Connection aConnection) throws Exception { - executeUpdate(aConnection, "drop table " + aTable); - return null; - } - }); - - } - - /** - * Executes an SQL statement within a transaction. - * - * @param aSql - * SQL statement. - * @return Return code of the corresponding JDBC call. - */ - public int executeSql(final String aSql) throws Exception { - return executeSql(aSql, new Object[0]); - } - - /** - * Executes an SQL statement within a transaction. See - * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on - * supported argument types. - * - * @param aSql - * SQL statement. - * @param aArg - * Argument of the sql statement. - * @return Return code of the corresponding JDBC call. - */ - public int executeSql(final String aSql, final Object aArg) - throws Exception { - return executeSql(aSql, new Object[] { aArg }); - } - - /** - * Executes an sql statement. See - * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on - * supported argument types. - * - * @param aSql - * SQL query to execute. - * @param aArgs - * Arguments. - * @return Number of rows updated. - */ - public int executeSql(final String aSql, final Object[] aArgs) - throws Exception { - return executeInTransaction(new JdbcUnitOfWork() { - public Integer execute(Connection aConnection) throws Exception { - PreparedStatement stmt = aConnection.prepareStatement(aSql); - setPreparedParams(aArgs, stmt); - return stmt.executeUpdate(); - } - }); - } - - /** - * Executes an SQL query. - * - * @param aSql - * Query to execute. - * @return Result set. - */ - public ResultSet executeQuery(Connection aConnection, String aSql) { - return executeQuery(aConnection, aSql, new Object[0]); - } - - /** - * Executes a query with a single argument. See - * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on - * supported argument types. - * - * @param aSql - * Query. - * @param aArg - * Argument. - * @return Result set. - */ - public ResultSet executeQuery(Connection aConnection, String aSql, - Object aArg) { - return executeQuery(aConnection, aSql, new Object[] { aArg }); - } - - /** - * Executes a query. See - * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on - * supported argument types. - * - * @param aSql - * Sql query. - * @param aArgs - * Arguments to the query. - * @return Result set. - */ - public ResultSet executeQuery(Connection aConnection, final String aSql, - final Object[] aArgs) { - try { - PreparedStatement statement = aConnection.prepareStatement(aSql); - setPreparedParams(aArgs, statement); - - return statement.executeQuery(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public int executeUpdate(Connection aConnection, final String aSql, - final Object... aArgs) { - try { - PreparedStatement statement = aConnection.prepareStatement(aSql); - setPreparedParams(aArgs, statement); - - return statement.executeUpdate(); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - /** - * Sets the values of a prepared statement. See - * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on - * supported argument types. - * - * @param aArgs - * Arguments to the prepared statement. - * @param aStatement - * Prepared statement - * @throws SQLException - */ - private void setPreparedParams(final Object[] aArgs, - PreparedStatement aStatement) throws SQLException { - for (int i = 1; i <= aArgs.length; i++) { - setPreparedParam(i, aStatement, aArgs[i - 1]); - } - } - - /** - * Sets a prepared statement parameter. - * - * @param aIndex - * Index of the parameter. - * @param aStatement - * Prepared statement. - * @param aObject - * Value Must be of type Integer, Long, or String. - * @throws SQLException - */ - private void setPreparedParam(int aIndex, PreparedStatement aStatement, - Object aObject) throws SQLException { - if (aObject instanceof Integer) { - aStatement.setInt(aIndex, ((Integer) aObject).intValue()); - } else if (aObject instanceof Long) { - aStatement.setLong(aIndex, ((Integer) aObject).longValue()); - } else if (aObject instanceof String) { - aStatement.setString(aIndex, (String) aObject); - } else { - TestCase.fail("Unsupported object type for prepared statement: " - + aObject.getClass() + " value: " + aObject - + " statement: " + aStatement); - } - } - - /** - * @return - * @throws SQLException - */ - public int getTableSize(final String aTable) throws Exception { - return executeInTransaction(new JdbcUnitOfWork() { - public Integer execute(Connection aConnection) throws Exception { - ResultSet resultSet = executeQuery(aConnection, - "select count(*) from " + aTable); - resultSet.next(); - return resultSet.getInt(1); - } - }); - - } - - public int countResultSet(ResultSet aResultSet) throws SQLException { - int count = 0; - - while (aResultSet.next()) { - count++; - } - - return count; - } + public static interface TableSet { + boolean contains(String aTableName); + } + + public static interface JdbcUnitOfWork { + T execute(Connection aConnection) throws Exception; + } + + public static interface TableSetOperation { + void execute(String aTable) throws Exception; + } + + private static final Logger LOG = Logger.getLogger(DatabaseUtils.class + .getName()); + + /** + * Schema pattern. + */ + private static final String SCHEMA_PATTERN = "%"; + private DataSource dataSource; + private ITableFilterSimple tables; + + public DatabaseUtils(DataSource aDataSource, ITableFilterSimple aTables) { + dataSource = aDataSource; + tables = aTables; + } + + public IDatabaseTester createDbTester() throws Exception { + return createDbTester(getTableNames(tables)); + } + + public IDatabaseTester createDbTester(String[] aTables) throws Exception { + IDatabaseTester dbtester = new DataSourceDatabaseTester(dataSource); + dbtester.setDataSet(dbtester.getConnection().createDataSet(aTables)); + return dbtester; + } + + public void cleanDatabase() throws Exception { + cleanDatabase(tables); + } + + public void executeOnTables(ITableFilterSimple aTables, + final TableSetOperation aOperation) throws Exception { + final String[] tables = getTableNames(aTables); + executeInTransaction(new JdbcUnitOfWork() { + public Void execute(Connection aConnection) throws Exception { + for (int i = tables.length-1; i >= 0; i--) { + aOperation.execute(tables[i]); + } + return null; + } + }); + } + + public void cleanDatabase(ITableFilterSimple aSelection) throws Exception { + + final String[] tables = getTableNames(aSelection); + executeInTransaction(new JdbcUnitOfWork() { + + public Void execute(Connection aConnection) throws Exception { + IDatabaseConnection connection = new DatabaseConnection( + aConnection); + ITableFilter filter = new DatabaseSequenceFilter(connection, + tables); + IDataSet dataset = new FilteredDataSet(filter, connection + .createDataSet(tables)); + DatabaseOperation.DELETE_ALL.execute(connection, dataset); + return null; + } + }); + + } + + public T executeInTransaction(JdbcUnitOfWork aCallback) + throws Exception { + Connection connection = dataSource.getConnection(); + try { + T value = aCallback.execute(connection); + connection.commit(); + return value; + } finally { + connection.close(); + } + } + + public String[] getTableNames() throws Exception { + return getTableNames(tables); + } + + /** + * @throws SQLException + */ + public String[] getTableNames(ITableFilterSimple aSelection) + throws Exception { + + List result = new ArrayList(); + LOG.fine("Getting database table names to clean (schema: '" + + SCHEMA_PATTERN + "'"); + + Connection connection = dataSource.getConnection(); + try { + ResultSet tables = connection.getMetaData().getTables(null, + SCHEMA_PATTERN, "%", new String[] { "TABLE" }); + while (tables.next()) { + String table = tables.getString("TABLE_NAME"); + if (aSelection.accept(table)) { + result.add(table); + } + } + return (String[]) result.toArray(new String[0]); + } finally { + connection.close(); + } + } + + public void emptyTables() throws Exception { + executeOnTables(tables, new TableSetOperation() { + public void execute(String aTable) throws Exception { + emptyTable(aTable); + } + }); + } + + /** + * @return + * @throws SQLException + */ + public void emptyTables(final ITableFilterSimple aSelection) + throws Exception { + executeOnTables(aSelection, new TableSetOperation() { + public void execute(String aTable) throws Exception { + emptyTable(aTable); + } + }); + } + + /** + * @return + * @throws SQLException + */ + public void emptyTable(String aTable) throws Exception { + executeSql("delete from " + aTable); + } + + public void dropTables() throws Exception { + dropTables(tables); + } + + public void dropTables(ITableFilterSimple aTables) throws Exception { + final String[] tables = getTableNames(aTables); + String[] sortedTables = executeInTransaction(new JdbcUnitOfWork() { + + public String[] execute(Connection aConnection) throws Exception { + IDatabaseConnection connection = new DatabaseConnection( + aConnection); + ITableFilter filter = new DatabaseSequenceFilter(connection, + tables); + IDataSet dataset = new FilteredDataSet(filter, connection + .createDataSet(tables)); + return dataset.getTableNames(); + } + }); + for (int i = sortedTables.length-1; i >= 0; i--) { + dropTable(sortedTables[i]); + } + } + + /** + * @return + * @throws SQLException + */ + public void dropTable(final String aTable) throws Exception { + executeInTransaction(new JdbcUnitOfWork() { + public Void execute(Connection aConnection) throws Exception { + executeUpdate(aConnection, "drop table " + aTable); + return null; + } + }); + + } + + /** + * Executes an SQL statement within a transaction. + * + * @param aSql + * SQL statement. + * @return Return code of the corresponding JDBC call. + */ + public int executeSql(final String aSql) throws Exception { + return executeSql(aSql, new Object[0]); + } + + /** + * Executes an SQL statement within a transaction. See + * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on + * supported argument types. + * + * @param aSql + * SQL statement. + * @param aArg + * Argument of the sql statement. + * @return Return code of the corresponding JDBC call. + */ + public int executeSql(final String aSql, final Object aArg) + throws Exception { + return executeSql(aSql, new Object[] { aArg }); + } + + /** + * Executes an sql statement. See + * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on + * supported argument types. + * + * @param aSql + * SQL query to execute. + * @param aArgs + * Arguments. + * @return Number of rows updated. + */ + public int executeSql(final String aSql, final Object[] aArgs) + throws Exception { + return executeInTransaction(new JdbcUnitOfWork() { + public Integer execute(Connection aConnection) throws Exception { + PreparedStatement stmt = aConnection.prepareStatement(aSql); + setPreparedParams(aArgs, stmt); + return stmt.executeUpdate(); + } + }); + } + + /** + * Executes an SQL query. + * + * @param aSql + * Query to execute. + * @return Result set. + */ + public ResultSet executeQuery(Connection aConnection, String aSql) { + return executeQuery(aConnection, aSql, new Object[0]); + } + + /** + * Executes a query with a single argument. See + * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on + * supported argument types. + * + * @param aSql + * Query. + * @param aArg + * Argument. + * @return Result set. + */ + public ResultSet executeQuery(Connection aConnection, String aSql, + Object aArg) { + return executeQuery(aConnection, aSql, new Object[] { aArg }); + } + + /** + * Executes a query. See + * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on + * supported argument types. + * + * @param aSql + * Sql query. + * @param aArgs + * Arguments to the query. + * @return Result set. + */ + public ResultSet executeQuery(Connection aConnection, final String aSql, + final Object[] aArgs) { + try { + PreparedStatement statement = aConnection.prepareStatement(aSql); + setPreparedParams(aArgs, statement); + + return statement.executeQuery(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + public int executeUpdate(Connection aConnection, final String aSql, + final Object... aArgs) { + try { + PreparedStatement statement = aConnection.prepareStatement(aSql); + setPreparedParams(aArgs, statement); + + return statement.executeUpdate(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + + /** + * Sets the values of a prepared statement. See + * {@link #setPreparedParam(int, PreparedStatement, Object)}for details on + * supported argument types. + * + * @param aArgs + * Arguments to the prepared statement. + * @param aStatement + * Prepared statement + * @throws SQLException + */ + private void setPreparedParams(final Object[] aArgs, + PreparedStatement aStatement) throws SQLException { + for (int i = 1; i <= aArgs.length; i++) { + setPreparedParam(i, aStatement, aArgs[i - 1]); + } + } + + /** + * Sets a prepared statement parameter. + * + * @param aIndex + * Index of the parameter. + * @param aStatement + * Prepared statement. + * @param aObject + * Value Must be of type Integer, Long, or String. + * @throws SQLException + */ + private void setPreparedParam(int aIndex, PreparedStatement aStatement, + Object aObject) throws SQLException { + if (aObject instanceof Integer) { + aStatement.setInt(aIndex, ((Integer) aObject).intValue()); + } else if (aObject instanceof Long) { + aStatement.setLong(aIndex, ((Long) aObject).longValue()); + } else if (aObject instanceof String) { + aStatement.setString(aIndex, (String) aObject); + } else { + TestCase.fail("Unsupported object type for prepared statement: " + + aObject.getClass() + " value: " + aObject + " statement: " + + aStatement); + } + } + + /** + * @return + * @throws SQLException + */ + public int getTableSize(final String aTable) throws Exception { + return executeInTransaction(new JdbcUnitOfWork() { + public Integer execute(Connection aConnection) throws Exception { + ResultSet resultSet = executeQuery(aConnection, + "select count(*) from " + aTable); + resultSet.next(); + return resultSet.getInt(1); + } + }); + + } + + public int countResultSet(ResultSet aResultSet) throws SQLException { + int count = 0; + + while (aResultSet.next()) { + count++; + } + + return count; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java index 646931c5..33bd4f44 100755 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 the original author or authors. + * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,267 +48,267 @@ import org.wamblee.io.FileSystemUtils; */ public class DerbyDatabase extends AbstractDatabase { - /** - * Logger. - */ - private static final Logger LOGGER = Logger.getLogger(DerbyDatabase.class - .getName()); - - /** - * Database user name. - */ - private static final String USERNAME = "sa"; - - /** - * Database password. - */ - private static final String PASSWORD = "123"; - /** - * Poll interval for the checking the server status. - */ - private static final int POLL_INTERVAL = 100; - - /** - * Maximum time to wait until the server has started or stopped. - */ - private static final int MAX_WAIT_TIME = 10000; - - /** - * Database name to use. - */ - private static final String DATABASE_NAME = "testdb"; - - /** - * Path on the file system where derby files are stored. - */ - private static final String DATABASE_PATH = "target/db/persistence/derby"; - - /** - * Derby property required to set the file system path - * {@link #DATABASE_PATH}. - */ - private static final String SYSTEM_PATH_PROPERTY = "derby.system.home"; - - - private boolean inmemory; - - - /** - * Constructs derby database class to allow creation of derby database - * instances. - */ - public DerbyDatabase() { - inmemory = true; - } - - public DerbyDatabase(boolean aInMemoryFlag) { - inmemory = aInMemoryFlag; - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.persistence.Database#start() - */ - public void doStart() { - try { - // just in case a previous run was killed without the - // cleanup - cleanPersistentStorage(); - - if (!inmemory) { - // set database path. - Properties lProperties = System.getProperties(); - lProperties.put(SYSTEM_PATH_PROPERTY, DATABASE_PATH); - } - - Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance(); - - runDatabase(); - - waitUntilStartedOrStopped(true); - - // Force creation of the database. - Connection lConnection = createConnection(); - lConnection.close(); - - LOGGER.info("Database started: \n URL = " + getExternalJdbcUrl() + "\n user = " + getUsername() + "\n password = " - + getPassword()); - - createDataSource(); - - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - if (isStarted()) { - LOGGER.warning("Shutting down db"); - DerbyDatabase.this.stop(); - } - } - }); - } catch (Exception e) { - throw new RuntimeException("Problem starting database", e); - } - } - - /** - * Waits until the database server has started or stopped. - * - * @param aStarted - * If true, waits until the server is up, if false, waits until - * the server is down. - * @throws InterruptedException - */ - private void waitUntilStartedOrStopped(boolean aStarted) - throws InterruptedException { - long lWaited = 0; - - while (aStarted != isStarted()) { - Thread.sleep(POLL_INTERVAL); - lWaited += POLL_INTERVAL; - - if (lWaited > MAX_WAIT_TIME) { - throw new RuntimeException( - "Derby database did not start within " + MAX_WAIT_TIME - + "ms"); - } - } - } - - /** - * Checks if the database server has started or not. - * - * @return True if started, false otherwise. - */ - private boolean isStarted() { - try { - getControl().ping(); - - return true; - } catch (Exception e) { - return false; - } - } - - /** - * Gets the controller for the database server. - * - * @return Controller. - * @throws Exception - */ - private NetworkServerControl getControl() throws Exception { - return new NetworkServerControl(); - } - - /** - * Runs the database. - * - */ - private void runDatabase() { - try { - getControl().start(new PrintWriter(System.out)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.persistence.Database#getJdbcUrl() - */ - public String getJdbcUrl() { - return getBaseJdbcUrl() - + ";create=true;retrieveMessagesFromServerOnGetMessage=true;"; - } - - private String getBaseJdbcUrl() { - return (inmemory ? "jdbc:derby:memory:": "jdbc:derby:") + DATABASE_NAME; - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.persistence.Database#getExternalJdbcUrl() - */ - public String getExternalJdbcUrl() { - return "jdbc:derby://localhost:1527/" + (inmemory ? "memory:" : "") + DATABASE_NAME; - } - - /** - * Shuts down the derby database and cleans up all created files. - * - */ - private void shutdownDerby() { - try { - DriverManager.getConnection("jdbc:derby:;shutdown=true"); - throw new RuntimeException("Derby did not shutdown, " - + " should always throw exception at shutdown"); - } catch (Exception e) { - LOGGER.info("Derby has been shut down."); - } - } - - /** - * Gets the user name. - */ - public String getUsername() { - return USERNAME; - } - - /** - * Gets the password. - * - * @return - */ - public String getPassword() { - return PASSWORD; - } - - /* - * (non-Javadoc) - * - * @see org.wamblee.persistence.Database#createConnection() - */ - public Connection createConnection() throws SQLException { - Connection c = DriverManager.getConnection(getJdbcUrl(), getUsername(), - getPassword()); - - return c; - } - - - /** - * Stops the derby database and cleans up all derby files. - */ - public void doStop() { - try { - // shutdown network server. - getControl().shutdown(); - waitUntilStartedOrStopped(false); - - // shutdown inmemory access. - shutdownDerby(); - cleanPersistentStorage(); - } catch (Exception e) { - LOGGER.log(Level.WARNING, "Problem stopping database", e); - } - } - - /** - * Cleans up persistent storage of Derby. - */ - private void cleanPersistentStorage() { - File lFile = new File(DATABASE_PATH); - - if (lFile.isFile()) { - TestCase.fail("A regular file by the name " + DATABASE_PATH - + " exists, clean this up first"); - } - - if (!lFile.isDirectory()) { - return; // no-op already cleanup up. - } - FileSystemUtils.deleteDirRecursively(DATABASE_PATH); - } + /** + * Logger. + */ + private static final Logger LOGGER = Logger.getLogger(DerbyDatabase.class + .getName()); + + /** + * Database user name. + */ + private static final String USERNAME = "sa"; + + /** + * Database password. + */ + private static final String PASSWORD = "123"; + /** + * Poll interval for the checking the server status. + */ + private static final int POLL_INTERVAL = 100; + + /** + * Maximum time to wait until the server has started or stopped. + */ + private static final int MAX_WAIT_TIME = 10000; + + /** + * Database name to use. + */ + private static final String DATABASE_NAME = "testdb"; + + /** + * Path on the file system where derby files are stored. + */ + private static final String DATABASE_PATH = "target/db/persistence/derby"; + + /** + * Derby property required to set the file system path + * {@link #DATABASE_PATH}. + */ + private static final String SYSTEM_PATH_PROPERTY = "derby.system.home"; + + private boolean inmemory; + + /** + * Constructs derby database class to allow creation of derby database + * instances. + */ + public DerbyDatabase() { + inmemory = true; + } + + public DerbyDatabase(boolean aInMemoryFlag) { + inmemory = aInMemoryFlag; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.persistence.Database#start() + */ + public void doStart() { + try { + // just in case a previous run was killed without the + // cleanup + cleanPersistentStorage(); + + if (!inmemory) { + // set database path. + Properties lProperties = System.getProperties(); + lProperties.put(SYSTEM_PATH_PROPERTY, DATABASE_PATH); + } + + Class.forName("org.apache.derby.jdbc.EmbeddedDriver").newInstance(); + + runDatabase(); + + waitUntilStartedOrStopped(true); + + // Force creation of the database. + Connection lConnection = createConnection(); + lConnection.close(); + + LOGGER.info("Database started: \n URL = " + + getExternalJdbcUrl() + "\n user = " + getUsername() + + "\n password = " + getPassword()); + + createDataSource(); + + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + if (isStarted()) { + LOGGER.warning("Shutting down db"); + DerbyDatabase.this.stop(); + } + } + }); + } catch (Exception e) { + throw new RuntimeException("Problem starting database", e); + } + } + + /** + * Waits until the database server has started or stopped. + * + * @param aStarted + * If true, waits until the server is up, if false, waits until + * the server is down. + * @throws InterruptedException + */ + private void waitUntilStartedOrStopped(boolean aStarted) + throws InterruptedException { + long lWaited = 0; + + while (aStarted != isStarted()) { + Thread.sleep(POLL_INTERVAL); + lWaited += POLL_INTERVAL; + + if (lWaited > MAX_WAIT_TIME) { + throw new RuntimeException( + "Derby database did not start within " + MAX_WAIT_TIME + + "ms"); + } + } + } + + /** + * Checks if the database server has started or not. + * + * @return True if started, false otherwise. + */ + private boolean isStarted() { + try { + getControl().ping(); + + return true; + } catch (Exception e) { + return false; + } + } + + /** + * Gets the controller for the database server. + * + * @return Controller. + * @throws Exception + */ + private NetworkServerControl getControl() throws Exception { + return new NetworkServerControl(); + } + + /** + * Runs the database. + * + */ + private void runDatabase() { + try { + getControl().start(new PrintWriter(System.out)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.persistence.Database#getJdbcUrl() + */ + public String getJdbcUrl() { + return getBaseJdbcUrl() + + ";create=true;retrieveMessagesFromServerOnGetMessage=true;"; + } + + private String getBaseJdbcUrl() { + return (inmemory ? "jdbc:derby:memory:" : "jdbc:derby:") + + DATABASE_NAME; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.persistence.Database#getExternalJdbcUrl() + */ + public String getExternalJdbcUrl() { + return "jdbc:derby://localhost:1527/" + (inmemory ? "memory:" : "") + + DATABASE_NAME; + } + + /** + * Shuts down the derby database and cleans up all created files. + * + */ + private void shutdownDerby() { + try { + DriverManager.getConnection("jdbc:derby:;shutdown=true"); + throw new RuntimeException( + "Derby did not shutdown, should always throw exception at shutdown"); + } catch (Exception e) { + LOGGER.info("Derby has been shut down."); + } + } + + /** + * Gets the user name. + */ + public String getUsername() { + return USERNAME; + } + + /** + * Gets the password. + * + * @return + */ + public String getPassword() { + return PASSWORD; + } + + /* + * (non-Javadoc) + * + * @see org.wamblee.persistence.Database#createConnection() + */ + public Connection createConnection() throws SQLException { + Connection c = DriverManager.getConnection(getJdbcUrl(), getUsername(), + getPassword()); + + return c; + } + + /** + * Stops the derby database and cleans up all derby files. + */ + public void doStop() { + try { + // shutdown network server. + getControl().shutdown(); + waitUntilStartedOrStopped(false); + + // shutdown inmemory access. + shutdownDerby(); + cleanPersistentStorage(); + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Problem stopping database", e); + } + } + + /** + * Cleans up persistent storage of Derby. + */ + private void cleanPersistentStorage() { + File lFile = new File(DATABASE_PATH); + + if (lFile.isFile()) { + TestCase.fail("A regular file by the name " + DATABASE_PATH + + " exists, clean this up first"); + } + + if (!lFile.isDirectory()) { + return; // no-op already cleanup up. + } + FileSystemUtils.deleteDirRecursively(DATABASE_PATH); + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java index 088202c3..183a73db 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/DerbyDatabaseProvider.java @@ -1,32 +1,53 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.Arrays; import java.util.List; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DerbyDatabaseProvider extends AbstractDatabaseProvider { - - /** - * Capabilities of this type of database. - */ - public static final List CAPABILIITIES = - Arrays.asList(DatabaseProvider.CAPABILITY_IN_MEMORY, "DERBY"); + /** + * Capabilities of this type of database. + */ + public static final List CAPABILIITIES = Arrays.asList( + DatabaseProvider.CAPABILITY_IN_MEMORY, "DERBY"); + /** + * Creates a new DerbyDatabaseProvider object. + */ + public DerbyDatabaseProvider() { + // Empty + } - public DerbyDatabaseProvider() { - // Empty - } - - public Database create() { - return new DerbyDatabase(); - } + public Database create() { + return new DerbyDatabase(); + } - public DatabaseDescription getDescription() { - return new DatabaseDescription(CAPABILIITIES.toArray(new String[0]), - "Derby", "In-memory, volatile, set breakpoint to debug"); - } + public DatabaseDescription getDescription() { + return new DatabaseDescription(CAPABILIITIES.toArray(new String[0]), + "Derby", "In-memory, volatile, set breakpoint to debug"); + } @Override protected List getCapabilities() { - return CAPABILIITIES; + return CAPABILIITIES; } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java index 2533df42..32e469ea 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabase.java @@ -1,82 +1,90 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; -import java.util.Arrays; -import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; -import org.apache.commons.dbcp.ConnectionFactory; -import org.apache.commons.dbcp.DriverManagerConnectionFactory; -import org.apache.commons.dbcp.PoolableConnectionFactory; -import org.apache.commons.dbcp.PoolingDataSource; -import org.apache.commons.pool.impl.GenericObjectPool; - /** - * Database that encapsulates connection to an external database. - * Database connection details can be configured through system properties - * and environment variables, see {@link #DB_URL_PROP}, {@link #DB_USER_PROP}, and - * {@link #DB_PASSWORD_PROP|. + * Database that encapsulates connection to an external database. Database + * connection details can be configured through system properties and + * environment variables, see {@link #DB_URL_PROP}, {@link #DB_USER_PROP}, and + * {@link #DB_PASSWORD_PROP|. * - * This class assumes modern database drivers that work together with java.util.ServiceLoader - * so that explicitly doing a Class.forName() is not necessary to load the database driver. + * This class assumes modern database drivers that work together with + * java.util.ServiceLoader so that explicitly doing a Class.forName() is not + * necessary to load the database driver. */ public class ExternalDatabase extends AbstractDatabase { - - private static final Logger LOGGER = Logger.getLogger(ExternalDatabase.class.getName()); - - /** - * System property/environment variable that defines the database URL. - */ - public static final String DB_URL_PROP = "TEST_DB_URL"; - - /** - * System property/environment variable that defines the database user. - */ - public static final String DB_USER_PROP = "TEST_DB_USER"; - - /** - * System property/environment variable that defines the database password. - */ - public static final String DB_PASSWORD_PROP = "TEST_DB_PASSWORD"; - - - private String itsUrl; - private String itsUser; - private String itsPassword; - - private DataSource itsDataSource; - - public ExternalDatabase() { - // Empty - } - - public String getExternalJdbcUrl() { - return itsUrl; - } - - public String getJdbcUrl() { - return itsUrl; - } - - public String getPassword() { - return itsPassword; - } - - public String getUsername() { - return itsUser; - } - - public void doStart() { - itsUrl = getProperty(DB_URL_PROP); - itsUser = getProperty(DB_USER_PROP); - itsPassword = getProperty(DB_PASSWORD_PROP); - - createDataSource(); - } - - public void doStop() { - // Empty. - } + + private static final Logger LOGGER = Logger + .getLogger(ExternalDatabase.class.getName()); + + /** + * System property/environment variable that defines the database URL. + */ + public static final String DB_URL_PROP = "TEST_DB_URL"; + + /** + * System property/environment variable that defines the database user. + */ + public static final String DB_USER_PROP = "TEST_DB_USER"; + + /** + * System property/environment variable that defines the database password. + */ + public static final String DB_PASSWORD_PROP = "TEST_DB_PASSWORD"; + + private String itsUrl; + private String itsUser; + private String itsPassword; + + private DataSource itsDataSource; + + public ExternalDatabase() { + // Empty + } + + public String getExternalJdbcUrl() { + return itsUrl; + } + + public String getJdbcUrl() { + return itsUrl; + } + + public String getPassword() { + return itsPassword; + } + + public String getUsername() { + return itsUser; + } + + public void doStart() { + itsUrl = getProperty(DB_URL_PROP); + itsUser = getProperty(DB_USER_PROP); + itsPassword = getProperty(DB_PASSWORD_PROP); + + createDataSource(); + } + + public void doStop() { + // Empty. + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java index 871be11a..9c131bfb 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/ExternalDatabaseProvider.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.Arrays; @@ -5,31 +20,31 @@ import java.util.List; public class ExternalDatabaseProvider extends AbstractDatabaseProvider { - /** - * Capabilities of this type of database. - */ - public static final List CAPABILIITIES = Arrays - .asList(CAPABILITY_EXTERNAL); + /** + * Capabilities of this type of database. + */ + public static final List CAPABILIITIES = Arrays + .asList(CAPABILITY_EXTERNAL); - @Override - protected List getCapabilities() { - return CAPABILIITIES; - } + @Override + protected List getCapabilities() { + return CAPABILIITIES; + } - public Database create() { - return new ExternalDatabase(); - } + public Database create() { + return new ExternalDatabase(); + } - public DatabaseDescription getDescription() { - return new DatabaseDescription( - CAPABILIITIES.toArray(new String[0]), - "External Database", - "Any database as described by the JDBC URL: requires system properties or environment variables: " - + ExternalDatabase.DB_URL_PROP - + ", " - + ExternalDatabase.DB_USER_PROP - + ", and " - + ExternalDatabase.DB_PASSWORD_PROP); - } + public DatabaseDescription getDescription() { + return new DatabaseDescription( + CAPABILIITIES.toArray(new String[0]), + "External Database", + "Any database as described by the JDBC URL: requires system properties or environment variables: " + + ExternalDatabase.DB_URL_PROP + + ", " + + ExternalDatabase.DB_USER_PROP + + ", and " + + ExternalDatabase.DB_PASSWORD_PROP); + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java index 8b6e3399..4d1921f5 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.Map; @@ -15,7 +30,6 @@ import javax.sql.DataSource; import org.wamblee.support.jndi.StubInitialContextFactory; - /** * Utility for building an appropriately configured EntityManagerFactory. The * idea is that a persistence.xml is used unchanged from the production version. @@ -27,110 +41,118 @@ import org.wamblee.support.jndi.StubInitialContextFactory; */ public class JpaBuilder { - private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class - .getName()); + private static final Logger LOGGER = Logger.getLogger(JpaBuilder.class + .getName()); + + /** + * Callback interface to execute some JPA code within a transaction with the + * entitymanager to use provided as input. + */ + public static interface JpaUnitOfWork { + /** + * Executes the unit of work. A transaction has been started. + * + * @param aEm + * Entity manager. + * @return Result of the execute method. If you don't want to return + * anything use Void for the return type and return + * null from the implementation. + */ + T execute(EntityManager aEm) throws Exception; + } + + private PersistenceUnitDescription persistenceUnit; + private DataSource dataSource; + private EntityManagerFactory factory; + + /** + * Constructs the builder. + * + * @param aDataSource + * Datasource of database. + * @param aPersistenceUnit + * Persistence unit. + */ + public JpaBuilder(DataSource aDataSource, + PersistenceUnitDescription aPersistenceUnit) { + persistenceUnit = aPersistenceUnit; + dataSource = aDataSource; + StubInitialContextFactory.register(); + } - /** - * Callback interface to execute some JPA code within a transaction with the - * entitymanager to use provided as input. - */ - public static interface JpaUnitOfWork { - /** - * Executes the unit of work. A transaction has been started. - * @param em Entity manager. - * @return Result of the execute method. If you don't want to return anything use - * Void for the return type and return null from the implementation. - */ - T execute(EntityManager em); - } + /** + * Starts the builder, which in particular, mocks JNDI, binds the datasource + * the JNDI where the persistence unit expects it, creates the entity + * manager factory, and forces creation of the database schema. + */ + public void start() throws Exception { + try { + InitialContext ctx = new InitialContext(); + ctx.bind(persistenceUnit.getJndiName(), dataSource); + } catch (NamingException e) { + throw new RuntimeException("JNDI problem", e); + } + factory = createFactory(); + execute(new JpaUnitOfWork() { + public Void execute(EntityManager aEm) { + // Empty, just to trigger database schema creation. + return null; + } + }); + } - private PersistenceUnitDescription persistenceUnit; - private DataSource dataSource; - private EntityManagerFactory factory; + /** + * Stops the entity manager factory and disables JNDI mocking. + */ + public void stop() { + StubInitialContextFactory.unregister(); + factory.close(); + } - /** - * Constructs the builder. - * - * @param aDataSource - * Datasource of database. - * @param aPersistenceUnit - * Persistence unit. - */ - public JpaBuilder(DataSource aDataSource, - PersistenceUnitDescription aPersistenceUnit) { - persistenceUnit = aPersistenceUnit; - dataSource = aDataSource; - StubInitialContextFactory.register(); - } + /** + * Creates a new entity manager factory. Typically not used by test code. + * + * @return Entity manager factory. + */ + public EntityManagerFactory createFactory() { + Map jpaProps = new TreeMap(); - /** - * Starts the builder, which in particular, mocks JNDI, binds the datasource - * the JNDI where the persistence unit expects it, creates the entity - * manager factory, and forces creation of the database schema. - */ - public void start() throws Exception { - try { - InitialContext ctx = new InitialContext(); - ctx.bind(persistenceUnit.getJndiName(), dataSource); - } catch (NamingException e) { - throw new RuntimeException("JNDI problem", e); - } - factory = createFactory(); - execute(new JpaUnitOfWork() { - public Void execute(EntityManager em) { - // Empty, just to trigger database schema creation. - return null; - } - }); - } + JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit, + jpaProps); - /** - * Stops the entity manager factory and disables JNDI mocking. - */ - public void stop() { - StubInitialContextFactory.unregister(); - factory.close(); - } + // jpaProps.put("javax.persistence.provider", + // HibernatePersistence.class.getName()); + EntityManagerFactory factory = Persistence.createEntityManagerFactory( + persistenceUnit.getUnitName(), jpaProps); - /** - * Creates a new entity manager factory. Typically not used by test code. - * @return Entity manager factory. - */ - public EntityManagerFactory createFactory() { - Map jpaProps = new TreeMap(); - - JpaCustomizerBuilder.getCustomizer().customize(persistenceUnit, jpaProps); - - //jpaProps.put("javax.persistence.provider", HibernatePersistence.class.getName()); - EntityManagerFactory factory = Persistence.createEntityManagerFactory(persistenceUnit - .getUnitName(), jpaProps); - - LOGGER.info("Using " + factory.getClass()); - return factory; - } + LOGGER.info("Using " + factory.getClass()); + return factory; + } - /** - * Executes a unit of work. This creates an entitymanager and runs the - * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction, passing - * it the entity manager. Use of this method saves a lot of typing for applications. - * - * @param aWork Work to execute. - * @return The return value of the execute method of the unit of work. - */ - public T execute(JpaUnitOfWork aWork) throws Exception { - EntityManager em = factory.createEntityManager(); - EntityTransaction transaction = em.getTransaction(); - transaction.begin(); - try { - T value = aWork.execute(em); - transaction.commit(); - return value; - } catch (Exception e) { - LOGGER.log(Level.WARNING, "Exception occured", e); - transaction.rollback(); - throw e; - } finally { - em.close(); - } - } + /** + * Executes a unit of work. This creates an entitymanager and runs the + * {@link JpaUnitOfWork#execute(EntityManager)} within a transaction, + * passing it the entity manager. Use of this method saves a lot of typing + * for applications. + * + * @param aWork + * Work to execute. + * @return The return value of the execute method of the unit of work. + */ + public T execute(JpaUnitOfWork aWork) throws Exception { + EntityManager em = factory.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + try { + T value = aWork.execute(em); + transaction.commit(); + return value; + } catch (Exception e) { + LOGGER.log(Level.WARNING, "Exception occured", e); + transaction.rollback(); + throw e; + } finally { + em.close(); + } + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java index 79303012..7c48cb24 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizer.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.Map; @@ -6,17 +21,19 @@ import java.util.ServiceLoader; import org.dbunit.dataset.filter.ITableFilterSimple; /** - * JPA customizer is used to customize properties for a given JPA implementation. + * JPA customizer is used to customize properties for a given JPA + * implementation. * - * Implementations of JpaCustomizer are found using {@link ServiceLoader}. In case - * of testing with a specific JPA provider, the customizer library for that JPA provider - * must be on the classpath as well. + * Implementations of JpaCustomizer are found using {@link ServiceLoader}. In + * case of testing with a specific JPA provider, the customizer library for that + * JPA provider must be on the classpath as well. * * @author Erik Brakkee */ public interface JpaCustomizer { - void customize(PersistenceUnitDescription aPersistenceUnit, Map aJpaProperties); - + void customize(PersistenceUnitDescription aPersistenceUnit, + Map aJpaProperties); + ITableFilterSimple getJpaTables(); } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java index a824bf6f..1f1884fe 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaCustomizerBuilder.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.util.ArrayList; @@ -6,13 +21,12 @@ import java.util.ServiceLoader; public class JpaCustomizerBuilder { - private static final ServiceLoader CUSTOMIZERS = - ServiceLoader.load(JpaCustomizer.class); - - - public static JpaCustomizer getCustomizer() { - List customizers = new ArrayList(); - for (JpaCustomizer customizer: CUSTOMIZERS) { + private static final ServiceLoader CUSTOMIZERS = ServiceLoader + .load(JpaCustomizer.class); + + public static JpaCustomizer getCustomizer() { + List customizers = new ArrayList(); + for (JpaCustomizer customizer : CUSTOMIZERS) { customizers.add(customizer); } return new CompositeJpaCustomizer(customizers); diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java index a6a512f1..52e284ee 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/JpaTester.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import javax.sql.DataSource; @@ -5,109 +20,114 @@ import javax.sql.DataSource; import org.dbunit.IDatabaseTester; /** - * This class is the entry point for JPA tests. Test code should construct a JpaTester in the - * @Before method and call {@link #start()} on it in that method. Also, test code should - * call {@link #stop()} on it in the @After method. + * This class is the entry point for JPA tests. Test code should construct a + * JpaTester in the @Before method and call {@link #start()} on it + * in that method. Also, test code should call {@link #stop()} on it in the + * @After method. + * + * This class is constructed with a description of the persistence unit to be + * tested. The principle is that an existing persistence.xml can be + * tested without change in unit test code. * - * This class is constructed with a description of the persistence unit to be tested. The principle is that - * an existing persistence.xml can be tested without change in unit test code. - * - * It then takes care of the following: - *
    - *
  • Creating an inmemory database for testing (default) or connecting to an external database. - * See {@link DatabaseBuilder} for more information on how a databse is obtained. - *
  • - *
  • Drop all database tables that are related to the persistence unit under test, including JPA provider - * specific tables. - *
  • - *
  • Creating a datasource for the database and make the datasource available through JNDI. - *
  • - *
  • Creating the entity manager factory for JPA and configuring it in such a way that schema creation - * happens. (Typically, schema creation will be disabled in the persistence.xml but this utility enables it - * for unit test). - *
  • - *
  • Creating a DBUnit database tester which is appropriately configured for the persistence unit under test. - *
  • + * It then takes care of the following: + *
      + *
    • Creating an inmemory database for testing (default) or connecting to an + * external database. See {@link DatabaseBuilder} for more information on how a + * databse is obtained.
    • + *
    • Drop all database tables that are related to the persistence unit under + * test, including JPA provider specific tables.
    • + *
    • Creating a datasource for the database and make the datasource available + * through JNDI.
    • + *
    • Creating the entity manager factory for JPA and configuring it in such a + * way that schema creation happens. (Typically, schema creation will be + * disabled in the persistence.xml but this utility enables it for unit test).
    • + *
    • Creating a DBUnit database tester which is appropriately configured for + * the persistence unit under test.
    • *
    * - * The main entry point for all this functionality is the {@link PersistenceUnitDescription} which describes the - * persistence unit and must be provided at construction of the JpaTester + * The main entry point for all this functionality is the + * {@link PersistenceUnitDescription} which describes the persistence unit and + * must be provided at construction of the JpaTester * - * NOTE: Persistence XML files should be explicitly configured with the classes that are part of the persistence unit - * since scanning of classes does not work correctly in a unit test environment. This is currently the only limitation. + * NOTE: Persistence XML files should be explicitly configured with the classes + * that are part of the persistence unit since scanning of classes does not work + * correctly in a unit test environment. This is currently the only limitation. */ public class JpaTester { - private PersistenceUnitDescription persistenceUnit; - private Database db; - private DataSource dataSource; - private DatabaseUtils dbUtils; - private JpaBuilder jpaBuilder; - private IDatabaseTester dbTester; - - /** - * Constructs the tester. - * @param aPersistenceUnit Persistence unit under test. - */ - public JpaTester(PersistenceUnitDescription aPersistenceUnit) { - persistenceUnit = aPersistenceUnit; - } - - /** - * Starts the tester. This must be called prior to running the test. - * @throws Exception - */ - public void start() throws Exception { - db = DatabaseBuilder.getDatabase(); - dataSource = db.start(); - - dbUtils = new DatabaseUtils(dataSource, persistenceUnit.getTables()); - dbUtils.dropTables(); - dbUtils.dropTables(JpaCustomizerBuilder.getCustomizer().getJpaTables()); - - jpaBuilder = new JpaBuilder(dataSource, persistenceUnit); - jpaBuilder.start(); - - // db tester should be created after Jpa builder because jpa builder - // creates the - // tables that the tester looks at when it is initialized. - dbTester = dbUtils.createDbTester(); - } - - /** - * Stops the tester. This must be called after the test. - */ - public void stop() { - if (jpaBuilder != null) { - jpaBuilder.stop(); - } - if (db != null) { - db.stop(); - } - } - - public Database getDb() { - return db; - } - - public DataSource getDataSource() { - return dataSource; - } - - public IDatabaseTester getDbTester() { - return dbTester; - } - - public DatabaseUtils getDbUtils() { - return dbUtils; - } - - public JpaBuilder getJpaBuilder() { - return jpaBuilder; - } - - public PersistenceUnitDescription getPersistenceUnit() { - return persistenceUnit; - } + private PersistenceUnitDescription persistenceUnit; + private Database db; + private DataSource dataSource; + private DatabaseUtils dbUtils; + private JpaBuilder jpaBuilder; + private IDatabaseTester dbTester; + + /** + * Constructs the tester. + * + * @param aPersistenceUnit + * Persistence unit under test. + */ + public JpaTester(PersistenceUnitDescription aPersistenceUnit) { + persistenceUnit = aPersistenceUnit; + } + + /** + * Starts the tester. This must be called prior to running the test. + * + * @throws Exception + */ + public void start() throws Exception { + db = DatabaseBuilder.getDatabase(); + dataSource = db.start(); + + dbUtils = new DatabaseUtils(dataSource, persistenceUnit.getTables()); + dbUtils.dropTables(); + dbUtils.dropTables(JpaCustomizerBuilder.getCustomizer().getJpaTables()); + + jpaBuilder = new JpaBuilder(dataSource, persistenceUnit); + jpaBuilder.start(); + + // db tester should be created after Jpa builder because jpa builder + // creates the + // tables that the tester looks at when it is initialized. + dbTester = dbUtils.createDbTester(); + } + + /** + * Stops the tester. This must be called after the test. + */ + public void stop() { + if (jpaBuilder != null) { + jpaBuilder.stop(); + } + if (db != null) { + db.stop(); + } + } + + public Database getDb() { + return db; + } + + public DataSource getDataSource() { + return dataSource; + } + + public IDatabaseTester getDbTester() { + return dbTester; + } + + public DatabaseUtils getDbUtils() { + return dbUtils; + } + + public JpaBuilder getJpaBuilder() { + return jpaBuilder; + } + + public PersistenceUnitDescription getPersistenceUnit() { + return persistenceUnit; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java index a2499b47..b6dc28bb 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/PersistenceUnitDescription.java @@ -1,28 +1,44 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import org.dbunit.dataset.filter.ITableFilterSimple; public class PersistenceUnitDescription { - private String jndiName; - private String unitName; - private ITableFilterSimple tables; - - public PersistenceUnitDescription(String aJndiName, String aUnitName, ITableFilterSimple aTables) { - jndiName = aJndiName; - unitName = aUnitName; - tables = aTables; - } - - public String getJndiName() { - return jndiName; - } - - public String getUnitName() { - return unitName; - } - - public ITableFilterSimple getTables() { - return tables; - } + private String jndiName; + private String unitName; + private ITableFilterSimple tables; + + public PersistenceUnitDescription(String aJndiName, String aUnitName, + ITableFilterSimple aTables) { + jndiName = aJndiName; + unitName = aUnitName; + tables = aTables; + } + + public String getJndiName() { + return jndiName; + } + + public String getUnitName() { + return unitName; + } + + public ITableFilterSimple getTables() { + return tables; + } } diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java new file mode 100644 index 00000000..e56d34fa --- /dev/null +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/TransactionProxyFactory.java @@ -0,0 +1,113 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import javax.persistence.EntityManager; + +import org.wamblee.support.ThreadSpecificProxyFactory; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; + +/** + * This utility makes sure that each invocation on a certain interface is + * carried out within a JPA unit of work. + * + * Use {@link #getTransactionScopedEntityManager()} to get the transaction + * scoped entity manager to pass to services. + * + * @param T + * Type of interface to proxy. + * + * @author Erik Brakkee + */ +public class TransactionProxyFactory { + + private class UnitOfWorkInvocationHandler implements InvocationHandler { + + private T service; + + public UnitOfWorkInvocationHandler(T aService) { + service = aService; + } + + @Override + public Object invoke(Object aProxy, final Method aMethod, + final Object[] aArgs) throws Throwable { + return TransactionProxyFactory.this.jpaBuilder + .execute(new JpaUnitOfWork() { + @Override + public Object execute(EntityManager aEm) throws Exception { + try { + ENTITY_MANAGER.set(aEm); + return aMethod.invoke(service, aArgs); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof Exception) { + throw (Exception) cause; + } else if (cause instanceof Error) { + throw (Error) cause; + } + // last resort. + throw new RuntimeException(e); + } finally { + ENTITY_MANAGER.set(null); + } + } + }); + } + + } + + private static final ThreadSpecificProxyFactory ENTITY_MANAGER = new ThreadSpecificProxyFactory( + EntityManager.class); + + private JpaBuilder jpaBuilder; + private Class clazz; + + /** + * Constructs the transaction proxy. + * + * @param aJpaBuilder + */ + public TransactionProxyFactory(JpaBuilder aJpaBuilder, Class aClass) { + jpaBuilder = aJpaBuilder; + clazz = aClass; + } + + public EntityManager getTransactionScopedEntityManager() { + return ENTITY_MANAGER.getProxy(); + } + + public T getProxy(T aService) { + InvocationHandler handler = new UnitOfWorkInvocationHandler(aService); + Class proxyClass = Proxy.getProxyClass(clazz.getClassLoader(), + new Class[] { clazz }); + T proxy; + try { + proxy = (T) proxyClass.getConstructor( + new Class[] { InvocationHandler.class }).newInstance( + new Object[] { handler }); + return proxy; + } catch (Exception e) { + throw new RuntimeException("Could not create proxy for " + + clazz.getName(), e); + } + } +} diff --git a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java index 1bd7050c..e30b0b32 100644 --- a/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java +++ b/test/enterprise/src/main/java/org/wamblee/support/persistence/package-info.java @@ -1,23 +1,17 @@ -/** - * This package provide a number of utilities for database testing and in particular with - * JPA. +/* + * Copyright 2005-2010 the original author or authors. * - * The following utilities are available: - *
      - *
    • {@link JpaTester}: The main entry point for all JPA tests. - *
    • - *
    • {@link JpaBuilder}: A utility constructed by JpaTester that provides a callback based - * style of working with transaction-scoped entity managers. - *
    • - *
    • {@link DatabaseUtils}: A utility constructed by JpaTester for working with databases in general. Test code will not use this - * utility often. - *
    • - *
    • {@link org.dbunit.IDatabaseTester}: A DB unit database tester. The test code can use this database tester. - * It is also created by JpaTester - *
    • - *
    • {@link DatabaseBuilder}: A utility by which test code can transparently create an inmemory database or - * connect to an external database. This is also used by JpaTester - *
    • - *
    - */ + * 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.wamblee.support.persistence; + diff --git a/test/enterprise/src/test/java/org/wamblee/support/ThreadSpecificProxyFactoryTest.java b/test/enterprise/src/test/java/org/wamblee/support/ThreadSpecificProxyFactoryTest.java new file mode 100644 index 00000000..0e9dbe48 --- /dev/null +++ b/test/enterprise/src/test/java/org/wamblee/support/ThreadSpecificProxyFactoryTest.java @@ -0,0 +1,106 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support; + +import static junit.framework.Assert.*; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ThreadSpecificProxyFactoryTest { + + private static interface Service { + int execute(int aX) throws Exception; + } + + private ThreadSpecificProxyFactory factory; + private Service proxy; + + @Before + public void setUp() { + factory = new ThreadSpecificProxyFactory(Service.class); + proxy = factory.getProxy(); + } + + @After + public void tearDown() { + // Empty. + } + + @Test(expected = NullPointerException.class) + public void testNoSvcDefined() throws Exception { + proxy.execute(10); + } + + @Test + public void testInvokeThroughProxy() throws Exception { + Service svc = mock(Service.class); + when(svc.execute(anyInt())).thenReturn(50); + factory.set(svc); + assertEquals(50, proxy.execute(10)); + verify(svc).execute(10); + } + + @Test + public void testInvokeThroughProxyWithException() throws Exception { + Service svc = mock(Service.class); + try { + when(svc.execute(anyInt())).thenThrow( + new RuntimeException("exception thrown")); + factory.set(svc); + svc.execute(10); + fail(); + } catch (RuntimeException e) { + assertEquals("exception thrown", e.getMessage()); + } + } + + private int returnFromThread; + + @Test + public void testVerifyThreadSpecificUsingTwoThreads() throws Exception { + Service svc1 = mock(Service.class); + final Service svc2 = mock(Service.class); + when(svc1.execute(anyInt())).thenReturn(10); + when(svc2.execute(anyInt())).thenReturn(20); + + factory.set(svc1); + assertEquals(10, svc1.execute(10)); + Thread t = new Thread() { + public void run() { + factory.set(svc2); + try { + returnFromThread = proxy.execute(100); + } catch (Exception e) { + returnFromThread = 100000; + } + }; + }; + t.start(); + t.join(); + assertEquals(20, returnFromThread); + assertEquals(10, proxy.execute(100)); + + } + + @Test(expected = IllegalArgumentException.class) + public void testNotAnInterface() { + ThreadSpecificProxyFactory f = new ThreadSpecificProxyFactory(String.class); + } +} diff --git a/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java b/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java index 6016e2b3..b4745bd1 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java +++ b/test/enterprise/src/test/java/org/wamblee/support/jndi/StubInitiaContextFactoryTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.jndi; import static junit.framework.Assert.assertEquals; @@ -12,30 +27,29 @@ import org.wamblee.support.jndi.StubInitialContextFactory; public class StubInitiaContextFactoryTest { - @Before - @After - public void setUp() { - StubInitialContextFactory.unregister(); - } - - - @Test(expected = NamingException.class) - public void testLookupNotRegistered() throws Exception { - InitialContext ctx = new InitialContext(); - ctx.bind("a/b", "hallo"); - } - - @Test - public void testLookup() throws Exception { - StubInitialContextFactory.register(); - - InitialContext ctx = new InitialContext(); - ctx.bind("a/b", "hallo"); - - ctx = new InitialContext(); - Object obj = ctx.lookup("a/b"); - - assertEquals("hallo", obj); - } - + @Before + @After + public void setUp() { + StubInitialContextFactory.unregister(); + } + + @Test(expected = NamingException.class) + public void testLookupNotRegistered() throws Exception { + InitialContext ctx = new InitialContext(); + ctx.bind("a/b", "hallo"); + } + + @Test + public void testLookup() throws Exception { + StubInitialContextFactory.register(); + + InitialContext ctx = new InitialContext(); + ctx.bind("a/b", "hallo"); + + ctx = new InitialContext(); + Object obj = ctx.lookup("a/b"); + + assertEquals("hallo", obj); + } + } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java index 51364876..044b73a9 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseBuilderTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import org.junit.Test; @@ -6,11 +21,11 @@ import org.wamblee.support.persistence.DatabaseDescription; public class DatabaseBuilderTest { - - @Test - public void testListAvailableDatabases() { - for (DatabaseDescription description: DatabaseBuilder.getSupportedDatabases()) { - System.out.println(description); - } - } + @Test + public void testListAvailableDatabases() { + for (DatabaseDescription description : DatabaseBuilder + .getSupportedDatabases()) { + System.out.println(description); + } + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java index e55f1341..9012dbd5 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DatabaseUtilsTestBase.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import static junit.framework.Assert.assertEquals; @@ -38,7 +53,7 @@ public class DatabaseUtilsTestBase { builder = new JpaBuilder(dataSource, persistenceUnit); builder.start(); - + dbtester = dbutils.createDbTester(); } @@ -63,9 +78,9 @@ public class DatabaseUtilsTestBase { // Put some data in the database. builder.execute(new JpaUnitOfWork() { - public Void execute(EntityManager em) { + public Void execute(EntityManager aEm) { MyEntity entity = new MyEntity("a", "b"); - em.persist(entity); + aEm.persist(entity); return null; } }); diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java index ffc17aea..85a581ee 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/DerbyDatabaseTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.sql.Connection; @@ -10,38 +25,38 @@ import org.junit.Test; import org.wamblee.support.persistence.Database; import org.wamblee.support.persistence.DatabaseBuilder; - public class DerbyDatabaseTest { - private Database db; - private DataSource ds; - - @Before - public void setUp() { - db = DatabaseBuilder.getDatabase(); - ds = db.start(); - } - - @After - public void tearDown() { - db.stop(); - } - - @Test - public void testConnect() throws Exception { - Connection conn = ds.getConnection(); - try { - System.out.println("Database name: " + conn.getMetaData().getDatabaseProductName()); - } finally { - conn.close(); - } - } - - @Test - public void testUseASecondTimeInTheSameTestCase() throws Exception { - testConnect(); - tearDown(); - setUp(); - testConnect(); - } + private Database db; + private DataSource ds; + + @Before + public void setUp() { + db = DatabaseBuilder.getDatabase(); + ds = db.start(); + } + + @After + public void tearDown() { + db.stop(); + } + + @Test + public void testConnect() throws Exception { + Connection conn = ds.getConnection(); + try { + System.out.println("Database name: " + + conn.getMetaData().getDatabaseProductName()); + } finally { + conn.close(); + } + } + + @Test + public void testUseASecondTimeInTheSameTestCase() throws Exception { + testConnect(); + tearDown(); + setUp(); + testConnect(); + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java index dbe5800b..ca91e87f 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/ExternalDatabaseTest.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import java.sql.Connection; @@ -14,40 +29,40 @@ import static junit.framework.TestCase.*; public class ExternalDatabaseTest { - @Test - public void testExternalDB() throws Exception { - // Connect to inmemory db using External database class. - - Database inmemory = DatabaseBuilder - .getDatabase(DatabaseProvider.CAPABILITY_IN_MEMORY); - try { - inmemory.start(); - - System.setProperty(ExternalDatabase.DB_URL_PROP, inmemory - .getExternalJdbcUrl()); - System.setProperty(ExternalDatabase.DB_USER_PROP, inmemory - .getUsername()); - System.setProperty(ExternalDatabase.DB_PASSWORD_PROP, inmemory - .getPassword()); - - Database external = DatabaseBuilder - .getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); - assertTrue(external instanceof ExternalDatabase); - try { - DataSource ds = external.start(); - Connection conn = ds.getConnection(); - try { - System.out.println("Database name: " - + conn.getMetaData().getDatabaseProductName()); - } finally { - conn.close(); - } - } finally { - external.stop(); - } - } finally { - inmemory.stop(); - } - - } + @Test + public void testExternalDB() throws Exception { + // Connect to inmemory db using External database class. + + Database inmemory = DatabaseBuilder + .getDatabase(DatabaseProvider.CAPABILITY_IN_MEMORY); + try { + inmemory.start(); + + System.setProperty(ExternalDatabase.DB_URL_PROP, inmemory + .getExternalJdbcUrl()); + System.setProperty(ExternalDatabase.DB_USER_PROP, inmemory + .getUsername()); + System.setProperty(ExternalDatabase.DB_PASSWORD_PROP, inmemory + .getPassword()); + + Database external = DatabaseBuilder + .getDatabase(DatabaseProvider.CAPABILITY_EXTERNAL); + assertTrue(external instanceof ExternalDatabase); + try { + DataSource ds = external.start(); + Connection conn = ds.getConnection(); + try { + System.out.println("Database name: " + + conn.getMetaData().getDatabaseProductName()); + } finally { + conn.close(); + } + } finally { + external.stop(); + } + } finally { + inmemory.stop(); + } + + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java index c2b47288..f7dd128a 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntity.java @@ -1,3 +1,18 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import javax.persistence.Entity; @@ -10,30 +25,28 @@ import javax.persistence.Table; @Table(name = "XYZ_MYENTITY") public class MyEntity { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private Long id; - - private String sleuteltje; - private String value; - - - public MyEntity() { - // Empty - } - - public MyEntity(String aKey, String aValue) { - sleuteltje = aKey; - value = aValue; - } - - public String getKey() { - return sleuteltje; - } - - public String getValue() { - return value; - } - - + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String sleuteltje; + private String value; + + public MyEntity() { + // Empty + } + + public MyEntity(String aKey, String aValue) { + sleuteltje = aKey; + value = aValue; + } + + public String getKey() { + return sleuteltje; + } + + public String getValue() { + return value; + } + } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java index 77f6114a..dcefee59 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyEntityExampleTestBase.java @@ -1,87 +1,99 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; +import static junit.framework.Assert.*; + import javax.persistence.EntityManager; -import javax.persistence.Persistence; -import javax.sql.DataSource; -import org.dbunit.DataSourceDatabaseTester; -import org.dbunit.DatabaseTestCase; import org.dbunit.IDatabaseTester; import org.dbunit.dataset.ITable; -import org.dbunit.dataset.filter.ITableFilterSimple; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.wamblee.support.persistence.DatabaseUtils; -import org.wamblee.support.persistence.JpaBuilder; -import org.wamblee.support.persistence.JpaTester; import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; -import static junit.framework.Assert.*; - - /** - * This class shows an example of how to test an entity using jpa. + * This class shows an example of how to test an entity using jpa. */ public class MyEntityExampleTestBase { - // This is the magical object that does all the test setup. - private JpaTester jpaTester; - + // This is the magical object that does all the test setup. + private JpaTester jpaTester; + // The jpa tester initializes a lot for us.... - - // A JPA builder that provides a transaction scoped entity manager for us. - private JpaBuilder builder; - - // The database tester for dbunit which is appropriately configured for our persistence unit. - private IDatabaseTester dbtester; - - // Database utilities with some additional functionality for working with the databse - // such as dropping tables, cleaning tables, etc. - private DatabaseUtils dbutils; - - @Before - public void setUp() throws Exception { - - // First we create the JpaTester by telling us which persistence unit we are going to test - jpaTester = new JpaTester(new MyPersistenceUnit()); - jpaTester.start(); - - // Retrieve some useful objects fromt he jpa tester. It also provides direct access to the datasource - // but we don't need it. We can use datbase utils if we want to execute straight JDBC calls. - builder = jpaTester.getJpaBuilder(); - dbtester = jpaTester.getDbTester(); - dbutils = jpaTester.getDbUtils(); - } - - @After - public void tearDown() { - jpaTester.stop(); - } - - @Test - public void testEntityPersistence() throws Exception { - - // Use the JPA builder to create a transaction scoped entity manager for as and execute the - // unit of work. - builder.execute(new JpaUnitOfWork() { - public Void execute(EntityManager em) { - MyEntity entity = new MyEntity("a", "b"); - em.persist(entity); - return null; - } - }); - - // Verify one row is written (using Db unit) - ITable table = dbtester.getDataSet().getTable("XYZ_MYENTITY"); - assertEquals(1, table.getRowCount()); - - assertEquals("a", table.getValue(0, "SLEUTELTJE")); - assertEquals("b", table.getValue(0, "VALUE")); - - // For this simple test, it can also be done through DatabaseUtils - assertEquals(1, dbutils.getTableSize("XYZ_MYENTITY")); - - } + + // A JPA builder that provides a transaction scoped entity manager for us. + private JpaBuilder builder; + + // The database tester for dbunit which is appropriately configured for our + // persistence unit. + private IDatabaseTester dbtester; + + // Database utilities with some additional functionality for working with + // the databse + // such as dropping tables, cleaning tables, etc. + private DatabaseUtils dbutils; + + @Before + public void setUp() throws Exception { + + // First we create the JpaTester by telling us which persistence unit we + // are going to test + jpaTester = new JpaTester(new MyPersistenceUnit()); + jpaTester.start(); + + // Retrieve some useful objects fromt he jpa tester. It also provides + // direct access to the datasource + // but we don't need it. We can use datbase utils if we want to execute + // straight JDBC calls. + builder = jpaTester.getJpaBuilder(); + dbtester = jpaTester.getDbTester(); + dbutils = jpaTester.getDbUtils(); + } + + @After + public void tearDown() { + jpaTester.stop(); + } + + @Test + public void testEntityPersistence() throws Exception { + + // Use the JPA builder to create a transaction scoped entity manager for + // as and execute the + // unit of work. + builder.execute(new JpaUnitOfWork() { + public Void execute(EntityManager aEm) { + MyEntity entity = new MyEntity("a", "b"); + aEm.persist(entity); + return null; + } + }); + + // Verify one row is written (using Db unit) + ITable table = dbtester.getDataSet().getTable("XYZ_MYENTITY"); + assertEquals(1, table.getRowCount()); + + assertEquals("a", table.getValue(0, "SLEUTELTJE")); + assertEquals("b", table.getValue(0, "VALUE")); + + // For this simple test, it can also be done through DatabaseUtils + assertEquals(1, dbutils.getTableSize("XYZ_MYENTITY")); + + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java index 777dd882..7a09d245 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyPersistenceUnit.java @@ -1,15 +1,30 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import org.wamblee.support.persistence.PersistenceUnitDescription; /** - * This class describes the persistence unit that we are testing. + * This class describes the persistence unit that we are testing. */ public class MyPersistenceUnit extends PersistenceUnitDescription { - private static final String JNDI_NAME = "wamblee/support/test"; - private static final String PERSISTENCE_UNIT_NAME = "org.wamblee.jee.support-test"; - - public MyPersistenceUnit() { - super(JNDI_NAME, PERSISTENCE_UNIT_NAME, new MyTables()); - } + private static final String JNDI_NAME = "wamblee/support/test"; + private static final String PERSISTENCE_UNIT_NAME = "org.wamblee.jee.support-test"; + + public MyPersistenceUnit() { + super(JNDI_NAME, PERSISTENCE_UNIT_NAME, new MyTables()); + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java index 1283a8ff..e0a337fe 100644 --- a/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/MyTables.java @@ -1,25 +1,41 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.filter.ITableFilterSimple; /** - * This class describes the tables we are testing. - * This implementation selects all tables with the "XYZ" prefix. + * This class describes the tables we are testing. This implementation selects + * all tables with the "XYZ" prefix. */ public class MyTables implements ITableFilterSimple { - - /** - * - * @param aJpaTables Specific tables used by the JPA provider in addition to those for the - * entities. - */ - public MyTables() { - // Empty. - } - public boolean accept(String tableName) throws DataSetException { - return tableName.startsWith("XYZ_"); - } + /** + * + * @param aJpaTables + * Specific tables used by the JPA provider in addition to those + * for the entities. + */ + public MyTables() { + // Empty. + } + + public boolean accept(String aTableName) throws DataSetException { + return aTableName.startsWith("XYZ_"); + } } diff --git a/test/enterprise/src/test/java/org/wamblee/support/persistence/TransactionProxyFactoryTestBase.java b/test/enterprise/src/test/java/org/wamblee/support/persistence/TransactionProxyFactoryTestBase.java new file mode 100644 index 00000000..286c8757 --- /dev/null +++ b/test/enterprise/src/test/java/org/wamblee/support/persistence/TransactionProxyFactoryTestBase.java @@ -0,0 +1,102 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence; + +import javax.persistence.EntityManager; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; + +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.*; + +public class TransactionProxyFactoryTestBase { + + public static interface Service { + int execute(int aValue) throws Exception; + } + + private JpaTester jpaTester; + + @Before + public void setUp() throws Exception { + jpaTester = new JpaTester(new MyPersistenceUnit()); + jpaTester.start(); + } + + @After + public void tearDown() throws Exception { + jpaTester.stop(); + } + + @Test + public void testServiceIsInvoked() throws Exception { + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), Service.class); + Service service = mock(Service.class); + when(service.execute(10)).thenReturn(200); + Service proxy = factory.getProxy(service); + int res = proxy.execute(10); + assertEquals(200, res); + verify(service).execute(10); + } + + @Test + public void testServiceThrowsException() throws Exception { + TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), Service.class); + Service service = mock(Service.class); + when(service.execute(10)).thenThrow(new RuntimeException("xyz")); + Service proxy = factory.getProxy(service); + try { + int res = proxy.execute(10); + fail(); + } catch (RuntimeException e) { + assertEquals("xyz", e.getMessage()); + } + } + + @Test + public void testEntityManagerIsPassed() throws Exception { + + + final TransactionProxyFactory factory = new TransactionProxyFactory( + jpaTester.getJpaBuilder(), Service.class); + Service service = new Service() { + private EntityManager em = factory.getTransactionScopedEntityManager(); + + @Override + public int execute(int aValue) throws Exception { + assertNotNull(em); + assertTrue(em.isOpen()); + return 0; + } + }; + + final Service proxy = factory.getProxy(service); + jpaTester.getJpaBuilder().execute(new JpaUnitOfWork() { + @Override + public Void execute(EntityManager aEm) throws Exception { + assert(aEm != null); + proxy.execute(10); + return null; + } + }); + } + +} diff --git a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java index fa4def8f..910ba8dd 100644 --- a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java +++ b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateJpaCustomizer.java @@ -1,31 +1,56 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.hibernate; -import java.util.Map; - import org.dbunit.dataset.filter.ITableFilterSimple; + import org.wamblee.support.persistence.JpaCustomizer; import org.wamblee.support.persistence.PersistenceUnitDescription; -public class HibernateJpaCustomizer implements JpaCustomizer { +import java.util.Map; - public HibernateJpaCustomizer() { +/** + * + * @author $author$ + * @version $Revision$ + */ +public class HibernateJpaCustomizer implements JpaCustomizer { + /** + * Creates a new HibernateJpaCustomizer object. + */ + public HibernateJpaCustomizer() { // Empty } - + @Override - public void customize(PersistenceUnitDescription aPersistenceUnit, Map aJpaProperties) { + public void customize(PersistenceUnitDescription aPersistenceUnit, + Map aJpaProperties) { // Hibernate: Override transaction type and datasource - aJpaProperties.put("javax.persistence.transactionType", "RESOURCE_LOCAL"); + aJpaProperties.put("javax.persistence.transactionType", + "RESOURCE_LOCAL"); aJpaProperties.put("javax.persistence.jtaDataSource", null); - aJpaProperties.put("javax.persistence.nonJtaDataSource", aPersistenceUnit.getJndiName()); - + aJpaProperties.put("javax.persistence.nonJtaDataSource", + aPersistenceUnit.getJndiName()); + // Hibernate schema generation - aJpaProperties.put("hibernate.hbm2ddl.auto", "create"); + aJpaProperties.put("hibernate.hbm2ddl.auto", "create"); } - + @Override public ITableFilterSimple getJpaTables() { return new HibernateTables(); } - } diff --git a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java index 4b2c8a09..f58ea8e9 100644 --- a/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java +++ b/test/hibernate/src/main/java/org/wamblee/support/persistence/hibernate/HibernateTables.java @@ -1,20 +1,34 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.hibernate; -import java.util.Arrays; -import java.util.List; - import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.filter.ITableFilterSimple; +import java.util.Arrays; +import java.util.List; + /** - * Toplink-specific tables. + * Toplink-specific tables. */ public class HibernateTables implements ITableFilterSimple { + private static final List TABLES = Arrays + .asList(new String[] { "" }); - private static final List TABLES = Arrays.asList(new String[] { "" } ); - - public boolean accept(String aTableName) throws DataSetException { - return TABLES.contains(aTableName); - } - + public boolean accept(String aTableName) throws DataSetException { + return TABLES.contains(aTableName); + } } diff --git a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java index 68edf22a..6059c956 100644 --- a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java +++ b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/DatabaseUtilsTest.java @@ -1,23 +1,27 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.hibernate; -import static junit.framework.Assert.assertEquals; - -import javax.persistence.EntityManager; -import javax.sql.DataSource; - -import org.dbunit.IDatabaseTester; -import org.dbunit.dataset.ITable; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.wamblee.support.persistence.Database; -import org.wamblee.support.persistence.DatabaseBuilder; -import org.wamblee.support.persistence.DatabaseUtils; import org.wamblee.support.persistence.DatabaseUtilsTestBase; -import org.wamblee.support.persistence.JpaBuilder; -import org.wamblee.support.persistence.PersistenceUnitDescription; -import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatabaseUtilsTest extends DatabaseUtilsTestBase { - // Empty, all tests inherited + // Empty, all tests inherited } diff --git a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java index 537cb549..3ac32a5d 100644 --- a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java +++ b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/MyEntityExampleTest.java @@ -1,28 +1,24 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.hibernate; -import javax.persistence.EntityManager; -import javax.persistence.Persistence; -import javax.sql.DataSource; - -import org.dbunit.DataSourceDatabaseTester; -import org.dbunit.DatabaseTestCase; -import org.dbunit.IDatabaseTester; -import org.dbunit.dataset.ITable; -import org.dbunit.dataset.filter.ITableFilterSimple; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.wamblee.support.persistence.DatabaseUtils; -import org.wamblee.support.persistence.JpaBuilder; -import org.wamblee.support.persistence.JpaTester; import org.wamblee.support.persistence.MyEntityExampleTestBase; -import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; - -import static junit.framework.Assert.*; - /** - * This class shows an example of how to test an entity using jpa. + * This class shows an example of how to test an entity using jpa. */ public class MyEntityExampleTest extends MyEntityExampleTestBase { // Empty, all tests are inherited diff --git a/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/TransactionProxyFactoryTest.java b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/TransactionProxyFactoryTest.java new file mode 100644 index 00000000..df057b5a --- /dev/null +++ b/test/hibernate/src/test/java/org/wamblee/support/persistence/hibernate/TransactionProxyFactoryTest.java @@ -0,0 +1,8 @@ +package org.wamblee.support.persistence.hibernate; + +import org.wamblee.support.persistence.TransactionProxyFactoryTestBase; + +public class TransactionProxyFactoryTest extends + TransactionProxyFactoryTestBase { + +} diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java index 814fe593..bc4a23a0 100644 --- a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java +++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/JndiSessionCustomizer.java @@ -1,59 +1,86 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.toplink; -import javax.naming.Context; -import javax.naming.InitialContext; - import oracle.toplink.essentials.jndi.JNDIConnector; import oracle.toplink.essentials.sessions.DatabaseLogin; import oracle.toplink.essentials.sessions.Session; import oracle.toplink.essentials.threetier.ServerSession; import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer; - + +import javax.naming.Context; +import javax.naming.InitialContext; + /** - * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) Use for clients that would like to use a - * JTA SE pu instead of a RESOURCE_LOCAL SE pu. - * - * This utility also makes sure that using a persistence.xml with a JTA datasource works in a standalone Java SE - * environment together with our JNDI stub. + * See http://wiki.eclipse.org/Customizing_the_EclipseLink_Application_(ELUG) + * Use for clients that would like to use a JTA SE pu instead of a + * RESOURCE_LOCAL SE pu. This utility also makes sure that using a + * persistence.xml with a JTA datasource works in a standalone Java SE + * environment together with our JNDI stub. */ -public class JndiSessionCustomizer - implements SessionCustomizer { - - public JndiSessionCustomizer() { - // Empty. - } - - /** - * Get a dataSource connection and set it on the session with lookupType=STRING_LOOKUP - */ - public void customize(Session session) throws Exception { - JNDIConnector connector = null; - Context context = null; - try { - context = new InitialContext(); - if(null != context) { - connector = (JNDIConnector)session.getLogin().getConnector(); // possible CCE - // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP - // Note: if both jta and non-jta elements exist this will only change the first one - and may still result in - // the COMPOSITE_NAME_LOOKUP being set - // Make sure only jta-data-source is in persistence.xml with no non-jta-data-source property set - connector.setLookupType(JNDIConnector.STRING_LOOKUP); - - // Or, if you are specifying both JTA and non-JTA in your persistence.xml then set both connectors to be safe - JNDIConnector writeConnector = (JNDIConnector)session.getLogin().getConnector(); - writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP); - JNDIConnector readConnector = - (JNDIConnector)((DatabaseLogin)((ServerSession)session).getReadConnectionPool().getLogin()).getConnector(); - readConnector.setLookupType(JNDIConnector.STRING_LOOKUP); - - System.out.println("JndiSessionCustomizer: configured " + connector.getName()); - } - else { - throw new Exception("JndiSessionCustomizer: Context is null"); - } +public class JndiSessionCustomizer implements SessionCustomizer { + /** + * Creates a new JndiSessionCustomizer object. + */ + public JndiSessionCustomizer() { + // Empty. } - catch(Exception e) { - e.printStackTrace(); + + /** + * Get a dataSource connection and set it on the session with + * lookupType=STRING_LOOKUP + * + * + */ + public void customize(Session aSession) throws Exception { + JNDIConnector connector = null; + Context context = null; + + try { + context = new InitialContext(); + + if (null != context) { + connector = (JNDIConnector) aSession.getLogin().getConnector(); // possible + // CCE + // Change from COMPOSITE_NAME_LOOKUP to STRING_LOOKUP + // Note: if both jta and non-jta elements exist this will only + // change the first one - and may still result in + // the COMPOSITE_NAME_LOOKUP being set + // Make sure only jta-data-source is in persistence.xml with no + // non-jta-data-source property set + + connector.setLookupType(JNDIConnector.STRING_LOOKUP); + + // Or, if you are specifying both JTA and non-JTA in your + // persistence.xml then set both connectors to be safe + JNDIConnector writeConnector = (JNDIConnector) aSession + .getLogin().getConnector(); + writeConnector.setLookupType(JNDIConnector.STRING_LOOKUP); + + JNDIConnector readConnector = (JNDIConnector) ((DatabaseLogin) ((ServerSession) aSession) + .getReadConnectionPool().getLogin()).getConnector(); + readConnector.setLookupType(JNDIConnector.STRING_LOOKUP); + + System.out.println("JndiSessionCustomizer: configured " + + connector.getName()); + } else { + throw new Exception("JndiSessionCustomizer: Context is null"); + } + } catch (Exception e) { + e.printStackTrace(); + } } - } -} \ No newline at end of file +} diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java index 5ba15e84..26fe6a54 100644 --- a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java +++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkJpaCustomizer.java @@ -1,30 +1,53 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.toplink; -import java.util.Map; - import org.dbunit.dataset.filter.ITableFilterSimple; + import org.wamblee.support.persistence.JpaCustomizer; import org.wamblee.support.persistence.PersistenceUnitDescription; -public class ToplinkJpaCustomizer implements JpaCustomizer { +import java.util.Map; - public ToplinkJpaCustomizer() { +/** + * + * @author $author$ + * @version $Revision$ + */ +public class ToplinkJpaCustomizer implements JpaCustomizer { + /** + * Creates a new ToplinkJpaCustomizer object. + */ + public ToplinkJpaCustomizer() { // Empty } - + @Override - public void customize(PersistenceUnitDescription aPersistenceUnit, Map aJpaProperties) { + public void customize(PersistenceUnitDescription aPersistenceUnit, + Map aJpaProperties) { // Hack to make JNDI lookup of the datasource work with toplink - aJpaProperties.put("toplink.session.customizer", JndiSessionCustomizer.class - .getName()); - + aJpaProperties.put("toplink.session.customizer", + JndiSessionCustomizer.class.getName()); + // DDL generation for toplink - aJpaProperties.put("toplink.ddl-generation", "create-tables"); + aJpaProperties.put("toplink.ddl-generation", "create-tables"); } - + @Override public ITableFilterSimple getJpaTables() { return new ToplinkTables(); } - } diff --git a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java index cd3a0562..4a99d7de 100644 --- a/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java +++ b/test/toplink-essentials/src/main/java/org/wamblee/support/persistence/toplink/ToplinkTables.java @@ -1,20 +1,34 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.toplink; -import java.util.Arrays; -import java.util.List; - import org.dbunit.dataset.DataSetException; import org.dbunit.dataset.filter.ITableFilterSimple; +import java.util.Arrays; +import java.util.List; + /** - * Toplink-specific tables. + * Toplink-specific tables. */ public class ToplinkTables implements ITableFilterSimple { + private static final List TABLES = Arrays + .asList(new String[] { "SEQUENCE" }); - private static final List TABLES = Arrays.asList(new String[] { "SEQUENCE" } ); - - public boolean accept(String aTableName) throws DataSetException { - return TABLES.contains(aTableName); - } - + public boolean accept(String aTableName) throws DataSetException { + return TABLES.contains(aTableName); + } } diff --git a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java index 095109d3..63974a33 100644 --- a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java +++ b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/DatabaseUtilsTest.java @@ -1,23 +1,47 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.toplink; import static junit.framework.Assert.assertEquals; -import javax.persistence.EntityManager; -import javax.sql.DataSource; - import org.dbunit.IDatabaseTester; + import org.dbunit.dataset.ITable; + import org.junit.After; import org.junit.Before; import org.junit.Test; + import org.wamblee.support.persistence.Database; import org.wamblee.support.persistence.DatabaseBuilder; import org.wamblee.support.persistence.DatabaseUtils; import org.wamblee.support.persistence.DatabaseUtilsTestBase; import org.wamblee.support.persistence.JpaBuilder; -import org.wamblee.support.persistence.PersistenceUnitDescription; import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; +import org.wamblee.support.persistence.PersistenceUnitDescription; + +import javax.persistence.EntityManager; + +import javax.sql.DataSource; +/** + * + * @author $author$ + * @version $Revision$ + */ public class DatabaseUtilsTest extends DatabaseUtilsTestBase { - // Empty, all tests inherited + // Empty, all tests inherited } diff --git a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java index 415ee70f..ebd299a9 100644 --- a/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java +++ b/test/toplink-essentials/src/test/java/org/wamblee/support/persistence/toplink/MyEntityExampleTest.java @@ -1,28 +1,46 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * 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.wamblee.support.persistence.toplink; -import javax.persistence.EntityManager; -import javax.persistence.Persistence; -import javax.sql.DataSource; +import static junit.framework.Assert.*; import org.dbunit.DataSourceDatabaseTester; import org.dbunit.DatabaseTestCase; import org.dbunit.IDatabaseTester; + import org.dbunit.dataset.ITable; import org.dbunit.dataset.filter.ITableFilterSimple; + import org.junit.After; import org.junit.Before; import org.junit.Test; + import org.wamblee.support.persistence.DatabaseUtils; import org.wamblee.support.persistence.JpaBuilder; +import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; import org.wamblee.support.persistence.JpaTester; import org.wamblee.support.persistence.MyEntityExampleTestBase; -import org.wamblee.support.persistence.JpaBuilder.JpaUnitOfWork; -import static junit.framework.Assert.*; +import javax.persistence.EntityManager; +import javax.persistence.Persistence; +import javax.sql.DataSource; /** - * This class shows an example of how to test an entity using jpa. + * This class shows an example of how to test an entity using jpa. */ public class MyEntityExampleTest extends MyEntityExampleTestBase { // Empty, all tests are inherited