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

com.amazonaws.mobileconnectors.amazonmobileanalytics.internal.session.FileSessionStore Maven / Gradle / Ivy

There is a newer version: 2.20.1
Show newest version
/*
 * Copyright 2010-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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 com.amazonaws.mobileconnectors.amazonmobileanalytics.internal.session;

import android.util.Log;

import com.amazonaws.mobileconnectors.amazonmobileanalytics.internal.core.AnalyticsContext;
import com.amazonaws.mobileconnectors.amazonmobileanalytics.internal.core.system.FileManager;
import com.amazonaws.util.StringUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;

public class FileSessionStore implements SessionStore {
    private static final String TAG = "FileSessionStore";

    protected static final String SESSION_DIRECTORY = "sessions";
    protected static final String SESSION_FILE_NAME = "sessionFile";
    static final String KEY_MAX_STORAGE_SIZE = "maxStorageSize";
    static final long MAX_STORAGE_SIZE = 8 * 564 * 5L; // up to 564 ASCII chars
                                                       // 5 timess

    private final AnalyticsContext context;
    private File sessionFile;
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
    private final ReadLock readSessionLock = lock.readLock();
    private final WriteLock writeSessionLock = lock.writeLock();
    private BufferedReader reader = null;

    public FileSessionStore(final AnalyticsContext context) {
        this.context = context;
        FileManager fileManager = this.context.getSystem().getFileManager();
        File sessionDir = fileManager.createDirectory(SESSION_DIRECTORY);
        try {
            sessionFile = fileManager.createFile(new File(sessionDir, SESSION_FILE_NAME));
        } catch (IOException e) {
            Log.e(TAG, "An error occurred while attempting to create/open the session file", e);
        }
    }

    @Override
    public void storeSession(final Session session) throws SessionStoreException {
        String serializedSession = session.toJSONObject().toString();
        Writer writer = null;
        this.writeSessionLock.lock();
        try {
            try {
                writer = tryInitializeWriter();
                if (writer != null) {
                    final long maxStorageSize = this.context.getConfiguration().optLong(
                            KEY_MAX_STORAGE_SIZE, MAX_STORAGE_SIZE);
                    if (this.sessionFile.length() + serializedSession.length() <= maxStorageSize) {
                        writer.write(serializedSession);
                        writer.flush();
                    } else {
                        Log.e(TAG, "The session file exceeded its allowed size of "
                                + maxStorageSize + " bytes");
                    }
                }
            } catch (IOException e) {
                Log.e(TAG, "Failed to persist the session", e);
                throw new SessionStoreException("Failed to persist the session", e);
            } finally {
                this.tryCloseWriter(writer);
            }
        } finally {
            this.writeSessionLock.unlock();
        }
    }

    private Writer tryInitializeWriter() throws SessionStoreException {
        try {
            createFileDirectories(sessionFile);
            OutputStream stream = context.getSystem().getFileManager()
                    .newOutputStream(sessionFile, false);
            return new OutputStreamWriter(stream, StringUtils.UTF8);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Unable to save session file", e);
            throw new SessionStoreException("Unable to save session file", e);
        } catch (Exception e) {
            Log.e(TAG, "Unexpected exception", e);
            throw new SessionStoreException("Unable to save session file", e);
        }
    }

    private void tryCloseWriter(final Writer writer) throws SessionStoreException {
        if (writer != null) {
            try {
                writer.close();
            } catch (IOException e) {
                Log.e(TAG, "Unable to close writer for session file", e);
            }
        }
    }

    private boolean tryOpenReader() {
        if (reader != null) {
            return true;
        }

        InputStreamReader streamReader = null;
        try {
            streamReader = new InputStreamReader(context.getSystem()
                    .getFileManager().newInputStream(sessionFile), StringUtils.UTF8);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Could not open the session file", e);
        }

        if (streamReader != null) {
            this.reader = new BufferedReader(streamReader);
            return true;
        }
        return false;
    }

    private void tryCloseReader() {
        if (this.reader != null) {
            this.readSessionLock.lock();
            try {
                try {
                    this.reader.close();
                } catch (IOException ioe) {
                    Log.e(TAG, "Unable to close reader for session file", ioe);
                } finally {
                    this.reader = null;
                }
            } finally {
                this.readSessionLock.unlock();
            }
        }
    }

    @Override
    public Session getSession() {
        String serializedSession = null;
        this.readSessionLock.lock();
        try {
            try {
                this.tryOpenReader();
                if (this.reader != null) {
                    serializedSession = this.reader.readLine();
                }
            } catch (IOException e) {
                Log.e(TAG, "Failed to read the session", e);
            } finally {
                this.tryCloseReader();
                // Clear out the session file so nothing is persisted after its
                // been loaded into memory
                FileManager fileManager = context.getSystem().getFileManager();
                try {
                    if (fileManager.deleteFile(sessionFile) || !sessionFile.exists()) {
                        sessionFile = fileManager.createFile(sessionFile);
                    }
                } catch (IOException e) {
                    Log.e(TAG, "Unable to clear session file", e);
                }
            }
        } finally {
            this.readSessionLock.unlock();
        }

        return Session.getSessionFromSerializedSession(serializedSession);
    }

    private void createFileDirectories(File file) {
        if(!file.getParentFile().mkdirs() && !file.getParentFile().exists()){ //Ensure all directories are in place before saving session file
            String msg = String.format("Could not create directories for file - %s", file.getAbsolutePath());
            Log.e(TAG, msg);
            throw new SessionStoreException(msg);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy