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

org.netbeans.modules.gradle.cache.AbstractDiskCache Maven / Gradle / Ivy

The newest version!
/*
 * 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.netbeans.modules.gradle.cache;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.logging.Level.*;
import java.util.logging.Logger;
import org.netbeans.modules.gradle.options.GradleExperimentalSettings;

/**
 *
 * @author lkishalmi
 */
public abstract class AbstractDiskCache {

    private static final Logger LOG = Logger.getLogger(AbstractDiskCache.class.getName());
    protected K key;
    private WeakReference> entryRef;

    protected AbstractDiskCache() {}
    
    protected AbstractDiskCache(K key) {
        this.key = key;
    }

    public final synchronized T loadData() {
        CacheEntry e = loadEntry();
        return e != null ? e.getData() : null;
    }

    public final boolean isCompatible() {
        CacheEntry e = loadEntry();
        return e != null && e.isCompatible(this);        
    }

    public final boolean isValid() {
        CacheEntry e = loadEntry();
        return e != null && e.isValid(this);        
    }
    
    public final synchronized void storeData(T data) {
        CacheEntry entry = new CacheEntry<>(this, data);
        if (doStoreEntry(entry)) {
            entryRef = new WeakReference<>(entry);        
        }
    }

    public final synchronized void invalidate() {
        entryRef = null;
        File cacheFile = cacheFile();
        if (cacheFile.canRead()) {
            cacheFile.delete();
        }
    }

    protected final synchronized CacheEntry loadEntry() {
        CacheEntry ret = entryRef != null ? entryRef.get() : null;
        if (ret == null && !GradleExperimentalSettings.getDefault().isCacheDisabled()) {
            ret = doLoadEntry();
            entryRef = ret != null ? new WeakReference<>(ret) : null;
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    protected CacheEntry doLoadEntry() {
        CacheEntry ret = null;
        File cacheFile = cacheFile();
        if (cacheFile.canRead()) {
            try (ObjectInputStream is = new ObjectInputStream(new FileInputStream(cacheFile))) {
                ret = (CacheEntry) is.readObject();
            } catch (ClassNotFoundException | IOException ex) {
                LOG.log(INFO, "Could no load project info from {0} due to: {1}", new Object[]{cacheFile, ex.getMessage()});
                cacheFile.delete();
            }
        }
        return ret;        
    }
    
    @SuppressWarnings({"unchecked", "rawtypes"})
    protected boolean doStoreEntry(CacheEntry entry) {
        File cacheFile = cacheFile();
        if (!cacheFile.exists()) {
            cacheFile.getParentFile().mkdirs();
        }
        try (ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(cacheFile))) {
            os.writeObject(entry);
            return true;
        } catch (IOException ex) {
            LOG.log(INFO, "Failed to persist info to {0} due to {1}", new Object[]{cacheFile, ex.getMessage()});
            cacheFile.delete();
        }
        return false;
    }
    
    protected abstract int cacheVersion();
    protected abstract File cacheFile();
    protected abstract Set cacheInvalidators();

    public static final class CacheEntry  implements Serializable  {
        static final long serialVersionUID = 1L;
        
        int version;

        long timestamp;
        Set sourceFiles;
        T data;

        protected CacheEntry() {
        }

        protected CacheEntry(AbstractDiskCache cache, T data) {
            timestamp = System.currentTimeMillis();
            version = cache.cacheVersion();
            this.sourceFiles = cache.cacheInvalidators();
            this.data = data;
        }
        
        public boolean isCompatible(AbstractDiskCache cache) {
            return version == cache.cacheVersion();
        }

        public boolean isValid(AbstractDiskCache cache) {
            boolean ret = (data != null) && isCompatible(cache);
            if (ret && (sourceFiles != null)) {
                for (File f : sourceFiles) {
                    if (!f.exists() || (f.lastModified() > timestamp)) {
                        ret = false;
                        break;
                    }
                }
            }
            return ret;
        }

        public T getData() {
            return data;
        }

        @Override
        public String toString() {
            Class dataClass = data != null ? data.getClass() : null;
            return "CacheEntryImpl{" + "data:version=" + dataClass + ":" + version + ", timestamp=" + new Date(timestamp) + ", sourceFiles=" + sourceFiles + '}';
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy