Package org.apache.felix.useradmin.filestore

Source Code of org.apache.felix.useradmin.filestore.RoleRepositoryFileStore

/**
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You 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.apache.felix.useradmin.filestore;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.felix.useradmin.RoleRepositoryStore;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.useradmin.UserAdminEvent;
import org.osgi.service.useradmin.UserAdminListener;


/**
* Provides an implementation of {@link RoleRepositoryStore} using Java Serialization.
*/
public class RoleRepositoryFileStore extends RoleRepositoryMemoryStore implements Runnable, UserAdminListener, ManagedService {

    /** The PID for this service to allow its configuration to be updated. */
    public static final String PID = "org.apache.felix.useradmin.filestore";

    static final String KEY_WRITE_DISABLED = "background.write.disabled";
    static final String KEY_WRITE_DELAY_VALUE = "background.write.delay.value";
    static final String KEY_WRITE_DELAY_TIMEUNIT = "background.write.delay.timeunit";

    private static final String PREFIX = PID.concat(".");
    private static final boolean DEFAULT_WRITE_DISABLED = Boolean.parseBoolean(System.getProperty(PREFIX.concat(KEY_WRITE_DISABLED), "false"));
    private static final int DEFAULT_WRITE_DELAY_VALUE = Integer.parseInt(System.getProperty(PREFIX.concat(KEY_WRITE_DELAY_VALUE), "500"));
    private static final TimeUnit DEFAULT_WRITE_DELAY_TIMEUNIT = TimeUnit.MILLISECONDS;

    private static final String FILE_NAME = "ua_repo.dat";

    private final File m_file;
    private final AtomicReference m_timerRef;

    /**
     * Creates a new {@link RoleRepositoryStore} instance.
     *
     * @param baseDir the base directory where we can store our serialized data, cannot be <code>null</code>.
     */
    public RoleRepositoryFileStore(File baseDir) {
        this(baseDir, !DEFAULT_WRITE_DISABLED);
    }
   
    /**
     * Creates a new {@link RoleRepositoryStore} instance.
     *
     * @param baseDir the base directory where we can store our serialized data, cannot be <code>null</code>;
     * @param backgroundWriteEnabled <code>true</code> if background writing should be enabled, <code>false</code> to disable it.
     */
    public RoleRepositoryFileStore(File baseDir, boolean backgroundWriteEnabled) {
        m_file = new File(baseDir, FILE_NAME);
       
        m_timerRef = new AtomicReference();

        if (backgroundWriteEnabled) {
            m_timerRef.set(new ResettableTimer(this, DEFAULT_WRITE_DELAY_VALUE, DEFAULT_WRITE_DELAY_TIMEUNIT));
        }
    }
   
    public void roleChanged(UserAdminEvent event) {
        scheduleTask();
    }

    /**
     * {@inheritDoc}
     *
     * <p>Will be called by m_timer!</p>
     */
    public void run() {
        try {
            // Persist everything to disk...
            flush();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Starts this store by reading the latest version from disk.
     *
     * @throws IOException in case of I/O problems retrieving the store.
     */
    public void start() throws IOException {
        m_entries.putAll(retrieve());
    }

    /**
     * Stops this store service.
     */
    public void stop() throws IOException {
        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
        if (timer != null) {
            if (!timer.isShutDown()) {
                // Shutdown and await termination...
                timer.shutDown();
            }
            // Clear reference...
            m_timerRef.compareAndSet(timer, null);
        }

        // Write the latest version to disk...
        flush();
    }

    /**
     * {@inheritDoc}
     */
    public void updated(Dictionary properties) throws ConfigurationException {
        boolean writeDisabled = DEFAULT_WRITE_DISABLED;
        int writeDelayValue = DEFAULT_WRITE_DELAY_VALUE;
        TimeUnit writeDelayUnit = DEFAULT_WRITE_DELAY_TIMEUNIT;

        if (properties != null) {
            Object wd = properties.get(KEY_WRITE_DISABLED);
            if (wd == null) {
                throw new ConfigurationException(KEY_WRITE_DISABLED, "Missing write disabled value!");
            }
            try {
                writeDisabled = Boolean.parseBoolean((String) wd);
            } catch (Exception e) {
                throw new ConfigurationException(KEY_WRITE_DISABLED, "Invalid write disabled value!");
            }

            if (!writeDisabled) {
                Object wdv = properties.get(KEY_WRITE_DELAY_VALUE);
                if (wdv == null) {
                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Missing write delay value!");
                }
                try {
                    writeDelayValue = Integer.parseInt((String) wdv);
                } catch (Exception e) {
                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Invalid write delay value!");
                }
                if (writeDelayValue <= 0) {
                    throw new ConfigurationException(KEY_WRITE_DELAY_VALUE, "Invalid write delay value!");
                }

                Object wdu = properties.get(KEY_WRITE_DELAY_TIMEUNIT);
                if (wdu != null) {
                    try {
                        writeDelayUnit = TimeUnit.valueOf(((String) wdu).toUpperCase());
                    } catch (Exception e) {
                        throw new ConfigurationException(KEY_WRITE_DELAY_TIMEUNIT, "Invalid write delay unit!");
                    }
                }
            }
        }

        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
        if (timer != null) {
            timer.shutDown();
        }
        m_timerRef.compareAndSet(timer, writeDisabled ? null : new ResettableTimer(this, writeDelayValue, writeDelayUnit));
    }

    /**
     * Retrieves the serialized repository from disk.
     *
     * @return the retrieved repository, never <code>null</code>.
     * @throws IOException in case the retrieval of the repository failed.
     */
    protected Map retrieve() throws IOException {
        InputStream is = null;

        try {
            is = new BufferedInputStream(new FileInputStream(m_file));

            return new RoleRepositorySerializer().deserialize(is);
        } catch (FileNotFoundException exception) {
            // Don't bother; file does not exist...
            return Collections.emptyMap();
        } catch (IOException exception) {
            exception.printStackTrace();
            throw exception;
        } finally {
            closeSafely(is);
        }
    }

    /**
     * Stores the given repository to disk as serialized objects.
     *
     * @param roleRepository the repository to store, cannot be <code>null</code>.
     * @throws IOException in case storing the repository failed.
     */
    protected void store(Map roleRepository) throws IOException {
        OutputStream os = null;

        try {
            os = new BufferedOutputStream(new FileOutputStream(m_file));

            new RoleRepositorySerializer().serialize(roleRepository, os);
        } finally {
            closeSafely(os);
        }
    }

    /**
     * Closes a given resource, ignoring any exceptions that may come out of this.
     *
     * @param resource the resource to close, can be <code>null</code>.
     */
    private void closeSafely(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                // Ignore
            }
        }
    }

    /**
     * Flushes the current repository to disk.
     *
     * @throws IOException in case of problems storing the repository.
     */
    private void flush() throws IOException {
        store(new HashMap(m_entries));
    }

    /**
     * Notifies the background timer to schedule a task for storing the
     * contents of this store to disk.
     */
    private void scheduleTask() {
        ResettableTimer timer = (ResettableTimer) m_timerRef.get();
        if (timer != null && !timer.isShutDown()) {
            timer.schedule();
        }
    }
}
TOP

Related Classes of org.apache.felix.useradmin.filestore.RoleRepositoryFileStore

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.