| Implementing the security information storage interface | 
iServer provides a Storage interface to store and manage security information such as users, roles, and permissions. When implementing custom storage methods, you need to implement Storage as follows:
public class JsonStorage implements Storage {
...
}
For the implementation of the use of json file to store security information, this example will achieve:
The corresponding methods include:
| Functional category | Method | Description | 
| User | getUsers(int startIndex, int expectCount) getUser(String name) addUser(User toAdd) removeUsers(String[] names) alterUser(String name, User user) authenticate(String username, char[] password) | Get, add, delete, modify the user, and input user account information. | 
| Role | getRole(String name) getRoles(String username, Set<String> groups) getRoles(int startIndex, int expectCount) addRole(Role toAdd) removeRoles(String[] names) alterRole(String name, Role role) containOne(String[] roles, String theRole) insertRole(String roleName, String description) getRolePermissions(String[] names) setRolePermissions(String roleName, RolePermissions permission, ServiceBeanPermission[] permissions) | Get, add, delete, modify roles, insert role information in 
		 stored files, and get, set role authorization. | 
| Role group | getGroups(int startIndex, int expectCount) getGroups(String username) addUserGroup(UserGroup toAdd) removeUserGroups(String[] names) alterUserGroup(String name, UserGroup userGroup) insertGroups(String GroupName, String description) | Get, add, delete, modify the user group, and input user group 
		 information. | 
| Authority | getPublicServiceNames() getPermission(String user, Collection<? extends String> groups, Collection<? extends String> roles, Set<String> resourceIds) getInstanceAuthorisations() updateInstanceAuthorisation(String name, AuthorizeSetting authorizeSetting) insert(ServiceBeanPermission[] permissions) | Obtain the service list, obtain the authorization information of the user, obtain and update the authorization status of the service instance, and input the authority information. | 
Other methods that need to be implemented are:
    //Set the use of extended json storage method. 
    @Override
    public void resetStorageSetting(SecurityInfoStorageSetting setting) {
        if (!(setting instanceof JsonStorageSetting)) {
            throw new IllegalArgumentException("only recieve JsonStorageSetting");
        }
        this.init((JsonStorageSetting) setting);
    }
    //Reads the storage location of the configuration, and initializes a json file for storing security information 
    private void init(JsonStorageSetting setting) {
        String appFilePath = Tool.getApplicationPath(setting.outputDirectory);
        this.storageFile = new File(appFilePath, SECURITY_FILE_NAME);
        if (!this.storageFile.exists()) {
            if (!this.storageFile.getParentFile().exists()) {
                try {
                    FileUtils.forceMkdirParent(this.storageFile);
                } catch (IOException e) {
                    throw new IllegalStateException("failed to make storage directory ");
                }
            }
            try {
                this.storageFile.createNewFile();
            } catch (IOException e) {
                throw new IllegalStateException("failed to make storage file ");
            }
            this.addPredefinedRoles();
            this.addPredefinedGroups();
        } else {
            this.setMapContent();
        }
    }
    @SuppressWarnings("unchecked")
    private void setMapContent() {
        try {
            String json = FileUtils.readFileToString(this.storageFile, UTF_8);
            Map<string, ?=""> statusMap = FastJSONUtils.parse(json, HashMap.class);
            if (statusMap.containsKey(TAG_USERS)) {
                this.users = (Map<string, user="">) statusMap.get(TAG_USERS);
            }
            if (statusMap.containsKey(TAG_ROLES)) {
                this.roles = (Map<string, role="">) statusMap.get(TAG_ROLES);
            }
            if (statusMap.containsKey(TAG_USERGROUPS)) {
                this.userGroups = (Map<string, usergroup="">) statusMap.get(TAG_USERGROUPS);
            }
            if (statusMap.containsKey(TAG_ROLEPERMISSIONS)) {
                this.rolePermissions = (Map<string, rolepermissions="">) statusMap.get(TAG_ROLEPERMISSIONS);
            }
            if (statusMap.containsKey(TAG_AUTHORIZESETTING)) {
                this.authorizeSetting = (Map<string, authorizesetting="">) statusMap.get(TAG_AUTHORIZESETTING);
            }
            if (statusMap.containsKey(TAG_SERVICEBEANPERMISSION)) {
                this.serviceBeanPermission = (Map<string, servicebeanpermission="">) statusMap.get(TAG_SERVICEBEANPERMISSION);
            }
        } catch (IOException e) {
            throw new IllegalStateException("JsonStorage init failed ");
        }
    }
    //Make persistence for the state of the security information, including all users, roles, user groups and permissions to the storage file 
    private void persistenceToFile() {
        Map<string, object=""> status = new HashMap<string, object="">();
        status.put(TAG_USERS, users);
        status.put(TAG_ROLES, roles);
        status.put(TAG_USERGROUPS, userGroups);
        status.put(TAG_ROLEPERMISSIONS, rolePermissions);
        status.put(TAG_AUTHORIZESETTING, authorizeSetting);
        status.put(TAG_SERVICEBEANPERMISSION, serviceBeanPermission);
        String jsonStatus = FastJSONUtils.toFastJson(status);
        jsonStatus = jsonFormat(jsonStatus);
        try {
            FileUtils.write(this.storageFile, jsonStatus, UTF_8);
        } catch (IOException e) {
            System.out.println("fail to persistence to " + this.storageFile.getAbsolutePath());
        }
    }
    //batch query. 
    private 	 QueryResult	 batchGet(int startIndex, int expectCount, List	 list) {
        int actualCount = expectCount;
        int size = list.size();
        if (expectCount > size - startIndex || expectCount == 0) {
            actualCount = size - startIndex;
        }
        List	 founds = new ArrayList	();
        if (startIndex <= size)="" {="" int="" index="startIndex;" findcount="0;" while="" (findcount="" <="" actualcount)="" founds.add(list.get(index));="" index++;="" findcount++;="" }="" queryresult<t=""> queryResult = new QueryResult	();
        queryResult.records = founds;
        queryResult.totalCount = size;
        return queryResult;
    }
    //Parse the role authorization information to convert it to a storeable string. 
    private static class ResolvingRolePermission {
        List<string> allowedCom = new LinkedList<string>();
        List<string> deniedCom = new LinkedList<string>();
        List<string> allowedService = new LinkedList<string>();
        List<string> deniedService = new LinkedList<string>();
        boolean isPublisher = false;
        public RolePermissions toRolePermission() {
            RolePermissions result = new RolePermissions();
            result.publishEnabled = isPublisher;
            result.componentManagerPermissions = new MixedPermissions();
            result.componentManagerPermissions.denied = toArray(deniedCom);
            result.componentManagerPermissions.permitted = toArray(allowedCom);
            result.instanceAccessPermissions = new MixedPermissions();
            result.instanceAccessPermissions.denied = toArray(deniedService);
            result.instanceAccessPermissions.permitted = toArray(allowedService);
            return result;
        }
        void add(int resourceType, String resourceName, int perm) {
            List<string> list = null;
            switch (resourceType) {
            case RESOURCE_TYPE_PUBLISH: {
                isPublisher = true;
                break;
            }
            case RESOURCE_TYPE_COMPONENT: {
                list = isAllowManageComponent(perm) ? allowedCom : deniedCom;
                break;
            }
            case RESOURCE_TYPE_SERVICE: {
                list = isAllowAccessService(perm) ? allowedService : deniedService;
                break;
            }
            }
            if (list != null) {
                list.add(resourceName);
            }
        }
    }
    private static String[] toArray(List<string> list) {
        return list.isEmpty() ? ArrayUtils.EMPTY_STRING_ARRAY : list.toArray(new String[list.size()]);
    }
The complete extended sample class is as follows:
NationalCacheStandardTileSourceInfo.java
package com.supermap.services.security.storages;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_ADMIN;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_PORTAL_USER;
import static com.supermap.services.rest.resources.SecurityManageResource.ROLE_DESCRIPTION_PUBLISHER;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.GROUP;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_COMPONENT;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_PUBLISH;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.RESOURCE_TYPE_SERVICE;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.ROLE;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.USER;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.isAllowAccessService;
import static com.supermap.services.security.DefaultServiceBeanPermissionDAOConstants.isAllowManageComponent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.credential.PasswordService;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.common.collect.Lists;
import com.supermap.server.config.JsonStorageSetting;
import com.supermap.server.config.SecurityInfoStorageSetting;
import com.supermap.services.components.commontypes.AuthorizeSetting;
import com.supermap.services.components.commontypes.AuthorizeType;
import com.supermap.services.rest.resources.SecurityManageResource;
import com.supermap.services.security.AuthenticateUsernamePasswordResult;
import com.supermap.services.security.AuthenticateUsernamePasswordResultType;
import com.supermap.services.security.MixedPermissions;
import com.supermap.services.security.QueryResult;
import com.supermap.services.security.Role;
import com.supermap.services.security.RolePermissions;
import com.supermap.services.security.SecurityConstants;
import com.supermap.services.security.ServiceBeanPermission;
import com.supermap.services.security.User;
import com.supermap.services.security.UserGroup;
import com.supermap.services.util.FastJSONUtils;
import com.supermap.services.util.IterableUtil;
import com.supermap.services.util.ProductTypeUtil;
import com.supermap.services.util.Tool;
import com.supermap.services.util.TypedResourceManager;
public class JsonStorage implements Storage {
    private static final String SECURITY_FILE_NAME = "security.json";
    private static final String UTF_8 = "utf-8";
    private static final String TAG_USERS = "users";
    private static final String TAG_ROLES = "roles";
    private static final String TAG_USERGROUPS = "userGroups";
    private static final String TAG_ROLEPERMISSIONS = "rolePermissions";
    private static final String TAG_AUTHORIZESETTING = "authorizeSetting";
    private static final String TAG_SERVICEBEANPERMISSION = "serviceBeanPermission";
    private File storageFile;
    private Map<String, Role> roles = new HashMap<String, Role>();
    private Map<String, User> users = new HashMap<String, User>();
    private Map<String, UserGroup> userGroups = new HashMap<String, UserGroup>();
    private Map<String, RolePermissions> rolePermissions = new HashMap<String, RolePermissions>();
    private Map<String, ServiceBeanPermission> serviceBeanPermission = new HashMap<String, ServiceBeanPermission>();
    private Map<String, AuthorizeSetting> authorizeSetting = new HashMap<String, AuthorizeSetting>();
    private Set<String> publicServiceNames = Collections.emptySet();
    private PasswordService passwordService;
    private static TypedResourceManager<SecurityManageResource> resource = new TypedResourceManager<SecurityManageResource>(SecurityManageResource.class);
    private static final Collection<String> PUBLISHER_PERMISSIONS = Collections.unmodifiableList(Arrays.asList(StringUtils.split(
            "interface:*,instance:*,component:*,componentset:*,provider:*,providerset:*,publish", ',')));
    //Set using the extended json storage method. 
    @Override
    public void resetStorageSetting(SecurityInfoStorageSetting setting) {
        if (!(setting instanceof JsonStorageSetting)) {
            throw new IllegalArgumentException("only recieve JsonStorageSetting");
        }
        this.init((JsonStorageSetting) setting);
    }
    //Read the storage location of the configuration, and initialize a json file for storing security information.  
    private void init(JsonStorageSetting setting) {
        String appFilePath = Tool.getApplicationPath(setting.outputDirectory);
        this.storageFile = new File(appFilePath, SECURITY_FILE_NAME);
        if (!this.storageFile.exists()) {
            if (!this.storageFile.getParentFile().exists()) {
                try {
                    FileUtils.forceMkdirParent(this.storageFile);
                } catch (IOException e) {
                    throw new IllegalStateException("failed to make storage directory ");
                }
            }
            try {
                this.storageFile.createNewFile();
            } catch (IOException e) {
                throw new IllegalStateException("failed to make storage file ");
            }
            this.addPredefinedRoles();
            this.addPredefinedGroups();
        } else {
            this.setMapContent();
        }
    }
    @SuppressWarnings("unchecked")
    private void setMapContent() {
        try {
            String json = FileUtils.readFileToString(this.storageFile, UTF_8);
            Map<String, ?> statusMap = FastJSONUtils.parse(json, HashMap.class);
            if (statusMap.containsKey(TAG_USERS)) {
                this.users = (Map<String, User>) statusMap.get(TAG_USERS);
            }
            if (statusMap.containsKey(TAG_ROLES)) {
                this.roles = (Map<String, Role>) statusMap.get(TAG_ROLES);
            }
            if (statusMap.containsKey(TAG_USERGROUPS)) {
                this.userGroups = (Map<String, UserGroup>) statusMap.get(TAG_USERGROUPS);
            }
            if (statusMap.containsKey(TAG_ROLEPERMISSIONS)) {
                this.rolePermissions = (Map<String, RolePermissions>) statusMap.get(TAG_ROLEPERMISSIONS);
            }
            if (statusMap.containsKey(TAG_AUTHORIZESETTING)) {
                this.authorizeSetting = (Map<String, AuthorizeSetting>) statusMap.get(TAG_AUTHORIZESETTING);
            }
            if (statusMap.containsKey(TAG_SERVICEBEANPERMISSION)) {
                this.serviceBeanPermission = (Map<String, ServiceBeanPermission>) statusMap.get(TAG_SERVICEBEANPERMISSION);
            }
        } catch (IOException e) {
            throw new IllegalStateException("JsonStorage init failed ");
        }
    }
    //Add predefined role, including "SYSTEM,ADMIN,PORTAL_USER,PUBLISHER". 
    private void addPredefinedRoles() {
        insertRole(SecurityConstants.ROLE_SYSTEM, StringUtils.EMPTY);
        insertRole(SecurityConstants.ROLE_ADMIN, resource.message(ROLE_DESCRIPTION_ADMIN));
        if (ProductTypeUtil.isPortal()) {
            insertRole(SecurityConstants.ROLE_PORTAL_USER, resource.message(ROLE_DESCRIPTION_PORTAL_USER));
        }
        insertRole(SecurityConstants.ROLE_PUBLISHER, resource.message(ROLE_DESCRIPTION_PUBLISHER));
        this.persistenceToFile();
    }
	//Add predefined user group. 
    private void addPredefinedGroups() {
        insertGroups(SecurityConstants.GROUP_THIRD_PART_AUTHORIZED, StringUtils.EMPTY);
        insertGroups(SecurityConstants.GROUP_LDAP_AUTHORIZED, StringUtils.EMPTY);
        this.persistenceToFile();
    }
    //Make persistence for the state of the security information, including all users, roles, user groups and permissions to the storage file. 
    private void persistenceToFile() {
        Map<String, Object> status = new HashMap<String, Object>();
        status.put(TAG_USERS, users);
        status.put(TAG_ROLES, roles);
        status.put(TAG_USERGROUPS, userGroups);
        status.put(TAG_ROLEPERMISSIONS, rolePermissions);
        status.put(TAG_AUTHORIZESETTING, authorizeSetting);
        status.put(TAG_SERVICEBEANPERMISSION, serviceBeanPermission);
        String jsonStatus = FastJSONUtils.toFastJson(status);
        jsonStatus = jsonFormat(jsonStatus);
        try {
            FileUtils.write(this.storageFile, jsonStatus, UTF_8);
        } catch (IOException e) {
            System.out.println("fail to persistence to " + this.storageFile.getAbsolutePath());
        }
    }
    //Format JSON. 
    private String jsonFormat(String jsonStatus) {
        try {
            JSONObject jsonObject = new JSONObject(jsonStatus);
            return jsonObject.toString(4);
        } catch (JSONException e1) {
            // will not execute here
            return "";
        }
    }
    //Add role. 
    private void insertRole(String roleName, String description) {
        Role role = new Role();
        role.name = roleName;
        role.description = description;
        this.roles.put(roleName, role);
    }
    //Add user group. 
    private void insertGroups(String GroupName, String description) {
        UserGroup userGroup = new UserGroup();
        userGroup.name = GroupName;
        userGroup.description = description;
        this.userGroups.put(GroupName, userGroup);
    }
    //Retrieve user lists based on roles. 
    @Override
    public QueryResult<User> getUsers(int startIndex, int expectCount) {
        ArrayList<User> userList = new ArrayList<User>();
        List<String> ownRoles = new ArrayList<String>();
        for (User user : this.users.values()) {
            user.ownRoles = ownRoles.toArray(new String[ownRoles.size()]);
            userList.add(user);
        }
        return batchGet(startIndex, expectCount, userList);
    }
    //Get individual users based on user name.  
    @Override
    public User getUser(String name) {
        return this.users.get(name);
    }
    //Add a role. 
    @Override
    public void addUser(User toAdd) {
        if (this.users.containsKey(toAdd.name)) {
            throw new IllegalArgumentException("user " + toAdd.name + " exists yet");
        }
        this.users.put(toAdd.name, toAdd);
        for (Role role : this.roles.values()) {
            boolean containRoleInUser = containOne(toAdd.roles, role.name);
            boolean containUserInRole = containOne(role.users, toAdd.name);
            if (containRoleInUser && !containUserInRole) {
                // The current user is associated with a new role. 
                role.users = ArrayUtils.add(role.users, toAdd.name);
            }
        }
        for (UserGroup userGroup : this.userGroups.values()) {
            String userGroupName = userGroup.name;
            boolean containUserInUserGroup = containOne(userGroup.users, toAdd.name);
            boolean containUserGroupInUser = containOne(toAdd.userGroups, userGroupName);
            if (!containUserInUserGroup && containUserGroupInUser) {
                // The current user is associated with a new user group. 
                userGroup.users = ArrayUtils.add(userGroup.users, toAdd.name);
            }
        }
        this.persistenceToFile();
    }
    //Delete users in batch. 
    @Override
    public void removeUsers(String[] names) {
        for (String name : names) {
            User user = this.users.get(name);
            this.users.remove(name);
            for (Role role : this.roles.values()) {
                boolean containUserInRole = containOne(role.users, user.name);
                if (containUserInRole) {
                    // The current user has unlinked a role. 
                    role.users = ArrayUtils.removeElement(role.users, user.name);
                }
            }
            for (UserGroup userGroup : this.userGroups.values()) {
                boolean containUserInGroup = containOne(userGroup.users, user.name);
                if (containUserInGroup) {
                    // The current user has unlinked a user group. 
                    userGroup.users = ArrayUtils.removeElement(userGroup.users, user.name);
                }
            }
        }
        this.persistenceToFile();
    }
    //Modify user information, including increasing / decreasing the associated roles, increasing / decreasing associated user groups. 
    @Override
    public void alterUser(String name, User user) {
        this.users.put(name, user);
        for (Role role : this.roles.values()) {
            boolean containRoleInUser = containOne(user.roles, role.name);
            boolean containUserInRole = containOne(role.users, user.name);
            if (containRoleInUser && !containUserInRole) {
                // The current user is associated with a new role. 
                role.users = ArrayUtils.add(role.users, user.name);
            } else if (!containRoleInUser && containUserInRole) {
                // The current user has unlinked a role. 
                role.users = ArrayUtils.removeElement(role.users, user.name);
            }
        }
        for (UserGroup userGroup : this.userGroups.values()) {
            String userGroupName = userGroup.name;
            boolean containRoleInUser = containOne(userGroup.users, user.name);
            boolean containUserInRole = containOne(user.userGroups, userGroupName);
            if (containRoleInUser && !containUserInRole) {
                // The current user has unlinked a role group. 
                userGroup.users = ArrayUtils.removeElement(userGroup.users, user.name);
            } else if (!containRoleInUser && containUserInRole) {
                // The current user is associated with a new user group.  
                userGroup.roles = ArrayUtils.add(userGroup.users, userGroupName);
            }
        }
        this.persistenceToFile();
    }
    //Add user group and associated role information. 
    @Override
    public void addUserGroup(UserGroup toAdd) {
        if (this.userGroups.containsKey(toAdd.name)) {
            throw new IllegalArgumentException("userGroups " + toAdd.name + " exists yet");
        }
        this.userGroups.put(toAdd.name, toAdd);
        for (Role role : this.roles.values()) {
            boolean containRoleInGroup = containOne(toAdd.roles, role.name);
            boolean containGroupInRole = containOne(role.userGroups, toAdd.name);
            if (containRoleInGroup && !containGroupInRole) {
                // The current user is associated with a new role. 
                role.userGroups = ArrayUtils.add(role.userGroups, toAdd.name);
            }
        }
        for (User user : this.users.values()) {
            boolean containUserInGroup = containOne(toAdd.users, user.name);
            boolean containGroupInUser = containOne(user.userGroups, toAdd.name);
            if (containUserInGroup && !containGroupInUser) {
                // The current user group is associated with a new user. 
                user.userGroups = ArrayUtils.add(user.userGroups, toAdd.name);
            }
        }
        this.persistenceToFile();
    }
    //Modify user group information, including increasing / decreasing the associated roles, increasing / decreasing associated user groups. 
    @Override
    public void alterUserGroup(String name, UserGroup userGroup) {
        this.userGroups.put(name, userGroup);
        for (User user : this.users.values()) {
            String userName = user.name;
            boolean containGroupInUser = containOne(user.userGroups, userGroup.name);
            boolean containUserInGroup = containOne(userGroup.users, userName);
            if (containGroupInUser && !containUserInGroup) {
                //  The current user group has unlinked a role. 
                user.userGroups = ArrayUtils.removeElement(user.userGroups, userGroup.name);
            } else if (!containGroupInUser && containUserInGroup) {
                // The current user is associated with a new user. 
                user.userGroups = ArrayUtils.add(user.userGroups, userGroup.name);
            }
        }
        for (Role role : this.roles.values()) {
            String roleName = role.name;
            boolean containGroupInRole = containOne(role.userGroups, userGroup.name);
            boolean containRoleInGroup = containOne(userGroup.roles, roleName);
            if (containGroupInRole && !containRoleInGroup) {
                // The current user group is associated with a new role. 
                role.userGroups = ArrayUtils.removeElement(role.userGroups, userGroup.name);
            } else if (!containGroupInRole && containRoleInGroup) {
                // The current user group is unlinked with a new role. 
                role.userGroups = ArrayUtils.add(role.userGroups, userGroup.name);
            }
        }
        this.persistenceToFile();
    }
    //Delete the user group. 
    @Override
    public void removeUserGroups(String[] names) {
        for (String name : names) {
            UserGroup userGroup = this.userGroups.get(name);
            this.userGroups.remove(name);
            for (Role role : this.roles.values()) {
                boolean containRoleInGroup = containOne(role.userGroups, userGroup.name);
                if (containRoleInGroup) {
                    //  The current user group is unlinked with a new role.  
                    role.userGroups = ArrayUtils.removeElement(role.userGroups, userGroup.name);
                }
            }
            for (User user : this.users.values()) {
                boolean containUserInGroup = containOne(user.userGroups, userGroup.name);
                if (containUserInGroup) {
                    //  The current user group is unlinked with a new user. 
                    user.userGroups = ArrayUtils.removeElement(user.userGroups, userGroup.name);
                }
            }
        }
        this.persistenceToFile();
    }
    //Get user group. 
    @Override
    public QueryResult<UserGroup> getGroups(int startIndex, int expectCount) {
        ArrayList<UserGroup> userGroupList = new ArrayList<UserGroup>();
        for (UserGroup userGroup : this.userGroups.values()) {
            userGroupList.add(userGroup);
        }
        return this.batchGet(startIndex, expectCount, userGroupList);
    }
    //Add role. 
    @Override
    public void addRole(Role toAdd) {
        if (this.roles.containsKey(toAdd.name)) {
            throw new IllegalArgumentException("roles" + toAdd.name + " exists yet");
        }
        this.roles.put(toAdd.name, toAdd);
        for (User user : this.users.values()) {
            boolean containUserInRole = containOne(toAdd.users, user.name);
            boolean containRoleInUser = containOne(user.roles, toAdd.name);
            if (containUserInRole && !containRoleInUser) {
                // The current role is associated with a new user. 
                user.roles = ArrayUtils.add(user.roles, toAdd.name);
            }
        }
        for (UserGroup userGroup : this.userGroups.values()) {
            String userGroupName = userGroup.name;
            boolean containGroupInRole = containOne(toAdd.userGroups, userGroupName);
            boolean containRoleInGroup = containOne(userGroup.roles, toAdd.name);
            if (containGroupInRole && !containRoleInGroup) {
                // The current role is associated with a new user group. 
                userGroup.roles = ArrayUtils.add(userGroup.roles, toAdd.name);
            }
        }
        this.persistenceToFile();
    }
    //Modify roles. 
    @Override
    public void alterRole(String name, Role role) {
        this.roles.put(name, role);
        String roleName = role.name;
        // Modify the associated user information
        for (User user : this.users.values()) {
            String userName = user.name;
            boolean containRoleInUser = containOne(user.roles, roleName);
            boolean containUserInRole = containOne(role.users, userName);
            if (containRoleInUser && !containUserInRole) {
                // The current role has unlinked a user.  
                user.roles = ArrayUtils.removeElement(user.roles, roleName);
            } else if (!containRoleInUser && containUserInRole) {
                //  The current role is associated with a new user.  
                user.roles = ArrayUtils.add(user.roles, roleName);
            }
        }
        for (UserGroup userGroup : this.userGroups.values()) {
            String userGroupName = userGroup.name;
            boolean containRoleInUser = containOne(userGroup.roles, roleName);
            boolean containUserInRole = containOne(role.userGroups, userGroupName);
            if (containRoleInUser && !containUserInRole) {
                //  The current user has unlinked a role group.  
                userGroup.roles = ArrayUtils.removeElement(userGroup.roles, roleName);
            } else if (!containRoleInUser && containUserInRole) {
                // The current role is associated with a new user group.  
                userGroup.roles = ArrayUtils.add(userGroup.roles, roleName);
            }
        }
        this.persistenceToFile();
    }
    //Delete roles in batch. 
    @Override
    public void removeRoles(String[] names) {
        for (String name : names) {
            Role role = this.roles.get(name);
            this.roles.remove(name);
            for (User user : this.users.values()) {
                boolean containRoleInUser = containOne(user.roles, role.name);
                if (containRoleInUser) {
                    // The current role has unlinked a user.  
                    user.roles = ArrayUtils.removeElement(user.roles, role.name);
                }
            }
            for (UserGroup userGroup : this.userGroups.values()) {
                boolean containRoleInGroup= containOne(userGroup.roles, role.name);
                if (containRoleInGroup) {
                    //The current role has unlinked a user group.   
                    userGroup.roles = ArrayUtils.removeElement(userGroup.roles, role.name);
                }
            }
        }
        this.persistenceToFile();
    }
    //Get a role by the role name. 
    @Override
    public Role getRole(String name) {
        return this.roles.get(name);
    }
    //Get the user group list. 
    @Override
    public Set<String> getGroups(String username) {
        Set<String> result = new LinkedHashSet<String>();
        if (!StringUtils.isEmpty(username)) {
            User user = this.users.get(username);
            if (user != null && !ArrayUtils.isEmpty(user.userGroups)) {
                result.addAll(Lists.asList(null, user.userGroups));
            }
        }
        return result;
    }
    //Get the role list associated with a user name. 
    @Override
    public Set<String> getRoles(String username, Set<String> groups) {
        Set<String> result = new LinkedHashSet<String>();
        if (!StringUtils.isEmpty(username)) {
            User user = this.users.get(username);
            if (user != null && !ArrayUtils.isEmpty(user.roles)) {
                result.addAll(Lists.asList(null, user.roles));
            }
        }
        if (groups != null && !groups.isEmpty()) {
            for (String groupName : groups) {
                if (StringUtils.isEmpty(groupName)) {
                    continue;
                }
                UserGroup ug = this.userGroups.get(groupName);
                if (ug != null && !ArrayUtils.isEmpty(ug.roles)) {
                    result.addAll(Lists.asList(null, ug.roles));
                }
            }
        }
        return result;
    }
    //Gets the list of roles based on the number of indexes and quantities.  
    @Override
    public QueryResult<Role> getRoles(int startIndex, int expectCount) {
        ArrayList<Role> roleList = new ArrayList<Role>();
        for (Role role : this.roles.values()) {
            roleList.add(role);
        }
        return this.batchGet(startIndex, expectCount, roleList);
    }
    //Gets all the list of services that are published. 
    @Override
    public Set<String> getPublicServiceNames() {
        return publicServiceNames;
    }
    //Set permissions for roles. 
    @Override
    public void setRolePermissions(String roleName, RolePermissions permission, ServiceBeanPermission[] permissions) {
        if (permission == null) {
            return;
        }
        final Set<ServiceBeanPermission> records = new LinkedHashSet<ServiceBeanPermission>();
        if (permission.publishEnabled) {
            records.add(new ServiceBeanPermission().publish().role(roleName));
            records.add(new ServiceBeanPermission().allowViewAllInterface().role(roleName));
        }
        MixedPermissions mngPermission = permission.componentManagerPermissions;
        if (mngPermission != null) {
            if (mngPermission.permitted != null) {
                for (String com : mngPermission.permitted) {
                    records.add(new ServiceBeanPermission().allowComponent(com).role(roleName));
                }
            }
            if (mngPermission.denied != null) {
                for (String com : mngPermission.denied) {
                    records.add(new ServiceBeanPermission().denyComponent(com).role(roleName));
                }
            }
        }
        final List<String> deniedServices = new ArrayList<String>();
        MixedPermissions accessPermission = permission.instanceAccessPermissions;
        if (accessPermission != null) {
            if (accessPermission.permitted != null) {
                for (String service : accessPermission.permitted) {
                    records.add(new ServiceBeanPermission().allowAccessService(service).role(roleName));
                }
            }
            if (accessPermission.denied != null) {
                for (String service : accessPermission.denied) {
                    records.add(new ServiceBeanPermission().denyAccessService(service).role(roleName));
                    deniedServices.add(service);
                }
            }
        }
        if (!ArrayUtils.isEmpty(permissions)) {
            records.addAll(Arrays.asList(permissions));
        }
        for (ServiceBeanPermission serbeanPermission : records) {
            this.serviceBeanPermission.put(serbeanPermission.principal, serbeanPermission);
        }
        this.persistenceToFile();
    }
    //Get the permissions of a user. 
    @Override
    public Set<String> getPermission(String user, Collection<? extends String> groups, Collection<? extends String> roles, Set<String> resourceIds) {
        Set<String> result = new LinkedHashSet<String>();
        int initialCapacity = 1;
        initialCapacity += groups == null ? 0 : groups.size();
        initialCapacity += roles == null ? 0 : roles.size();
        final Set<String> principals = new LinkedHashSet<String>(initialCapacity);
        if (StringUtils.isNotEmpty(user)) {
            principals.add(USER + user);
        }
        add(principals, groups, GROUP);
        add(principals, roles, ROLE);
        if (principals.isEmpty()) {
            return Collections.emptySet();
        }
        final boolean isPublisher = principals.remove("ROLE^PUBLISHER");
        if (isPublisher) {
            result.addAll(PUBLISHER_PERMISSIONS);
        } else {
            for (String principal : principals) {
                ServiceBeanPermission sp = this.serviceBeanPermission.get(principal);
                if (sp == null) {
                    continue;
                }
                result.add(sp.shiroPermission);
            }
        }
        return result;
    }
    //Get the permissions of a role. 
    @Override
    public Map<String, RolePermissions> getRolePermissions(String[] names) {
        if (ArrayUtils.isEmpty(names)) {
            return Collections.emptyMap();
        }
        String[] roles = new String[names.length];
        for (int i = 0; i < roles.length; i++) {
            roles[i] = ROLE + names[i];
        }
        List<ServiceBeanPermission> sqlResult = new ArrayList<ServiceBeanPermission>();
        for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
            int[] a = new int[] { RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, RESOURCE_TYPE_PUBLISH };
            if (ArrayUtils.contains(roles, serviceBeanPer) && serviceBeanPer.principaltype == 2 && ArrayUtils.contains(a, serviceBeanPer.resourcetype)) {
                sqlResult.add(serviceBeanPer);
            }
        }
        Map<String, ResolvingRolePermission> resolvingResult = new HashMap<String, ResolvingRolePermission>();
        for (ServiceBeanPermission serviceBean : sqlResult) {
            if (!StringUtils.startsWith(serviceBean.principal, ROLE)) {
                continue;
            }
            String roleName = serviceBean.principal.substring(ROLE.length());
            ResolvingRolePermission rolePermission = resolvingResult.get(roleName);
            if (rolePermission == null) {
                rolePermission = new ResolvingRolePermission();
                resolvingResult.put(roleName, rolePermission);
            }
            rolePermission.add(serviceBean.resourcetype, serviceBean.resource, serviceBean.permission);
        }
        final Map<String, RolePermissions> result = new HashMap<String, RolePermissions>();
        IterableUtil.iterate(resolvingResult.entrySet(), new IterableUtil.Visitor<Entry<String, ResolvingRolePermission>>() {
            @Override
            public boolean visit(Entry<String, ResolvingRolePermission> element) {
                result.put(element.getKey(), element.getValue().toRolePermission());
                return false;
            }
        });
        return result;
    }
    //Update the authorization information of a service instance. 
    @Override
    public void updateInstanceAuthorisation(String name, AuthorizeSetting authorizeSetting) {
        final Set<ServiceBeanPermission> records = new LinkedHashSet<ServiceBeanPermission>();
        if (AuthorizeType.PUBLIC.equals(authorizeSetting.type)) {
            records.add(new ServiceBeanPermission().role(SecurityConstants.ROLE_EVERYONE).allowAccessService(name));
        } else if (AuthorizeType.AUTHENTICATED.equals(authorizeSetting.type)) {
            records.add(new ServiceBeanPermission().role(SecurityConstants.ROLE_USER).allowAccessService(name));
        }
        if (!ArrayUtils.isEmpty(authorizeSetting.deniedRoles)) {
            for (String role : authorizeSetting.deniedRoles) {
                if (StringUtils.isEmpty(role)) {
                    continue;
                }
                records.add(new ServiceBeanPermission().role(role).denyAccessService(name));
            }
        }
        if (!ArrayUtils.isEmpty(authorizeSetting.permittedRoles)) {
            for (String role : authorizeSetting.permittedRoles) {
                if (StringUtils.isEmpty(role)) {
                    continue;
                }
                records.add(new ServiceBeanPermission().role(role).allowAccessService(name));
            }
        }
        int[] a = new int[] {RESOURCE_TYPE_SERVICE};
        for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
            if (ArrayUtils.contains(a, serviceBeanPer.resourcetype)&&serviceBeanPer.resource.equals(name)) {
                this.serviceBeanPermission.remove(serviceBeanPer.principal);
            }
        }
        for (ServiceBeanPermission record : records) {
           this.serviceBeanPermission.put(record.principal, record);
        }
        this.persistenceToFile();
    }
    //Obtain authorization information for service instances. 
    @Override
    public Map<String, AuthorizeSetting> getInstanceAuthorisations() {
        int[] a = new int[] {RESOURCE_TYPE_SERVICE};
        List<ServiceBeanPermission> serviceBeanResults = new ArrayList<ServiceBeanPermission>();
        for (ServiceBeanPermission serviceBeanPer : this.serviceBeanPermission.values()) {
            if (ArrayUtils.contains(a, serviceBeanPer.resourcetype)) {
                serviceBeanResults.add(serviceBeanPer);
            }
        }
        Map<String, QueryingAuthorizeSetting> querying = new HashMap<String, QueryingAuthorizeSetting>();
        for (ServiceBeanPermission serviceBean : serviceBeanResults) {
            String instanceName = serviceBean.resource;
            QueryingAuthorizeSetting setting = querying.get(instanceName);
            if (setting == null) {
                setting = new QueryingAuthorizeSetting();
                querying.put(instanceName, setting);
            }
            int permission = serviceBean.permission;
            String role = serviceBean.principal;
            if (isAllowAccessService(permission)) {
                setting.allowedRole(role);
            } else {
                setting.deniedRole(role);
            }
        }
        if (querying.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, AuthorizeSetting> result = new HashMap<String, AuthorizeSetting>(querying.size());
        Iterator<Entry<String, QueryingAuthorizeSetting>> it = querying.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, QueryingAuthorizeSetting> entry = it.next();
            result.put(entry.getKey(), entry.getValue().toAuthorizeSetting());
        }
        return result;
    }
    @Override
    public void grantUser(String username, RolePermissions permission) {
    }
    //Add a permission message. 
    @Override
    public void insert(ServiceBeanPermission[] permissions) {
        if (ArrayUtils.isEmpty(permissions)) {
            return;
        }
        for (ServiceBeanPermission permission : permissions) {
            this.serviceBeanPermission.put(permission.principal, permission);
        }
        this.persistenceToFile();
    }
    @Override
    public void setPasswordService(PasswordService value) {
        this.passwordService = value;
    }
    //Store the user's account information. 
    @Override
    public AuthenticateUsernamePasswordResult authenticate(String username, char[] password) {
        User user = this.getUser(username);
        AuthenticateUsernamePasswordResult result = new AuthenticateUsernamePasswordResult();
        if (user != null) {
            result.type = this.passwordService.passwordsMatch(password, user.password) ? AuthenticateUsernamePasswordResultType.VALIED
                    : AuthenticateUsernamePasswordResultType.INVALID;
        }
        return result;
    }
    private void add(Set<String> toAddIn, Collection<? extends String> toAdd, String prefix) {
        if (toAdd == null || toAdd.isEmpty()) {
            return;
        }
        for (String str : toAdd) {
            toAddIn.add(prefix + str);
        }
    }
    //Query whether there is a role. 
    private boolean containOne(String[] roles, String theRole) {
        if (ArrayUtils.isEmpty(roles)) {
            return false;
        }
        return ArrayUtils.contains(roles, theRole);
    }
    //Batch query. 
    private <T> QueryResult<T> batchGet(int startIndex, int expectCount, List<T> list) {
        int actualCount = expectCount;
        int size = list.size();
        if (expectCount > size - startIndex || expectCount == 0) {
            actualCount = size - startIndex;
        }
        List<T> founds = new ArrayList<T>();
        if (startIndex <= size) {
            int index = startIndex;
            int findCount = 0;
            while (findCount < actualCount) {
                founds.add(list.get(index));
                index++;
                findCount++;
            }
        }
        QueryResult<T> queryResult = new QueryResult<T>();
        queryResult.records = founds;
        queryResult.totalCount = size;
        return queryResult;
    }
    //Parse the role authorization information to convert it to a storeable string. 
    private static class ResolvingRolePermission {
        List<String> allowedCom = new LinkedList<String>();
        List<String> deniedCom = new LinkedList<String>();
        List<String> allowedService = new LinkedList<String>();
        List<String> deniedService = new LinkedList<String>();
        boolean isPublisher = false;
        public RolePermissions toRolePermission() {
            RolePermissions result = new RolePermissions();
            result.publishEnabled = isPublisher;
            result.componentManagerPermissions = new MixedPermissions();
            result.componentManagerPermissions.denied = toArray(deniedCom);
            result.componentManagerPermissions.permitted = toArray(allowedCom);
            result.instanceAccessPermissions = new MixedPermissions();
            result.instanceAccessPermissions.denied = toArray(deniedService);
            result.instanceAccessPermissions.permitted = toArray(allowedService);
            return result;
        }
        void add(int resourceType, String resourceName, int perm) {
            List<String> list = null;
            switch (resourceType) {
            case RESOURCE_TYPE_PUBLISH: {
                isPublisher = true;
                break;
            }
            case RESOURCE_TYPE_COMPONENT: {
                list = isAllowManageComponent(perm) ? allowedCom : deniedCom;
                break;
            }
            case RESOURCE_TYPE_SERVICE: {
                list = isAllowAccessService(perm) ? allowedService : deniedService;
                break;
            }
            }
            if (list != null) {
                list.add(resourceName);
            }
        }
    }
    private static String[] toArray(List<String> list) {
        return list.isEmpty() ? ArrayUtils.EMPTY_STRING_ARRAY : list.toArray(new String[list.size()]);
    }
    static class QueryingAuthorizeSetting {
        AuthorizeType type;
        Set<String> deniedRoles = new LinkedHashSet<String>();
        Set<String> allowedRoles = new LinkedHashSet<String>();
        QueryingAuthorizeSetting allowedRole(String value) {
            String role = value.substring(ROLE.length());
            if (type == null && SecurityConstants.ROLE_USER.equals(role)) {
                type = AuthorizeType.AUTHENTICATED;
            } else if (SecurityConstants.ROLE_EVERYONE.equals(role)) {
                type = AuthorizeType.PUBLIC;
            } else {
                allowedRoles.add(role);
            }
            return this;
        }
        QueryingAuthorizeSetting deniedRole(String value) {
            deniedRoles.add(value.substring(ROLE.length()));
            return this;
        }
        AuthorizeSetting toAuthorizeSetting() {
            AuthorizeSetting result = new AuthorizeSetting();
            result.type = type == null ? AuthorizeType.PRIVATE : type;
            result.deniedRoles = deniedRoles.toArray(new String[deniedRoles.size()]);
            result.permittedRoles = allowedRoles.toArray(new String[allowedRoles.size()]);
            return result;
        }
    }
    @Override
    public void removeInstances(String[] names) {
    }
    @Override
    public void renameInstance(String oldName, String newName) {
    }
    @Override
    public void setFormPasswordSavedCount(int passwordDiffCount) {
    }
    @Override
    public void dispose() {
    }
}