Java tutorial
/** * Copyright (C) 2011 Red Hat, Inc. (jdcasey@commonjava.org) * * 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.commonjava.aprox.folo.data; import java.io.File; import java.io.IOException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import javax.annotation.PostConstruct; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import org.commonjava.aprox.folo.conf.FoloConfig; import org.commonjava.aprox.folo.model.TrackedContentRecord; import org.commonjava.aprox.folo.model.TrackingKey; import org.commonjava.aprox.model.core.io.AproxObjectMapper; import org.commonjava.aprox.subsys.datafile.DataFile; import org.commonjava.aprox.subsys.datafile.DataFileManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; @ApplicationScoped public class FoloRecordCache extends CacheLoader<TrackingKey, TrackedContentRecord> implements RemovalListener<TrackingKey, TrackedContentRecord> { private static final String DATA_DIR = "folo"; private final Logger logger = LoggerFactory.getLogger(getClass()); @Inject private DataFileManager dataFileManager; @Inject private AproxObjectMapper objectMapper; @Inject private FoloConfig config; protected Cache<TrackingKey, TrackedContentRecord> recordCache; protected FoloRecordCache() { } public FoloRecordCache(final DataFileManager dataFileManager, final AproxObjectMapper objectMapper, final FoloConfig config) { this.dataFileManager = dataFileManager; this.objectMapper = objectMapper; this.config = config; } @PostConstruct public void buildCache() { final CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder(); builder.expireAfterAccess(config.getCacheTimeoutSeconds(), TimeUnit.SECONDS).removalListener(this); recordCache = builder.build(this); } @Override public void onRemoval(final RemovalNotification<TrackingKey, TrackedContentRecord> notification) { final TrackingKey key = notification.getKey(); if (key == null) { logger.info("Nothing to persist. Skipping."); return; } write(notification.getValue()); } protected void write(final TrackedContentRecord record) { final TrackingKey key = record.getKey(); final File file = getFile(key); logger.info("Writing {} to: {}", key, file); try { file.getParentFile().mkdirs(); objectMapper.writeValue(file, record); } catch (final IOException e) { logger.error("Failed to persist artimon log of artifact usage via: " + key, e); } } @Override public TrackedContentRecord load(final TrackingKey key) throws Exception { final File file = getFile(key); if (!file.exists()) { logger.info("Creating new record for: {}", key); return new TrackedContentRecord(key); } logger.info("Loading: {} from: {}", key, file); try { return objectMapper.readValue(file, TrackedContentRecord.class); } catch (final IOException e) { logger.error("Failed to read artimon tracked record: " + key, e); throw new IllegalStateException( "Requested artimon tracked record: " + key + " is corrupt, and cannot be read.", e); } } public void delete(final TrackingKey key) { recordCache.invalidate(key); final File file = getFile(key); if (file.exists()) { logger.info("Deleting: {} at: {}", key, file); file.delete(); } } protected File getFile(final TrackingKey key) { final String fname = String.format("%s.json", key.getId()); final DataFile dataFile = dataFileManager.getDataFile(DATA_DIR, fname); return dataFile.getDetachedFile(); } public Callable<? extends TrackedContentRecord> newCallable(final TrackingKey trackedStore) { return new LoaderCall(this, trackedStore); } private static final class LoaderCall implements Callable<TrackedContentRecord> { private final FoloRecordCache persister; private final TrackingKey key; public LoaderCall(final FoloRecordCache persister, final TrackingKey key) { this.persister = persister; this.key = key; } @Override public TrackedContentRecord call() throws Exception { return persister.load(key); } } public boolean hasRecord(final TrackingKey key) { return recordCache.getIfPresent(key) != null || getFile(key).exists(); } public TrackedContentRecord get(final TrackingKey key) throws FoloContentException { try { return recordCache.get(key, newCallable(key)); } catch (final ExecutionException e) { throw new FoloContentException("Failed to load tracking record for: %s. Reason: %s", e, key, e.getMessage()); } } }