/**
* Copyright (C) 2012-2013 Selventa, Inc.
*
* This file is part of the OpenBEL Framework.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The OpenBEL Framework is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the OpenBEL Framework. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms under LGPL v3:
*
* This license does not authorize you and you are prohibited from using the
* name, trademarks, service marks, logos or similar indicia of Selventa, Inc.,
* or, in the discretion of other licensors or authors of the program, the
* name, trademarks, service marks, logos or similar indicia of such authors or
* licensors, in any marketing or advertising materials relating to your
* distribution of the program or any covered product. This restriction does
* not waive or limit your obligation to keep intact all copyright notices set
* forth in the program as delivered to you.
*
* If you distribute the program in whole or in part, or any modified version
* of the program, and you assume contractual liability to the recipient with
* respect to the program or modified version, then you will indemnify the
* authors and licensors of the program for any liabilities that these
* contractual assumptions directly impose on those licensors and authors.
*/
package org.openbel.framework.tools;
import static org.openbel.framework.common.Strings.HASH;
import static org.openbel.framework.common.Strings.LIST_CACHE;
import static org.openbel.framework.common.Strings.LOAD_INDEX_FILE;
import static org.openbel.framework.common.Strings.LOAD_INDEX_FROM_SYSCONFIG;
import static org.openbel.framework.common.Strings.LOAD_RESOURCE;
import static org.openbel.framework.common.Strings.PURGE_CACHE;
import static org.openbel.framework.common.Strings.SYSTEM_CONFIG_PATH;
import static org.openbel.framework.common.cfg.SystemConfiguration.getSystemConfiguration;
import static org.openbel.framework.common.enums.ExitCode.GENERAL_FAILURE;
import static org.openbel.framework.core.StandardOptions.ARG_SYSCFG;
import static org.openbel.framework.core.StandardOptions.LONG_OPT_SYSCFG;
import static org.openbel.framework.core.StandardOptions.SHRT_OPT_SYSCFG;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.cli.Option;
import org.apache.commons.io.FileUtils;
import org.openbel.framework.common.SimpleOutput;
import org.openbel.framework.common.cfg.SystemConfiguration;
import org.openbel.framework.common.index.Index;
import org.openbel.framework.common.index.ResourceIndex;
import org.openbel.framework.common.util.Hasher;
import org.openbel.framework.core.CommandLineApplication;
import org.openbel.framework.core.cache.CacheManagerService;
import org.openbel.framework.core.cache.DefaultCacheManagerService;
import org.openbel.framework.core.df.cache.CacheLookupService;
import org.openbel.framework.core.df.cache.CacheableResourceService;
import org.openbel.framework.core.df.cache.CachedResource;
import org.openbel.framework.core.df.cache.DefaultCacheLookupService;
import org.openbel.framework.core.df.cache.DefaultCacheableResourceService;
import org.openbel.framework.core.df.cache.ResolvedResource;
import org.openbel.framework.core.df.cache.ResourceType;
import org.openbel.framework.core.namespace.DefaultNamespaceService;
import org.openbel.framework.core.namespace.NamespaceIndexerService;
import org.openbel.framework.core.namespace.NamespaceIndexerServiceImpl;
import org.openbel.framework.core.namespace.NamespaceService;
/**
* CacheManager is a {@link CommandLineApplication} to manage the BELFramework
* cache and provides the following functionality:<ul>
* <li>List the contents of the cache.</li>
* <li>Load a resource file into the cache.</li>
* <li>Load resources from a resource index file into the cache.</li>
* <li>Update all resources in the cache.</li>
* <li>Purge all resources in the cache.</li>
* <li>Generates a hash for a local file.</li></ul>
*
* @author Anthony Bargnesi {@code <abargnesi@selventa.com>}
*/
public class CacheManager extends CommandLineApplication {
private final static String CACHE_MANAGER_APP_NAME = "Cache Manager";
private final static String CACHE_MANAGER_APP_DESC =
"Manages the OpenBEL Framework resource cache.";
private final static String LIST_CACHE_OPTION = "l";
private final static String CACHE_RESOURCE_OPTION = "a";
private final static String CACHE_INDEX_FILE = "i";
private final static String CACHE_SYSCONFIG_FILE_OPTION = "c";
private final static String PURGE_CACHE_OPTION = "p";
private final static String GENERATE_CHECKSUM_OPTION = "g";
/**
* Defines the cache lookup to use.
*/
private final CacheLookupService cacheLookupService;
/**
* Defines the cache manager to use.
*/
private final CacheManagerService cacheMgrService;
/**
* Defines the resource cache service to use.
*/
private final CacheableResourceService cacheService;
/**
* Defines the system configuration to use.
*/
private SystemConfiguration config = null;
/**
* Constructs the CacheManager with command-line arguments.
*
* @param args {@link String}[] the command-line arguments
*/
public CacheManager(String[] args) {
super(args);
final SimpleOutput reportable = new SimpleOutput();
reportable.setErrorStream(System.err);
reportable.setOutputStream(System.out);
setReportable(reportable);
printApplicationInfo();
initializeSystemConfiguration();
config = getSystemConfiguration();
cacheLookupService = new DefaultCacheLookupService();
cacheService = new DefaultCacheableResourceService();
final NamespaceIndexerService nsindexer =
new NamespaceIndexerServiceImpl();
final NamespaceService namespace = new DefaultNamespaceService(
cacheService, cacheLookupService, nsindexer);
cacheMgrService = new DefaultCacheManagerService(
cacheLookupService, namespace, getReportable());
Option[] options = getOptions();
if (options.length == 0) {
printUsage();
bail(GENERAL_FAILURE);
}
reportable.output("Using cache directory: "
+ config.getCacheDirectory().getAbsolutePath());
for (int i = 0; i < options.length; i++) {
if (i != 0) {
reportable.output("");
}
handleOption(options[i]);
}
}
/**
* Handle the cli option that was provided.
*
* @param option {@link Option} the current option to handle
*/
private void handleOption(Option option) {
if (LIST_CACHE_OPTION.equals(option.getOpt())) {
handleListCache();
} else if (CACHE_RESOURCE_OPTION.equals(option.getOpt())) {
handleLoadResource(option);
} else if (CACHE_SYSCONFIG_FILE_OPTION.equals(option.getOpt())) {
handleLoadDefaultIndex();
} else if (CACHE_INDEX_FILE.equals(option.getOpt())) {
handleLoadIndex(option.getValue());
} else if (PURGE_CACHE_OPTION.equals(option.getOpt())) {
handlePurgeCache();
} else if (GENERATE_CHECKSUM_OPTION.equals(option.getOpt())) {
handleGenerateHash(option);
}
}
/**
* Handle the list cache option.
*/
protected void handleListCache() {
reportable.output("Listing resources in the cache");
List<CachedResource> resources = cacheLookupService.getResources();
if (resources.isEmpty()) {
reportable.output("No resources in the cache.");
}
for (CachedResource resource : resources) {
reportable.output("\t" + resource.getType().getResourceFolderName()
+ "\t" + resource.getRemoteLocation());
}
}
protected void handleLoadDefaultIndex() {
String resourceIndex = config.getResourceIndexURL();
handleLoadIndex(resourceIndex);
}
/**
* Handle the load resource option.
*
* @param option {@link Option} the option to fetch the cli argument from
*/
protected void handleLoadResource(Option option) {
String resourceLocation = option.getValue();
reportable.output("Loading resource into the cache:");
reportable.output(" " + resourceLocation);
ResourceType type = ResourceType.fromLocation(resourceLocation);
if (type == null) {
reportable
.error("Resource type cannot be determined, consult help with -h.");
bail(GENERAL_FAILURE);
}
cacheMgrService.updateResourceInCache(type, resourceLocation);
}
/**
* Handle the load index option.
*
* @param indexLocation {@link String} the index location
*/
protected void handleLoadIndex(String indexLocation) {
reportable.output("Loading resource from index file:");
reportable.output(" " + indexLocation);
File indexFile = new File(indexLocation);
if (!indexFile.exists() || !indexFile.canRead()) {
// try the index as an online resource.
try {
ResolvedResource resolvedResource = cacheService
.resolveResource(ResourceType.RESOURCE_INDEX,
indexLocation);
indexFile = resolvedResource.getCacheResourceCopy();
} catch (Exception e) {
reportable.error("Index could not be read");
bail(GENERAL_FAILURE);
}
}
try {
ResourceIndex.INSTANCE.loadIndex(indexFile);
} catch (Exception e) {
reportable.error("Unable to load index");
reportable.error("Reason: " + e.getMessage());
bail(GENERAL_FAILURE);
}
Index index = ResourceIndex.INSTANCE.getIndex();
cacheMgrService.updateResourceIndexInCache(index);
}
/**
* Handle the purge cache option.
*/
protected void handlePurgeCache() {
reportable.output("Purging all resources from the cache");
try {
cacheMgrService.purgeResources();
} catch (Exception e) {
reportable.error("Unable to remove all resources in the cache");
reportable.error("Reason: " + e.getMessage());
bail(GENERAL_FAILURE);
}
}
/**
* Handle the generate hash option.
*
* @param option {@link Option} the option to fetch the cli argument from
*/
protected void handleGenerateHash(Option option) {
String hashFileLocation = option.getValue();
reportable.output("Generating checksum for file: " + hashFileLocation);
File hashFile = new File(hashFileLocation);
if (!hashFile.exists() || !hashFile.canRead()) {
reportable.error("File cannot be read");
bail(GENERAL_FAILURE);
}
String hashContents = null;
try {
hashContents = FileUtils.readFileToString(hashFile);
} catch (IOException e) {
reportable.error("Unable to read file");
reportable.error("Reason: " + e.getMessage());
bail(GENERAL_FAILURE);
}
Hasher hasher = Hasher.INSTANCE;
try {
String generatedhash = hasher.hashValue(hashContents);
reportable.output("Checksum: " + generatedhash);
} catch (Exception e) {
reportable.error("Unable to created checksum");
reportable.error("Reason: " + e.getMessage());
bail(GENERAL_FAILURE);
}
}
/**
* {@inheritDoc}
*/
@Override
public String getApplicationName() {
return CACHE_MANAGER_APP_NAME;
}
/**
* Returns {@value #CACHE_MANAGER_APP_NAME}.
*
* @return String
*/
@Override
public String getApplicationShortName() {
// App name is short enough.
return getApplicationName();
}
/**
* {@inheritDoc}
*/
@Override
public String getApplicationDescription() {
return CACHE_MANAGER_APP_DESC;
}
/**
* {@inheritDoc}
*/
@Override
public String getUsage() {
StringBuilder bldr = new StringBuilder();
bldr.append(" [-l ]");
bldr.append(" [-a <resource url>]");
bldr.append(" [-i <resource index url>]");
bldr.append(" [-p ]");
bldr.append(" [-c ]");
return bldr.toString();
}
/**
* {@inheritDoc}
*/
@Override
public List<Option> getCommandLineOptions() {
final List<Option> ret = new LinkedList<Option>();
String help;
help = LIST_CACHE;
ret.add(new Option(LIST_CACHE_OPTION, "list-cache", false, help));
help = LOAD_RESOURCE;
ret.add(new Option(CACHE_RESOURCE_OPTION, "cache-resource", true, help));
help = LOAD_INDEX_FILE;
ret.add(new Option(CACHE_INDEX_FILE, "index-file", true, help));
help = LOAD_INDEX_FROM_SYSCONFIG;
ret.add(new Option(CACHE_SYSCONFIG_FILE_OPTION, "sysconfig-index-file",
false, help));
help = PURGE_CACHE;
ret.add(new Option(PURGE_CACHE_OPTION, "purge", false, help));
help = HASH;
ret.add(new Option(GENERATE_CHECKSUM_OPTION, "generate-checksum", true,
help));
help = SYSTEM_CONFIG_PATH;
Option o = new Option(SHRT_OPT_SYSCFG, LONG_OPT_SYSCFG, true, help);
o.setArgName(ARG_SYSCFG);
ret.add(o);
return ret;
}
/**
* Main entrance to the application...Exit, stage left.
*
* @param args {@link String}[] the command-line arguments
*/
public static void main(String... args) {
CacheManager cm = new CacheManager(args);
cm.end();
}
}