All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.picketlink.idm.file.internal.FileDataSource Maven / Gradle / Ivy

There is a newer version: 5.0.0-2013Jan16
Show newest version
/*
 * JBoss, Home of Professional Open Source
 *
 * Copyright 2013 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.picketlink.idm.file.internal;

import org.picketlink.idm.IdentityManagementException;
import org.picketlink.idm.config.FileIdentityStoreConfiguration;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.picketlink.common.util.StringUtil.isNullOrEmpty;
import static org.picketlink.idm.IDMInternalLog.FILE_STORE_LOGGER;
import static org.picketlink.idm.file.internal.FileUtils.createFileIfNotExists;
import static org.picketlink.idm.file.internal.FileUtils.delete;
import static org.picketlink.idm.file.internal.FileUtils.readObject;

/**
 * @author Pedro Silva
 */
public class FileDataSource {

    /**
     * 

* Default buffer length when flushing changes to the filesystem. The higher the value greater will be the * throughput. *

*/ private static final int FLUSH_BYTE_BUFFER = 1024; private static final String DEFAULT_WORKING_DIR = System.getProperty("java.io.tmpdir", File.separator + "tmp") + File.separator + "pl-idm"; private static final String PARTITIONS_FILE_NAME = "pl-idm-partitions.db"; private static final String IDENTITY_TYPES__FILE_NAME = "pl-idm-identity-types.db"; private static final String ATTRIBUTED_TYPES__FILE_NAME = "pl-idm-attributed-types.db"; private static final String ATTRIBUTES_FILE_NAME = "pl-idm-attributes.db"; private static final String RELATIONSHIPS_FILE_NAME = "pl-idm-relationships.db"; private static final String CREDENTIALS_FILE_NAME = "pl-idm-credentials.db"; private static final String PERMISSIONS_FILE_NAME = "pl-idm-permissions.db"; private final FileIdentityStoreConfiguration configuration; /** *

* Holds all stored {@link FilePartition} instances loaded from the filesystem. This {@link Map} is also used to * persist * information to the filesystem. *

*/ private Map partitions; /** *

* Holds all stored {@link FileRelationship} instances loaded from the filesystem. This {@link Map} is also used to * persist * information to the filesystem. *

*/ private Map> relationships; /** *

* Holds all stored {@link FileAttribute} instances loaded from the filesystem. This {@link Map} is also used to * persist * information to the filesystem. *

*/ private Map attributes; /** *

* Holds all stored {@link FileAttributedType} instances loaded from the filesystem. This {@link Map} is also used * to persist * information to the filesystem. *

*/ private Map attributedTypes; private ExecutorService executorService; FileDataSource(FileIdentityStoreConfiguration configuration) { this.configuration = configuration; init(); } Map getPartitions() { return this.partitions; } Map> getRelationships() { return this.relationships; } Map getAttributes() { return attributes; } public Map getAttributedTypes() { return this.attributedTypes; } void flushPartitions() { flush(PARTITIONS_FILE_NAME, getPartitions()); } void flushPartitions(FilePartition partition) { initPartition(partition.getId()); flush(PARTITIONS_FILE_NAME, getPartitions()); } void flushAttributedTypes(FilePartition partition) { flush(partition, IDENTITY_TYPES__FILE_NAME, partition.getIdentityTypes()); } void flushRelationships() { flush(RELATIONSHIPS_FILE_NAME, getRelationships()); } void flushAttributes() { flush(ATTRIBUTES_FILE_NAME, getAttributes()); } void flushAttributedTypes() { flush(ATTRIBUTED_TYPES__FILE_NAME, getAttributedTypes()); } void flushCredentials(FilePartition partition) { FilePartition filePartition = getPartitions().get(partition.getId()); flush(filePartition, CREDENTIALS_FILE_NAME, filePartition.getCredentials()); } void flushPermissions(FilePartition partition) { FilePartition filePartition = getPartitions().get(partition.getId()); flush(filePartition, PERMISSIONS_FILE_NAME, filePartition.getPermissions()); } /** *

* Initializes the working directory. *

* * @return */ private void initWorkingDirectory() { String workingDir = getWorkingDir(); File workingDirectoryFile = new File(workingDir); if (workingDirectoryFile.exists()) { if (this.configuration.isAlwaysCreateFiles()) { FILE_STORE_LOGGER.fileConfigAlwaysCreateWorkingDir(workingDirectoryFile.getPath()); delete(workingDirectoryFile); } } workingDirectoryFile.mkdirs(); FILE_STORE_LOGGER.fileConfigUsingWorkingDir(workingDirectoryFile.getPath()); } private void init() { initWorkingDirectory(); File partitionsFile = createFileIfNotExists(getWorkingDirFile(PARTITIONS_FILE_NAME)); loadPartitions(partitionsFile); Map> relationships = readObject(createFileIfNotExists(getWorkingDirFile(RELATIONSHIPS_FILE_NAME))); if (relationships == null) { relationships = new ConcurrentHashMap>(); } this.relationships = relationships; Map attributes = readObject(createFileIfNotExists(getWorkingDirFile(ATTRIBUTES_FILE_NAME))); if (attributes == null) { attributes = new ConcurrentHashMap(); } this.attributes = attributes; Map attrubtedTypes = readObject(createFileIfNotExists(getWorkingDirFile(ATTRIBUTED_TYPES__FILE_NAME))); if (attrubtedTypes == null) { attrubtedTypes = new ConcurrentHashMap(); } this.attributedTypes = attrubtedTypes; if (this.configuration.isAsyncWrite()) { FILE_STORE_LOGGER.fileAsyncWriteEnabled(this.configuration.getAsyncThreadPool()); this.executorService = Executors.newFixedThreadPool(this.configuration.getAsyncThreadPool()); } } private void loadPartitions(File partitionsFile) { this.partitions = readObject(partitionsFile); if (this.partitions == null) { if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("No partitions to load from %s", partitionsFile.getPath()); } this.partitions = new ConcurrentHashMap(); } else { if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("Loading [%s] Partition(s) from %s", this.partitions.size(), partitionsFile.getPath()); } Set> entrySet = this.partitions.entrySet(); for (Entry entry : entrySet) { initPartition(entry.getKey()); } } } private void initPartition(String partitionId) { FilePartition filePartition = this.partitions.get(partitionId); if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("Initializing Partition [%s] with id [%s].", filePartition.getEntry().getName(), partitionId); } File agentsFile = createFileIfNotExists(getWorkingDirFile(partitionId + File.separator + IDENTITY_TYPES__FILE_NAME)); Map> identityTypes = readObject(agentsFile); if (identityTypes == null) { identityTypes = new ConcurrentHashMap>(); } filePartition.setIdentityTypes(identityTypes); if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("Loaded Identity Types [%s] for Partition [%s].", filePartition.getIdentityTypes().size(), filePartition.getId()); } File credentialsFile = createFileIfNotExists(getWorkingDirFile(partitionId + File.separator + CREDENTIALS_FILE_NAME)); Map>> credentials = readObject(credentialsFile); if (credentials == null) { credentials = new ConcurrentHashMap>>(); } filePartition.setCredentials(credentials); if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("Loaded Credentials [%s] for Partition [%s].", filePartition.getCredentials().size(), filePartition.getId()); } File permissionsFile = createFileIfNotExists(getWorkingDirFile(partitionId + File.separator + PERMISSIONS_FILE_NAME)); Map> permissions = readObject(permissionsFile); if (permissions == null) { permissions = new ConcurrentHashMap>(); } filePartition.setPermissions(permissions); if (isDebugEnabled()) { FILE_STORE_LOGGER.debugf("Loaded Permissions [%s] for Partition [%s].", filePartition.getPermissions().size(), filePartition.getId()); } } private String getWorkingDir() { String workingDir = this.configuration.getWorkingDir(); if (isNullOrEmpty(workingDir)) { workingDir = DEFAULT_WORKING_DIR; } return workingDir; } private void flush(final FilePartition partition, final String fileName, final Object object) { flush(partition.getId() + File.separator + fileName, object); } private void flush(final String fileName, final Object object) { if (this.configuration.isAsyncWrite()) { this.executorService.execute(new Runnable() { @Override public void run() { performFlush(fileName, object); } }); } else { performFlush(fileName, object); } } private synchronized void performFlush(final String fileName, final Object object) { ObjectOutputStream oos = null; ByteArrayOutputStream bos = null; RandomAccessFile randomAccessFile = null; try { randomAccessFile = new RandomAccessFile(getWorkingDir() + File.separator + fileName, "rw"); FileChannel channel = randomAccessFile.getChannel(); bos = new ByteArrayOutputStream(FLUSH_BYTE_BUFFER); oos = new ObjectOutputStream(bos); oos.writeObject(object); channel.write(ByteBuffer.wrap(bos.toByteArray())); } catch (Exception e) { throw new IdentityManagementException("Error flushing changes to file system.", e); } finally { try { if (randomAccessFile != null) { randomAccessFile.close(); } } catch (IOException e) { } try { if (oos != null) { oos.close(); } } catch (Exception e) { } try { if (bos != null) { bos.close(); } } catch (Exception e) { } } } private File getWorkingDirFile(String name) { return new File(getWorkingDir() + File.separator + name); } private boolean isDebugEnabled() { return FILE_STORE_LOGGER.isDebugEnabled(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy