1 package com.atlassian.plugin.osgi.container.impl;
2
3 import com.atlassian.plugin.osgi.container.OsgiContainerException;
4 import com.atlassian.plugin.osgi.container.OsgiPersistentCache;
5 import com.google.common.base.Charsets;
6 import com.google.common.hash.Hashing;
7 import org.apache.commons.io.FileUtils;
8 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory;
10
11 import java.io.File;
12 import java.io.IOException;
13
14 import static com.google.common.base.Preconditions.checkNotNull;
15 import static com.google.common.base.Preconditions.checkState;
16
17
18
19
20
21
22 public class DefaultOsgiPersistentCache implements OsgiPersistentCache {
23 private final File osgiBundleCache;
24 private final File frameworkBundleCache;
25 private final File transformedPluginCache;
26 private final Logger log = LoggerFactory.getLogger(DefaultOsgiPersistentCache.class);
27
28
29
30
31
32
33 public DefaultOsgiPersistentCache(final File baseDir) {
34 checkState(checkNotNull(baseDir).exists(), "The base directory for OSGi persistent caches should exist, %s", baseDir);
35 osgiBundleCache = new File(baseDir, "felix");
36 frameworkBundleCache = new File(baseDir, "framework-bundles");
37 transformedPluginCache = new File(baseDir, "transformed-plugins");
38 validate(null);
39 }
40
41 public File getFrameworkBundleCache() {
42 return frameworkBundleCache;
43 }
44
45 public File getOsgiBundleCache() {
46 return osgiBundleCache;
47 }
48
49 public File getTransformedPluginCache() {
50 return transformedPluginCache;
51 }
52
53 public void clear() throws OsgiContainerException {
54 try {
55 FileUtils.cleanDirectory(frameworkBundleCache);
56 FileUtils.cleanDirectory(osgiBundleCache);
57 FileUtils.cleanDirectory(transformedPluginCache);
58 } catch (final IOException e) {
59 throw new OsgiContainerException("Unable to clear OSGi caches", e);
60 }
61 }
62
63 public void validate(final String cacheValidationKey) {
64 ensureDirectoryExists(frameworkBundleCache);
65 ensureDirectoryExists(osgiBundleCache);
66 ensureDirectoryExists(transformedPluginCache);
67
68 try {
69 FileUtils.cleanDirectory(osgiBundleCache);
70 } catch (final IOException e) {
71 throw new OsgiContainerException("Unable to clean the cache directory: " + osgiBundleCache, e);
72 }
73
74 if (cacheValidationKey != null) {
75 final String newHash = Hashing.sha1().hashString(cacheValidationKey, Charsets.UTF_8).toString();
76 final File versionFile = new File(transformedPluginCache, "cache.key");
77 if (versionFile.exists()) {
78 String oldVersion = null;
79 try {
80 oldVersion = FileUtils.readFileToString(versionFile);
81 } catch (final IOException e) {
82 log.debug("Unable to read cache key file", e);
83 }
84 if (!newHash.equals(oldVersion)) {
85 log.info("Application upgrade detected, clearing OSGi cache directories");
86 clear();
87 } else {
88 return;
89 }
90 }
91
92 try {
93 FileUtils.writeStringToFile(versionFile, newHash);
94 } catch (final IOException e) {
95 log.warn("Unable to write cache key file, so will be unable to detect upgrades", e);
96 }
97 }
98 }
99
100 private void ensureDirectoryExists(final File dir) {
101 if (dir.exists() && !dir.isDirectory()) {
102 throw new IllegalArgumentException("'" + dir + "' is not a directory");
103 }
104
105 if (!dir.exists() && !dir.mkdir()) {
106 throw new IllegalArgumentException("Directory '" + dir + "' cannot be created");
107 }
108 }
109 }