integrated account management with default id provider management. create account would create a user in the default id provider and delete would delete if present. if password is provided on account create, a user would be created in the default id provider. added tenant id and userid in account. consolidated persistence.xml (jaxrsprovider/src/main/resources) so that DML could be performed atomically on all cs entities involved under the same transaction. added gen_ddl task to account(client)
test: account service tests and all service tests
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <persistence-unit name="org.collectionspace.services.account">
+ <persistence-unit name="org.collectionspace.services">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<non-jta-data-source>CspaceDS</non-jta-data-source>
<class>org.collectionspace.services.account.AccountsCommon</class>
<class>org.collectionspace.services.account.AccountsCommonList</class>
<class>org.collectionspace.services.account.AccountsCommonList$AccountListItem</class>
+ <class>org.collectionspace.services.authentication.User</class>
+ <class>org.collectionspace.services.authentication.Role</class>
+ <class>org.collectionspace.services.authentication.UserRole</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.max_fetch_depth" value="3"/>
</exec>\r
</target>\r
\r
+ <target name="gen_ddl" depends="gen_ddl-unix,gen_ddl-windows"\r
+ description="geneate ddl" />\r
+ <target name="gen_ddl-unix" if="osfamily-unix">\r
+ <exec executable="mvn" failonerror="true">\r
+ <arg value="-Pddl" />\r
+ <arg value="process-test-resources" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+ <target name="gen_ddl-windows" if="osfamily-windows">\r
+ <exec executable="cmd" failonerror="true">\r
+ <arg value="/c" />\r
+ <arg value="mvn.bat" />\r
+ <arg value="-Pddl" />\r
+ <arg value="process-test-resources" />\r
+ <arg value="-f" />\r
+ <arg value="${basedir}/pom.xml" />\r
+ <arg value="-N" />\r
+ <arg value="${mvn.opts}" />\r
+ </exec>\r
+ </target>\r
+\r
<target name="create_db"\r
description="create tables(s), indices for account service">\r
<sql driver="com.mysql.jdbc.Driver"\r
drop table if exists accounts_common;
-create table accounts_common (csid varchar(255) not null, email longtext not null, first_name longtext not null, last_name longtext not null, mi varchar(1), mobile varchar(15), phone varchar(15), screen_name varchar(128) not null, primary key (csid));
+create table accounts_common (csid varchar(255) not null, email longtext not null, first_name longtext not null, last_name longtext not null, mi varchar(1), mobile varchar(15), phone varchar(15), screen_name varchar(128) not null, tenantid varchar(255) not null, userid longtext not null, primary key (csid));
// Submit the request to the service and store the response.
AccountsCommon account =
- createAccountInstance("barney", "dino", "barney", "hello", "barney@dinoland.com");
+ createAccountInstance("barney", "dino", "barney", "hithere08", "barney@dinoland.com");
ClientResponse<Response> res = client.create(account);
int statusCode = res.getStatus();
}
}
- /* (non-Javadoc)
- * @see org.collectionspace.services.client.test.ServiceTest#createList()
- */
+ //to not cause uniqueness violation for account, createList is removed
@Override
@Test(dataProvider = "testName", dataProviderClass = AbstractServiceTest.class,
dependsOnMethods = {"create"})
public void createList(String testName) throws Exception {
- for (int i = 0; i < 3; i++) {
- create(testName);
- }
}
-
+
// Failure outcomes
// Placeholders until the three tests below can be uncommented.
// See Issue CSPACE-401.
account.setFirstName(firstName);
account.setLastName(lastName);
account.setScreenName(screenName);
- account.setUserName(screenName);
+ account.setUserId(screenName);
byte[] b64passwd = Base64.encodeBase64(passwd.getBytes());
account.setPassword(b64passwd);
account.setEmail(email);
account.setFirstName("John");
account.setLastName("Doe");
account.setEmail("john.doe@berkeley.edu");
+ account.setUserId("johndoe");
id = UUID.randomUUID().toString();
account.setCsid(id);
+ account.setTenantid("123"); //set by service runtime
em.getTransaction().begin();
em.persist(account);
// Commit the transaction
log4j.logger.org.apache=INFO\r
log4j.logger.httpclient=INFO\r
log4j.logger.org.jboss.resteasy=INFO\r
+log4j.logger.org.hibernate=INFO\r
</xs:appinfo>
</xs:annotation>
</xs:element>
- <!-- optional username for default identity provider -->
- <xs:element name="userName" type="xs:string" minOccurs="0" maxOccurs="1">
+ <!-- userid, could be calnet id, openid URI -->
+ <xs:element name="userId" type="xs:string" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:appinfo>
- <hj:ignored/>
+ <hj:basic>
+ <orm:column name="userid" length="512" nullable="false"/>
+ </hj:basic>
</xs:appinfo>
</xs:annotation>
</xs:element>
- <!-- optional base64 encoded password for default identity provider -->
+ <!-- optional base64 encoded password for default identity provider only -->
<xs:element name="password" type="xs:base64Binary" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:appinfo>
</xs:appinfo>
</xs:annotation>
</xs:element>
+ <!-- tenant id is not needed from service consumer, it will be ignored if provided -->
+ <!-- tenant id is for internal use for CollectionSpace -->
+ <!-- it is assumed that account creation is performed under valid -->
+ <!-- tenant context. tenant id is never returned in response -->
+ <xs:element name="tenantid" type="xs:string" minOccurs="0" maxOccurs="1">
+ <xs:annotation>
+ <xs:appinfo>
+ <hj:basic>
+ <orm:column name="tenantid" nullable="false"/>
+ </hj:basic>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
</xs:sequence>
<xs:attribute name="csid" type="xs:string">
<xs:annotation>
*/
package org.collectionspace.services.account.storage;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Query;
+import org.apache.commons.codec.binary.Base64;
+import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.account.AccountsCommon;
+import org.collectionspace.services.authentication.User;
+import org.collectionspace.services.common.context.ServiceContext;
+import org.collectionspace.services.common.document.BadRequestException;
+import org.collectionspace.services.common.document.DocumentException;
+import org.collectionspace.services.common.document.DocumentHandler;
+import org.collectionspace.services.common.document.DocumentHandler.Action;
+import org.collectionspace.services.common.document.DocumentNotFoundException;
+import org.collectionspace.services.common.document.DocumentWrapper;
+import org.collectionspace.services.common.document.DocumentWrapperImpl;
+import org.collectionspace.services.common.security.SecurityUtils;
import org.collectionspace.services.common.storage.jpa.JpaStorageClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* AccountStorageClient deals with both Account and Default Identity Provider's
* state in persistent storage
* @author
*/
-public class AccountStorageClient extends JpaStorageClient
-{
+public class AccountStorageClient extends JpaStorageClient {
+ private final Logger logger = LoggerFactory.getLogger(AccountStorageClient.class);
+
+ public AccountStorageClient() {
+ }
+
+ @Override
+ public String create(ServiceContext ctx,
+ DocumentHandler handler) throws BadRequestException,
+ DocumentException {
+
+ String docType = ctx.getDocumentType();
+ if (docType == null) {
+ throw new DocumentNotFoundException(
+ "Unable to find DocumentType for service " + ctx.getServiceName());
+ }
+ if (handler == null) {
+ throw new IllegalArgumentException(
+ "AccountStorageClient.create: handler is missing");
+ }
+ EntityManagerFactory emf = null;
+ EntityManager em = null;
+ try {
+ handler.prepare(Action.CREATE);
+ AccountsCommon account = (AccountsCommon) handler.getCommonPart();
+ DocumentWrapper<AccountsCommon> wrapDoc =
+ new DocumentWrapperImpl<AccountsCommon>(account);
+ handler.handle(Action.CREATE, wrapDoc);
+ emf = getEntityManagerFactory();
+ em = emf.createEntityManager();
+ em.getTransaction().begin();
+ //if userid and password are given, add to default id provider
+ if (account.getUserId() != null && account.getPassword() != null) {
+ User user = createUser(account);
+ em.persist(user);
+ }
+ account.setTenantid(ctx.getTenantId());
+ em.persist(account);
+ em.getTransaction().commit();
+ handler.complete(Action.CREATE, wrapDoc);
+ return (String) getValue(account, "getCsid");
+ } catch (Exception e) {
+ if (em != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("Caught exception ", e);
+ }
+ throw new DocumentException(e);
+ } finally {
+ if (em != null) {
+ releaseEntityManagerFactory(emf);
+ }
+ }
+ }
+
+ @Override
+ public void delete(ServiceContext ctx, String id)
+ throws DocumentNotFoundException,
+ DocumentException {
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("deleting entity with id=" + id);
+ }
+ String docType = ctx.getDocumentType();
+ if (docType == null) {
+ throw new DocumentNotFoundException(
+ "Unable to find DocumentType for service " + ctx.getServiceName());
+ }
+ EntityManagerFactory emf = null;
+ EntityManager em = null;
+ try {
+ emf = getEntityManagerFactory();
+ em = emf.createEntityManager();
+ //TODO investigate if deep delete is possible
+ //query an delete is inefficient
+ AccountsCommon accountFound = em.find(AccountsCommon.class, id);
+ if (accountFound == null) {
+ if (em != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ String msg = "could not find entity with id=" + id;
+ logger.error(msg);
+ throw new DocumentNotFoundException(msg);
+ }
+
+ StringBuilder accDelStr = new StringBuilder("DELETE FROM ");
+ accDelStr.append(getEntityName(ctx));
+ accDelStr.append(" WHERE csid = :csid");
+ //TODO: add tenant id
+ Query accDel = em.createQuery(accDelStr.toString());
+ accDel.setParameter("csid", id);
+ //TODO: add tenant id
+
+ //if userid gives any indication about the id provider, it should
+ //be used to avoid the following approach
+ User userLocal = em.find(User.class, accountFound.getUserId());
+ Query usrDel = null;
+ if (userLocal != null) {
+ StringBuilder usrDelStr = new StringBuilder("DELETE FROM ");
+ usrDelStr.append(User.class.getCanonicalName());
+ usrDelStr.append(" WHERE username = :username");
+ //TODO: add tenant id
+ usrDel = em.createQuery(usrDelStr.toString());
+ usrDel.setParameter("username", accountFound.getUserId());
+ }
+ em.getTransaction().begin();
+ int accDelCount = accDel.executeUpdate();
+ if (accDelCount != 1) {
+ if (em != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ }
+ if (userLocal != null) {
+ int usrDelCount = usrDel.executeUpdate();
+ if (usrDelCount != 1) {
+ if (em != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ }
+ if (usrDelCount != 1) {
+ String msg = "could not find user with username=" + accountFound.getUserId();
+ logger.error(msg);
+ throw new DocumentNotFoundException(msg);
+ }
+ }
+ em.getTransaction().commit();
+
+ } catch (DocumentException de) {
+ throw de;
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Caught exception ", e);
+ }
+ if (em != null && em.getTransaction().isActive()) {
+ em.getTransaction().rollback();
+ }
+ throw new DocumentException(e);
+ } finally {
+ if (emf != null) {
+ releaseEntityManagerFactory(emf);
+ }
+ }
+ }
+
+ private User createUser(AccountsCommon account) {
+ User user = new User();
+ user.setUsername(account.getUserId());
+ byte[] bpass = Base64.decodeBase64(account.getPassword());
+ SecurityUtils.validatePassword(new String(bpass));
+ String secEncPasswd = SecurityUtils.createPasswordHash(
+ account.getUserId(), new String(bpass));
+ user.setPasswd(secEncPasswd);
+ return user;
+ }
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
- <persistence-unit name="org.collectionspace.services.authentication">
- <non-jta-data-source>java:comp/env/jdbc/CspaceDS</non-jta-data-source>
- <class>org.collectionspace.services.authentication.User</class>
- <class>org.collectionspace.services.authentication.Role</class>
- <class>org.collectionspace.services.authentication.UserRole</class>
- <properties>
- <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
- <property name="hibernate.max_fetch_depth" value="3"/>
- <!--property name="hibernate.hbm2ddl.auto" value="create-drop"/-->
- </properties>
- </persistence-unit>
-</persistence>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
- CollectionSpace identity provider schema (XSD)
+ CollectionSpace default (security) identity provider schema (XSD)
- Entity :
+ Entity(s) : users, roles, users_roles
Used for:
$LastChangedRevision: 916 $
<xs:annotation>
<xs:appinfo>
<hj:id>
- <orm:column name="username" length="128" nullable="false"/>
+ <orm:column name="username" length="512" nullable="false"/>
</hj:id>
</xs:appinfo>
</xs:annotation>
use cspace;\r
\r
DROP TABLE IF EXISTS users;\r
-CREATE TABLE users(username VARCHAR(128) PRIMARY KEY, passwd VARCHAR(128) NOT NULL );\r
+CREATE TABLE users(username VARCHAR(512) PRIMARY KEY, passwd VARCHAR(128) NOT NULL );\r
CREATE INDEX username_users on users(username);\r
\r
DROP TABLE IF EXISTS roles;\r
CREATE INDEX rolename_roles on roles(rolename);\r
\r
DROP TABLE IF EXISTS users_roles;\r
-CREATE TABLE users_roles(username VARCHAR(128) NOT NULL, rolename VARCHAR(128) NOT NULL);\r
+CREATE TABLE users_roles(username VARCHAR(512) NOT NULL, rolename VARCHAR(128) NOT NULL);\r
CREATE INDEX username_users_roles on users_roles(username);
\ No newline at end of file
<artifactId>hibernate-entitymanager</artifactId>\r
</dependency>\r
<!-- jboss -->\r
+ <dependency>\r
+ <groupId>jboss</groupId>\r
+ <artifactId>jbosssx</artifactId>\r
+ <version>4.2.3.GA</version>\r
+ <scope>provided</scope>\r
+ </dependency>\r
<dependency>\r
<groupId>jboss</groupId>\r
<artifactId>jboss-remoting</artifactId>\r
--- /dev/null
+/**
+ * This document is a part of the source code and related artifacts
+ * for CollectionSpace, an open source collections management system
+ * for museums and related institutions:
+ *
+ * http://www.collectionspace.org
+ * http://wiki.collectionspace.org
+ *
+ * Copyright © 2009 Regents of the University of California
+ *
+ * Licensed under the Educational Community License (ECL), Version 2.0.
+ * You may not use this file except in compliance with this License.
+ *
+ * You may obtain a copy of the ECL 2.0 License at
+ * https://source.collectionspace.org/collection-space/LICENSE.txt
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.collectionspace.services.common.security;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author
+ */
+public class SecurityUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(SecurityUtils.class);
+
+ /**
+ * createPasswordHash creates password has using configured digest algorithm
+ * and encoding
+ * @param user
+ * @param password in cleartext
+ * @return hashed password
+ */
+ public static String createPasswordHash(String username, String password) {
+ //TODO: externalize digest algo and encoding
+ return org.jboss.security.Util.createPasswordHash("SHA-256", //digest algo
+ "base64", //encoding
+ null, //charset
+ username,
+ password);
+ }
+
+ /**
+ * validatePassword validates password per configured password policy
+ * @param password
+ */
+ public static void validatePassword(String password) {
+ //TODO: externalize password length
+ if (password == null) {
+ String msg = "Password missing ";
+ logger.error(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (password.length() < 8 || password.length() > 24) {
+ String msg = "Password length should be >8 and <24";
+ logger.error(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ }
+}
*/
package org.collectionspace.services.common.storage.jpa;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import javax.persistence.EntityManager;
public class JpaStorageClient implements StorageClient {
private final Logger logger = LoggerFactory.getLogger(JpaStorageClient.class);
-
+ protected final static String CS_PERSISTENCE_UNIT = "org.collectionspace.services";
public JpaStorageClient() {
}
Object entity = handler.getCommonPart();
DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(entity);
handler.handle(Action.CREATE, wrapDoc);
- emf = getEntityManagerFactory(docType);
+ emf = getEntityManagerFactory();
em = emf.createEntityManager();
em.getTransaction().begin();
em.persist(entity);
em.getTransaction().commit();
handler.complete(Action.CREATE, wrapDoc);
- return getCsid(entity);
+ return (String) getValue(entity, "getCsid");
+ } catch (DocumentException de) {
+ throw de;
} catch (Exception e) {
if (em != null && em.getTransaction().isActive()) {
em.getTransaction().rollback();
if ((null != where) && (where.length() > 0)) {
queryStr.append(" AND " + where);
}
- emf = getEntityManagerFactory(docType);
+ emf = getEntityManagerFactory();
em = emf.createEntityManager();
Query q = em.createQuery(queryStr.toString());
q.setParameter("csid", id);
DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(o);
handler.handle(Action.GET, wrapDoc);
handler.complete(Action.GET, wrapDoc);
- } catch (IllegalArgumentException iae) {
- throw iae;
} catch (DocumentException de) {
throw de;
} catch (Exception e) {
throw new UnsupportedOperationException("use getFiltered instead");
}
- /**
- * getFiltered get all documents for an entity service from the Document repository,
- * given filter parameters specified by the handler.
- * @param ctx service context under which this method is invoked
- * @param handler should be used by the caller to provide and transform the document
- * @throws DocumentNotFoundException if workspace not found
- * @throws DocumentException
- */
+ @Override
public void getFiltered(ServiceContext ctx, DocumentHandler handler)
throws DocumentNotFoundException, DocumentException {
if (handler == null) {
if ((null != where) && (where.length() > 0)) {
queryStr.append(" AND " + where);
}
- emf = getEntityManagerFactory(docType);
+ emf = getEntityManagerFactory();
em = emf.createEntityManager();
Query q = em.createQuery(queryStr.toString());
//TODO: add tenant id
setCsid(entity, id);
DocumentWrapper<Object> wrapDoc = new DocumentWrapperImpl<Object>(entity);
handler.handle(Action.UPDATE, wrapDoc);
- emf = getEntityManagerFactory(docType);
+ emf = getEntityManagerFactory();
em = emf.createEntityManager();
em.getTransaction().begin();
Object entityFound = em.find(entity.getClass(), id);
- if(entityFound == null) {
+ if (entityFound == null) {
if (em != null && em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
}
}
- /**
- * delete a document from the Nuxeo repository
- * @param ctx service context under which this method is invoked
- * @param id
- * of the document
- * @throws DocumentException
- */
@Override
public void delete(ServiceContext ctx, String id)
throws DocumentNotFoundException,
deleteStr.append(" WHERE csid = :csid");
//TODO: add tenant id
- emf = getEntityManagerFactory(docType);
+ emf = getEntityManagerFactory();
em = emf.createEntityManager();
Query q = em.createQuery(deleteStr.toString());
q.setParameter("csid", id);
}
}
- private EntityManagerFactory getEntityManagerFactory(
+ protected EntityManagerFactory getEntityManagerFactory() {
+ return getEntityManagerFactory(CS_PERSISTENCE_UNIT);
+ }
+ protected EntityManagerFactory getEntityManagerFactory(
String persistenceUnit) {
return Persistence.createEntityManagerFactory(persistenceUnit);
}
- private void releaseEntityManagerFactory(EntityManagerFactory emf) {
+ protected void releaseEntityManagerFactory(EntityManagerFactory emf) {
if (emf != null) {
emf.close();
}
}
- private String getCsid(Object o) throws Exception {
- Class c = o.getClass();
- Method m = c.getMethod("getCsid");
- if (m == null) {
- String msg = "Could not find csid in entity of class=" + o.getClass().getCanonicalName();
+ /**
+ * getValue gets invokes specified accessor method on given object. Assumption
+ * is that this is used for JavaBean pattern getXXX methods only.
+ * @param o object to return value from
+ * @param methodName of method to invoke
+ * @return value returned of invocation
+ * @throws NoSuchMethodException
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ protected Object getValue(Object o, String methodName)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ if (methodName == null) {
+ String msg = methodName + " cannot be null";
logger.error(msg);
throw new IllegalArgumentException(msg);
}
+ Class c = o.getClass();
+ Method m = c.getMethod(methodName);
Object r = m.invoke(o);
if (logger.isDebugEnabled()) {
- logger.debug("getCsid returned csid=" + r +
+ logger.debug("getValue returned value=" + r +
" for " + c.getName());
}
+ return r;
+ }
- return (String) r;
+ /**
+ * setValue mutates the given object by invoking specified method. Assumption
+ * is that this is used for JavaBean pattern setXXX methods only.
+ * @param o object to mutate
+ * @param methodName indicates method to invoke
+ * @param argType type of the only argument (assumed) to method
+ * @param argValue value of the only argument (assumed) to method
+ * @return
+ * @throws NoSuchMethodException
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ protected Object setValue(Object o, String methodName, Class argType, Object argValue)
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ if (methodName == null) {
+ String msg = methodName + " cannot be null";
+ logger.error(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ if (argType == null) {
+ String msg = "argType cannot be null";
+ logger.error(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ Class c = o.getClass();
+ Method m = c.getMethod(methodName, argType);
+ Object r = m.invoke(o, argValue);
+ if (logger.isDebugEnabled()) {
+ logger.debug("completed invocation of " + methodName +
+ " for " + c.getName());
+ }
+ return r;
}
- private void setCsid(Object o, String csid) throws Exception {
- //verify csid
- String id = getCsid(o);
+ protected void setCsid(Object o, String csid) throws Exception {
+ //verify csid
+ String id = (String) getValue(o, "getCsid");
if (id != null) {
if (!id.equals(csid)) {
String msg = "Csids do not match!";
}
//set csid
- Class c = o.getClass();
- Method m = c.getMethod("setCsid", java.lang.String.class);
- if (m == null) {
- String msg = "Could not find csid in entity of class=" + o.getClass().getCanonicalName();
- logger.error(msg);
- throw new IllegalArgumentException(msg);
- }
-
- Object r = m.invoke(o, csid);
- if (logger.isDebugEnabled()) {
- logger.debug("completed setCsid " +
- " for " + c.getName());
- }
-
+ setValue(o, "setCsid", java.lang.String.class, csid);
}
- private String getEntityName(ServiceContext ctx) {
+ protected String getEntityName(ServiceContext ctx) {
Object o = ctx.getProperty("entity-name");
if (o == null) {
throw new IllegalArgumentException("property entity-name missing in context " +