org.ralasafe.application.ApplicationManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.ralasafe.application.ApplicationManagerImpl.java

Source

/**
 * Copyright (c) 2004-2011 Wang Jinbao(Julian Wong), http://www.ralasafe.com
 * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
 */
package org.ralasafe.application;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.ralasafe.EntityExistException;
import org.ralasafe.Factory;
import org.ralasafe.db.ComplexWhereElement;
import org.ralasafe.db.DBLevelException;
import org.ralasafe.db.DBPower;
import org.ralasafe.db.FieldWhereElement;
import org.ralasafe.db.JavaBeanColumnAdapter;
import org.ralasafe.db.JavaBeanObjectNewer;
import org.ralasafe.db.LWhereElement;
import org.ralasafe.db.SingleValueComparator;
import org.ralasafe.db.Table;
import org.ralasafe.db.TableNewer;
import org.ralasafe.db.TableUpdator;
import org.ralasafe.db.impl.TableDeletorImpl;
import org.ralasafe.db.impl.TableSaverImpl;
import org.ralasafe.db.impl.TableSelectorImpl;
import org.ralasafe.db.impl.TableUpdatorImpl;
import org.ralasafe.entitle.QueryManager;
import org.ralasafe.entitle.UserCategoryManager;
import org.ralasafe.metadata.user.FieldMetadata;
import org.ralasafe.metadata.user.TableMetadata;
import org.ralasafe.metadata.user.UserMetadata;
import org.ralasafe.privilege.PrivilegeManager;
import org.ralasafe.privilege.RoleManager;
import org.ralasafe.user.User;
import org.ralasafe.userType.UserType;
import org.ralasafe.userType.UserTypeManager;
import org.ralasafe.util.DBUtil;

public class ApplicationManagerImpl implements ApplicationManager {
    private static Log logger = LogFactory.getLog(ApplicationManagerImpl.class);

    private Table table;
    private TableSelectorImpl selector;
    private TableSaverImpl saver;
    private TableUpdator updator;
    private TableDeletorImpl deletor;
    private FieldWhereElement appNameWhereEmt;

    private TableSaverImpl applicationUserTypeSaver;
    private TableSelectorImpl applicationUserTypeSelector;
    private TableDeletorImpl applicationUserTypeDeletor;
    private FieldWhereElement appNameUserTypeTableWhereEmt;
    private ComplexWhereElement appNameUserTypeNameUserTypeTableWhereEmt;

    private Map store = new HashMap();
    private boolean changed = true;

    public ApplicationManagerImpl() {
        initApplicationTableInfo();
        initApplicationUserTypeTableInfo();
    }

    private void initApplicationTableInfo() {
        TableNewer newer = new TableNewer();
        newer.setTableName("application");
        newer.setColumnNames(new String[] { "name", "description" });
        newer.setIdColumnNames(new String[] { "name" });
        // newer.setUniqueColumnNames(new String[] { "name" });
        newer.setMappingClass(Application.class.getName());
        newer.put("name", new JavaBeanColumnAdapter("name", "java.lang.String"));
        newer.put("description", new JavaBeanColumnAdapter("description", "java.lang.String"));

        newer.setId(DBPower.getTableId(null, newer.getTableName()));
        table = newer.getTable();
        selector = new TableSelectorImpl();
        selector.setObjectNewer(new JavaBeanObjectNewer(newer.getMappingClass()));
        saver = new TableSaverImpl();
        updator = new TableUpdatorImpl();
        deletor = new TableDeletorImpl();
        selector.setTable(table);
        saver.setTable(table);
        updator.setTable(table);
        deletor.setTable(table);

        appNameWhereEmt = new FieldWhereElement();
        appNameWhereEmt.setColumn(table.getColumns()[0]);
        appNameWhereEmt.setCompartor(SingleValueComparator.EQUAL);
        appNameWhereEmt.setContextValue(true);
    }

    private void initApplicationUserTypeTableInfo() {
        TableNewer newer = new TableNewer();
        newer.setTableName("applicationusertype");
        newer.setColumnNames(new String[] { "appName", "userTypeName", "userMetadataStr" });
        newer.setIdColumnNames(new String[] { "appName", "userTypeName" });
        // newer.setUniqueColumnNames(new String[] { "name" });
        newer.setMappingClass(ApplicationUserType.class.getName());
        newer.put("appName", new JavaBeanColumnAdapter("appName", "java.lang.String"));
        newer.put("userTypeName", new JavaBeanColumnAdapter("userTypeName", "java.lang.String"));
        newer.put("userMetadataStr", new JavaBeanColumnAdapter("userMetadataStr", "java.lang.String"));

        newer.setId(DBPower.getTableId(null, newer.getTableName()));
        Table appUserTypeTable = newer.getTable();
        applicationUserTypeSelector = new TableSelectorImpl();
        applicationUserTypeSelector.setObjectNewer(new JavaBeanObjectNewer(newer.getMappingClass()));
        applicationUserTypeSaver = new TableSaverImpl();
        // updator = new TableUpdatorImpl();
        applicationUserTypeDeletor = new TableDeletorImpl();
        applicationUserTypeSelector.setTable(appUserTypeTable);
        applicationUserTypeSaver.setTable(appUserTypeTable);
        // updator.setTable(table);
        applicationUserTypeDeletor.setTable(appUserTypeTable);

        appNameUserTypeTableWhereEmt = new FieldWhereElement();
        appNameUserTypeTableWhereEmt.setColumn(appUserTypeTable.getColumns()[0]);
        appNameUserTypeTableWhereEmt.setCompartor(SingleValueComparator.EQUAL);
        appNameUserTypeTableWhereEmt.setContextValue(true);

        appNameUserTypeNameUserTypeTableWhereEmt = new ComplexWhereElement();
        FieldWhereElement emt1 = new FieldWhereElement();
        emt1.setColumn(appUserTypeTable.getColumns()[0]);
        emt1.setCompartor(SingleValueComparator.EQUAL);
        emt1.setContextValue(true);
        FieldWhereElement emt2 = new FieldWhereElement();
        emt2.setColumn(appUserTypeTable.getColumns()[1]);
        emt2.setCompartor(SingleValueComparator.EQUAL);
        emt2.setContextValue(true);

        appNameUserTypeNameUserTypeTableWhereEmt.setFirstPart(emt1);
        LWhereElement lemt = new LWhereElement();
        lemt.setLinkType(LWhereElement.AND_LINK_TYPE);
        lemt.setWhereElement(emt2);
        LWhereElement[] linkedParts = new LWhereElement[] { lemt };
        appNameUserTypeNameUserTypeTableWhereEmt.setLinkedParts(linkedParts);
    }

    private synchronized void loadIntoMemory() {
        if (!changed) {
            return;
        }

        Collection allApps = selector.select(null, null);
        Collection allAppUserTypes = applicationUserTypeSelector.select(null, null);

        store.clear();

        for (Iterator iter = allApps.iterator(); iter.hasNext();) {
            Application app = (Application) iter.next();
            store.put(app.getName(), app);
        }

        for (Iterator iter = allAppUserTypes.iterator(); iter.hasNext();) {
            ApplicationUserType entry = (ApplicationUserType) iter.next();
            String appName = entry.getAppName();

            UserType userType = extractUserType(entry);

            Application app = (Application) store.get(appName);
            app.getUserTypes().add(userType);
        }
        changed = false;
    }

    public void addApplication(Locale locale, Application app) throws EntityExistException {
        loadIntoMemory();

        // Already exist?
        if (store.keySet().contains(app.getName())) {
            throw new EntityExistException("The name '" + app.getName() + "' already exists.");
        }

        Connection conn = null;
        boolean commitMode = true;
        try {
            conn = DBPower.getConnection(table.getId());
            commitMode = conn.getAutoCommit();
            conn.setAutoCommit(false);

            // save application info
            saver.save(conn, app);

            // save usertypes info
            Collection userTypes = app.getUserTypes();
            if (userTypes != null && userTypes.size() > 0) {
                List appUserTypes = new ArrayList(userTypes.size());
                for (Iterator iter = userTypes.iterator(); iter.hasNext();) {
                    UserType userType = (UserType) iter.next();

                    ApplicationUserType appUserType = new ApplicationUserType();
                    appUserType.setAppName(app.getName());
                    appUserType.setUserTypeName(userType.getName());
                    String produceUserMetadataStr = produceUserMetadataStr(userType.getUserMetadata());
                    appUserType.setUserMetadataStr(produceUserMetadataStr);

                    appUserTypes.add(appUserType);
                }

                applicationUserTypeSaver.batchSave(conn, appUserTypes);
            }

            conn.commit();
        } catch (SQLException e) {
            DBUtil.rollback(conn);
            throw new DBLevelException(e);
        } finally {
            DBUtil.setCommitMode(conn, commitMode);
            DBUtil.close(conn);
        }

        changed = true;

        // create tables
        createTablesForApp(app);

        Iterator itr = app.getUserTypes().iterator();
        while (itr.hasNext()) {
            UserType userType = (UserType) itr.next();
            // create reserved query
            QueryManager queryManager = Factory.getQueryManager(app.getName());
            queryManager.addReservedQuery(userType.getName());

            // create reserved usercategory
            UserCategoryManager userCategoryManager = Factory.getUserCategoryManager(app.getName());
            userCategoryManager.addReservedUserCategory(locale);

            // create reserved privilege
            PrivilegeManager privilegeManager = Factory.getPrivilegeManager(app.getName());
            privilegeManager.addReservedPrivilege(locale);

            // create reserved roles
            RoleManager roleManager = Factory.getRoleManager(app.getName());
            roleManager.addReservedRole(locale);
        }
    }

    private void createTablesForApp(Application app) {

        // Name rule for role, privilege and roleprivilege is:
        //   <appName>_role, <appName>_privilege and <appName>_roleprivilege
        String appName = app.getName();
        String sqlRole = DBUtil.roleTableCreateSql(appName);
        String sqlPrivilege = DBUtil.privilegeTableCreateSql(appName);
        String sqlRolePrivilege = DBUtil.rolePrivilegeTableCreateSql(appName);

        // Each usertype has it's own userrole table. Name rule is:
        // <appName>_<userTypeName>_userrole
        ArrayList sqlUserRoles = new ArrayList();
        Iterator itr = app.getUserTypes().iterator();
        while (itr.hasNext()) {
            UserType userType = (UserType) itr.next();
            userType = Factory.getUserTypeManager().getUserType(userType.getName());
            TableMetadata userTable = userType.getUserMetadata().getMainTableMetadata();
            String sqlUserRole = DBUtil.userRoleTableCreateSql(appName, userType.getName(), User.idFieldName,
                    getIdColumnType(userTable));
            sqlUserRoles.add(sqlUserRole);
        }

        String tableQueryCreateSql = DBUtil.tableQueryCreateSql(appName);
        String tableUserCategoryCreateSql = DBUtil.tableUserCategoryCreateSql(appName);
        String tableDicisionEntitlementCreateSql = DBUtil.tableDecisionEntitlementCreateSql(appName);
        String tableQueryEntitlementCreateSql = DBUtil.tableQueryEntitlementCreateSql(appName);
        String tableBusinessDataCreateSql = DBUtil.tableBusinessDataCreateSql(appName);

        Connection conn = DBPower.getConnection(DBPower.getDefaultDsName());
        try {
            // conn.setAutoCommit(false);
            // create tables
            DBUtil.exec(conn, sqlRole);
            DBUtil.exec(conn, sqlPrivilege);
            DBUtil.exec(conn, sqlRolePrivilege);
            itr = sqlUserRoles.iterator();
            while (itr.hasNext()) {
                DBUtil.exec(conn, (String) itr.next());
            }
            DBUtil.exec(conn, tableQueryCreateSql);
            DBUtil.exec(conn, tableUserCategoryCreateSql);
            DBUtil.exec(conn, tableDicisionEntitlementCreateSql);
            DBUtil.exec(conn, tableQueryEntitlementCreateSql);
            DBUtil.exec(conn, tableBusinessDataCreateSql);
            // conn.commit();
        } catch (SQLException e) {
            // try {
            // conn.rollback();
            // } catch (SQLException e1) {
            // throw new DBLevelException(e1);
            // }
            throw new DBLevelException(e);
        } finally {
            DBUtil.close(conn);
        }
    }

    public void addApplicationUserType(Locale locale, String appName, UserType userType) {
        loadIntoMemory();

        // 1. save ApplicationUserType info
        ApplicationUserType appUserType = new ApplicationUserType();
        appUserType.setAppName(appName);
        appUserType.setUserTypeName(userType.getName());
        String produceUserMetadataStr = produceUserMetadataStr(userType.getUserMetadata());
        appUserType.setUserMetadataStr(produceUserMetadataStr);

        try {
            applicationUserTypeSaver.save(appUserType);
        } catch (EntityExistException e2) {
            throw new DBLevelException(e2);
        }

        changed = true;

        // 2. create related userrole tables of application's userType
        Connection conn = DBPower.getConnection(DBPower.getDefaultDsName());
        try {
            conn.setAutoCommit(false);
            userType = Factory.getUserTypeManager().getUserType(userType.getName());
            TableMetadata userTable = userType.getUserMetadata().getMainTableMetadata();
            DBUtil.exec(conn, DBUtil.userRoleTableCreateSql(appName, userType.getName(), User.idFieldName,
                    getIdColumnType(userTable)));
            conn.commit();
        } catch (SQLException e) {
            try {
                conn.rollback();
            } catch (SQLException e1) {
                throw new DBLevelException(e1);
            }
            throw new DBLevelException(e);
        } finally {
            DBUtil.close(conn);
        }

        // 3. create reserved query
        QueryManager queryManager = Factory.getQueryManager(appName);
        queryManager.addReservedQuery(userType.getName());

        // 4. create reserved usercategory
        UserCategoryManager userCategoryManager = Factory.getUserCategoryManager(appName);
        userCategoryManager.addReservedUserCategory(locale);

        // 5. create reserved privilege
        PrivilegeManager privilegeManager = Factory.getPrivilegeManager(appName);
        privilegeManager.addReservedPrivilege(locale);

        // 6. create reserved roles
        RoleManager roleManager = Factory.getRoleManager(appName);
        roleManager.addReservedRole(locale);
    }

    private String getIdColumnType(TableMetadata userTable) {
        String idColumnType = null;
        FieldMetadata[] fields = userTable.getFields();
        for (int i = 0; i < fields.length; i++) {
            if (fields[i].getName().equals(User.idFieldName)) {
                idColumnType = fields[i].getSqlType();
                break;
            }
        }
        return idColumnType;
    }

    // private void addApplicationUserType(String appName, UserType userType,
    // Session session) {
    // ApplicationUserType appUserType = new ApplicationUserType();
    // ApplicationUserTypeId id = new ApplicationUserTypeId(appName, userType
    // .getName());
    // appUserType.setId(id);
    // appUserType.setUserMetadataStr(produceUserMetadataStr(userType
    // .getUserMetadata()));
    // session.save(appUserType);
    // }

    private String produceUserMetadataStr(UserMetadata userMetadata) {
        StringBuffer buf = new StringBuffer();
        FieldMetadata[] fields = userMetadata.getMainTableMetadata().getFields();
        for (int i = 0; i < fields.length; i++) {
            buf.append(fields[i].getColumnName() + " ");
        }
        return buf.toString();
    }

    private UserType extractUserType(ApplicationUserType appUserType) {
        String[] columNames = appUserType.getUserMetadataStr().split(" ");
        UserTypeManager userTypeManager = Factory.getUserTypeManager();
        UserType userType = userTypeManager.getUserTypeCopy(appUserType.getUserTypeName());
        FieldMetadata[] fields = userType.getUserMetadata().getMainTableMetadata().getFields();
        // find usertype infos which defined in usertype definition
        ArrayList newFields = new ArrayList();
        for (int i = 0; i < columNames.length; i++) {
            for (int j = 0; j < fields.length; j++) {
                if (columNames[i].equals(fields[j].getColumnName())) {
                    newFields.add(fields[j]);
                }
            }
        }
        userType.getUserMetadata().getMainTableMetadata()
                .setFields((FieldMetadata[]) newFields.toArray(new FieldMetadata[newFields.size()]));
        return userType;
    }

    public void deleteApplication(String name) {
        Application app = getApplication(name);

        // delete infos
        Connection conn = null;
        boolean autoCommit = true;
        try {
            conn = DBPower.getConnection(table.getId());
            autoCommit = conn.getAutoCommit();
            conn.setAutoCommit(false);

            ApplicationUserType appUserType = new ApplicationUserType();
            appUserType.setAppName(name);
            applicationUserTypeDeletor.delete(conn, appNameUserTypeTableWhereEmt, appUserType);

            Application hint = new Application();
            hint.setName(name);
            deletor.delete(conn, appNameWhereEmt, hint);

            conn.commit();
        } catch (SQLException e) {
            DBUtil.rollback(conn);
            throw new DBLevelException(e);
        } finally {
            DBUtil.setCommitMode(conn, autoCommit);
            DBUtil.close(conn);
        }

        changed = true;

        // delete tables
        deleteTablesForApp(app);

        // notify Factory
        org.ralasafe.Factory.applicationChanged(app.getName());
    }

    private void deleteTablesForApp(Application app) {
        // Name rule for role, privilegeand roleprivilege table is:
        // <appName>_role,<appName>_privilege and<appName>_roleprivilege
        String appName = app.getName();
        String sqlRole = DBUtil.roleTableDropSql(appName);
        String sqlPrivilege = DBUtil.privilegeTableDropSql(appName);
        String sqlRolePrivilege = DBUtil.rolePrivilegeTableDropSql(appName);

        // userrole tables
        ArrayList sqlUserRoles = new ArrayList();
        Iterator itr = app.getUserTypes().iterator();
        while (itr.hasNext()) {
            UserType userType = (UserType) itr.next();
            String sqlUserRole = DBUtil.userRoleTableDropSql(appName, userType.getName());
            sqlUserRoles.add(sqlUserRole);
        }

        String tableQueryDropSql = DBUtil.tableQueryDropSql(appName);
        String tableUserCategoryDropSql = DBUtil.tableUserCategoryDropSql(appName);
        String tableDicisionEntitlementDropSql = DBUtil.tableDecisionEntitlementDropSql(appName);
        String tableQueryEntitlementDropSql = DBUtil.tableQueryEntitlementDropSql(appName);
        String tableBusinessDataDropSql = DBUtil.tableBusinessDataDropSql(appName);

        Connection conn = DBPower.getConnection(DBPower.getDefaultDsName());
        try {
            conn.setAutoCommit(false);
            DBUtil.exec(conn, tableQueryDropSql);
            DBUtil.exec(conn, tableUserCategoryDropSql);
            DBUtil.exec(conn, tableDicisionEntitlementDropSql);
            DBUtil.exec(conn, tableQueryEntitlementDropSql);
            DBUtil.exec(conn, tableBusinessDataDropSql);

            itr = sqlUserRoles.iterator();
            while (itr.hasNext()) {
                String sql = (String) itr.next();
                try {
                    DBUtil.exec(conn, sql);
                } catch (SQLException e) {
                    logger.error("Error when delete table: " + sql);
                }
            }
            DBUtil.exec(conn, sqlRolePrivilege);
            DBUtil.exec(conn, sqlRole);
            DBUtil.exec(conn, sqlPrivilege);

            conn.commit();
        } catch (SQLException e) {
            try {
                conn.rollback();
            } catch (SQLException e1) {
                throw new DBLevelException(e1);
            }
            throw new DBLevelException(e);
        } finally {
            DBUtil.close(conn);
        }
    }

    public void deleteApplicationUserType(String appName, String userTypeName) {
        Connection conn = null;
        boolean autoCommit = true;
        try {
            conn = DBPower.getConnection(table.getId());
            autoCommit = conn.getAutoCommit();
            conn.setAutoCommit(false);

            // delete ApplicationUserType infos
            ApplicationUserType hint = new ApplicationUserType();
            hint.setAppName(appName);
            hint.setUserTypeName(userTypeName);

            applicationUserTypeDeletor.delete(conn, appNameUserTypeNameUserTypeTableWhereEmt, hint);

            // drop userrole tables
            DBUtil.exec(conn, DBUtil.userRoleTableDropSql(appName, userTypeName));

            conn.commit();
        } catch (SQLException e) {
            throw new DBLevelException(e);
        } finally {
            DBUtil.setCommitMode(conn, autoCommit);
            DBUtil.close(conn);
        }

        changed = true;
    }

    // private void deleteApplicationUserType(String appName, String
    // userTypeName,
    // Session session) {
    // session
    // .createQuery(
    // "delete ApplicationUserType where appName = :appName and userTypeName = :userTypeName")
    // .setString("appName", appName).setString("userTypeName",
    // userTypeName).executeUpdate();
    // }

    public Collection getAllApplications() {
        loadIntoMemory();
        return store.values();
    }

    public Application getApplication(String name) {
        loadIntoMemory();
        return (Application) store.get(name);
    }

    // private Application getApplication(String name, Session session) {
    // Application app = (Application) session.load(Application.class, name);
    // 
    // extractUserTypes(app, session);
    // return app;
    // }

    // private void extractUserTypes(Application app, Session session) {
    // Iterator itr = app.getApplicationUserTypes().iterator();
    // while (itr.hasNext()) {
    // ApplicationUserType appUserType = (ApplicationUserType) itr.next();
    // UserType userType = extractUserType(appUserType, session);
    // app.getUserTypes().add(userType);
    // }
    // }

    public void updateApplication(Application app) {
        loadIntoMemory();

        Application originalApplication = getApplication(app.getName());
        if (originalApplication == null) {
            return;
        }

        // get a copy of original application
        Collection origUserTypes = originalApplication.getUserTypes();
        Collection newUserTypes = app.getUserTypes();

        Connection conn = null;
        boolean autoCommit = true;
        try {
            conn = DBPower.getConnection(table.getId());
            autoCommit = conn.getAutoCommit();
            conn.setAutoCommit(false);

            // delete original app-usertype
            ApplicationUserType hintUserType = new ApplicationUserType();
            hintUserType.setAppName(app.getName());
            applicationUserTypeDeletor.delete(conn, appNameUserTypeTableWhereEmt, hintUserType);

            // save updated app-usertype relationship
            Collection userTypes = app.getUserTypes();
            if (userTypes != null && userTypes.size() > 0) {
                List appUserTypes = new ArrayList(userTypes.size());
                for (Iterator iter = userTypes.iterator(); iter.hasNext();) {
                    UserType userType = (UserType) iter.next();

                    ApplicationUserType appUserType = new ApplicationUserType();
                    appUserType.setAppName(app.getName());
                    appUserType.setUserTypeName(userType.getName());
                    String produceUserMetadataStr = produceUserMetadataStr(userType.getUserMetadata());
                    appUserType.setUserMetadataStr(produceUserMetadataStr);

                    appUserTypes.add(appUserType);
                }

                applicationUserTypeSaver.batchSave(conn, appUserTypes);
            }

            // update app info
            try {
                updator.updateByIdColumns(conn, app);
            } catch (EntityExistException e) {
                e.printStackTrace();
                throw new DBLevelException(e);
            }

            // update userrole tables
            // 1, find out which usertype(s) to be newly added and which to be deleted
            Iterator origItr = origUserTypes.iterator();
            while (origItr.hasNext()) {
                UserType origUserType = (UserType) origItr.next();
                Iterator newItr = newUserTypes.iterator();
                while (newItr.hasNext()) {
                    UserType newUserType = (UserType) newItr.next();
                    if (origUserType.getName().equals(newUserType.getName())) {
                        // this usertype is updated, move out
                        origItr.remove();
                        newItr.remove();
                    }
                }
            }

            Collection userTypesToBeDeleted = origUserTypes;
            Collection userTypesToBeAdded = newUserTypes;

            // 2, delete related userrole tables

            Iterator delItr = userTypesToBeDeleted.iterator();
            while (delItr.hasNext()) {
                UserType delUserType = (UserType) delItr.next();
                DBUtil.exec(conn, DBUtil.userRoleTableDropSql(app.getName(), delUserType.getName()));
            }

            // 3, create related userrole tables

            Iterator addItr = userTypesToBeAdded.iterator();
            while (addItr.hasNext()) {
                UserType delUserType = (UserType) addItr.next();
                delUserType = Factory.getUserTypeManager().getUserType(delUserType.getName());
                TableMetadata userTable = delUserType.getUserMetadata().getMainTableMetadata();
                DBUtil.exec(conn, DBUtil.userRoleTableCreateSql(app.getName(), delUserType.getName(),
                        User.idFieldName, getIdColumnType(userTable)));
            }

            conn.commit();
        } catch (SQLException e) {
            DBUtil.rollback(conn);
            throw new DBLevelException(e);
        } finally {
            DBUtil.setCommitMode(conn, autoCommit);
            DBUtil.close(conn);
        }

        changed = true;

        // notify Factory
        Factory.applicationChanged(app.getName());
    }

    public void updateApplicatonUserType(String appName, UserType userType) {
        Connection conn = null;
        boolean autoCommit = true;
        try {
            conn = DBPower.getConnection(table.getId());
            autoCommit = conn.getAutoCommit();
            conn.setAutoCommit(false);

            ApplicationUserType appUserType = new ApplicationUserType();
            appUserType.setAppName(appName);
            appUserType.setUserTypeName(userType.getName());
            String userMetadataStr = produceUserMetadataStr(userType.getUserMetadata());
            appUserType.setUserMetadataStr(userMetadataStr);

            // delete original app-usertype
            applicationUserTypeDeletor.delete(conn, appNameUserTypeNameUserTypeTableWhereEmt, appUserType);

            // save newly app-usertype
            try {
                applicationUserTypeSaver.save(conn, appUserType);
            } catch (EntityExistException e) {
                // should not happen
                e.printStackTrace();
                throw new DBLevelException(e);
            }

            conn.commit();
        } catch (SQLException e) {
            DBUtil.rollback(conn);
            throw new DBLevelException(e);
        } finally {
            DBUtil.setCommitMode(conn, autoCommit);
            DBUtil.close(conn);
        }

        changed = true;

        // notify Factory
        Factory.applicationUserTypeChanged(appName, userType.getName());
    }
}