com.qwazr.library.LibraryManagerImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.qwazr.library.LibraryManagerImpl.java

Source

/**
 * Copyright 2014-2016 Emmanuel Keller / QWAZR
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 com.qwazr.library;

import com.qwazr.utils.IOUtils;
import com.qwazr.utils.LockUtils;
import com.qwazr.utils.ReadOnlyMap;
import com.qwazr.utils.file.TrackedDirectory;
import com.qwazr.utils.file.TrackedInterface;
import com.qwazr.utils.json.JsonMapper;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.*;

class LibraryManagerImpl extends ReadOnlyMap<String, AbstractLibrary>
        implements LibraryManager, TrackedInterface.FileChangeConsumer, Closeable {

    private static final Logger logger = LoggerFactory.getLogger(LibraryManagerImpl.class);

    static volatile LibraryManagerImpl INSTANCE = null;

    static synchronized void load(File dataDirectory, TrackedDirectory etcTracker) throws IOException {
        if (INSTANCE != null)
            throw new IOException("Already loaded");
        INSTANCE = new LibraryManagerImpl(dataDirectory, etcTracker);
        etcTracker.register(INSTANCE);
    }

    private final File rootDirectory;

    private final TrackedDirectory etcTracker;

    private final LockUtils.ReadWriteLock mapLock = new LockUtils.ReadWriteLock();
    private final Map<File, Map<String, AbstractLibrary>> libraryFileMap;

    private LibraryManagerImpl(File dataDirectory, TrackedDirectory etcTracker) throws IOException {
        this.rootDirectory = dataDirectory;
        this.libraryFileMap = new HashMap<>();
        this.etcTracker = etcTracker;
    }

    public void load() throws IOException {
    }

    @Override
    public void close() {
        mapLock.w.lock();
        try {
            libraryFileMap.clear();
            IOUtils.close(this.values());
            setMap(Collections.emptyMap());
        } finally {
            mapLock.w.unlock();
        }
    }

    public AbstractLibrary getLibrary(String name) {
        etcTracker.check();
        return super.get(name);
    }

    public Map<String, String> getLibraries() {
        etcTracker.check();
        final Map<String, String> map = new LinkedHashMap<>();
        this.forEach((name, library) -> map.put(name, library.getClass().getName()));
        return map;
    }

    @Override
    public void accept(TrackedInterface.ChangeReason changeReason, File jsonFile) {
        String extension = FilenameUtils.getExtension(jsonFile.getName());
        if (!"json".equals(extension))
            return;
        switch (changeReason) {
        case UPDATED:
            loadLibrarySet(jsonFile);
            break;
        case DELETED:
            unloadLibrarySet(jsonFile);
            break;
        }
    }

    private void loadLibrarySet(File jsonFile) {
        try {
            final LibraryConfiguration configuration;
            configuration = JsonMapper.MAPPER.readValue(jsonFile, LibraryConfiguration.class);

            if (configuration == null || configuration.library == null) {
                unloadLibrarySet(jsonFile);
                return;
            }

            if (logger.isInfoEnabled())
                logger.info("Load library configuration file: " + jsonFile.getAbsolutePath());

            mapLock.w.lock();
            try {
                libraryFileMap.put(jsonFile, buildAndLoad(configuration.library));
                buildGlobalMap();
            } finally {
                mapLock.w.unlock();
            }

        } catch (IOException e) {
            if (logger.isErrorEnabled())
                logger.error(e.getMessage(), e);
            return;
        }
    }

    private void unloadLibrarySet(File jsonFile) {
        final Map<String, AbstractLibrary> map;
        mapLock.w.lock();
        try {
            map = libraryFileMap.remove(jsonFile);
            if (map == null)
                return;
            if (logger.isInfoEnabled())
                logger.info("Unload library configuration file: " + jsonFile.getAbsolutePath());
            buildGlobalMap();
        } finally {
            mapLock.w.unlock();
        }
        IOUtils.close(map.values());
    }

    private void buildGlobalMap() {
        final Map<String, AbstractLibrary> libraries = new HashMap<>();
        libraryFileMap.forEach((file, libraryMap) -> libraries.putAll(libraryMap));
        setMap(libraries);
    }

    private Map<String, AbstractLibrary> buildAndLoad(List<AbstractLibrary> libraries) throws IOException {
        final Map<String, AbstractLibrary> map = new HashMap<>();
        try {
            for (AbstractLibrary library : libraries) {
                library.load(rootDirectory);
                map.put(library.name, library);
            }
            return map;
        } catch (IOException e) {
            IOUtils.close(map.values());
            throw e;
        }
    }

}