/** * Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cloudsmith * */ package org.cloudsmith.geppetto.forge.impl; import static org.cloudsmith.geppetto.forge.Forge.CACHE_LOCATION; import static org.cloudsmith.geppetto.forge.model.Constants.API_V2_URL_NAME; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.cloudsmith.geppetto.common.os.StreamUtil; import org.cloudsmith.geppetto.forge.Cache; import org.cloudsmith.geppetto.forge.util.Checksums; import org.cloudsmith.geppetto.forge.util.ModuleUtils; import org.cloudsmith.geppetto.forge.v2.model.ModuleName; import org.cloudsmith.geppetto.forge.v2.service.ReleaseService; import org.cloudsmith.geppetto.semver.Version; import com.google.inject.Inject; import com.google.inject.Singleton; import com.google.inject.name.Named; @Singleton class CacheImpl implements Cache { private static void delete(File fileOrDir) throws IOException { File[] children = fileOrDir.listFiles(); if(children != null) for(File child : children) delete(child); if(!fileOrDir.delete() && fileOrDir.exists()) throw new IOException("Unable to delete " + fileOrDir); } @Inject private ReleaseService releaseService; private transient String cacheKey; @Inject(optional = true) @Named(CACHE_LOCATION) private File location; @Inject @Named(API_V2_URL_NAME) private String apiV2URL; @Override public void clean() throws IOException { delete(getLocation()); } private synchronized String getCacheKey() { if(cacheKey == null) { StringBuilder bld = new StringBuilder(apiV2URL.replaceAll("[^\\p{Alnum}]+", "_")); int last = bld.length() - 1; if(bld.charAt(last) == '_') bld.setLength(last); bld.append('-'); Checksums.appendSHA1(bld, apiV2URL); cacheKey = bld.toString(); } return cacheKey; } @Override public synchronized File getLocation() { if(location == null) { if(location == null) { String userHome = System.getProperty("user.home"); if(userHome == null) throw new RuntimeException("Unable to obtain users home directory"); File dir = new File(userHome); if(!dir.isDirectory()) throw new RuntimeException(userHome + " is not a directory"); location = new File(new File(dir, ".puppet/var/puppet-module/cache"), getCacheKey()); } } return location; } @Override public File retrieve(ModuleName qname, Version version) throws IOException { // This cache assumes that all leaf names are unique so we don't want // to preserve the folder structure StringBuilder bld = new StringBuilder(); ModuleUtils.buildFileNameWithExtension(qname, version, bld); File cachedFile = new File(getLocation(), bld.toString()); if(!cachedFile.exists()) { File dir = cachedFile.getParentFile(); dir.mkdirs(); OutputStream output = new FileOutputStream(cachedFile); try { releaseService.download(qname.getOwner(), qname.getName(), version, output); } finally { StreamUtil.close(output); } } return cachedFile; } }