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
42
43
44
45
46 @Deprecated
47 public DefaultOsgiPersistentCache(final File baseDir, final String applicationVersion) {
48 this(baseDir);
49 }
50
51 public File getFrameworkBundleCache() {
52 return frameworkBundleCache;
53 }
54
55 public File getOsgiBundleCache() {
56 return osgiBundleCache;
57 }
58
59 public File getTransformedPluginCache() {
60 return transformedPluginCache;
61 }
62
63 public void clear() throws OsgiContainerException {
64 try {
65 FileUtils.cleanDirectory(frameworkBundleCache);
66 FileUtils.cleanDirectory(osgiBundleCache);
67 FileUtils.cleanDirectory(transformedPluginCache);
68 } catch (final IOException e) {
69 throw new OsgiContainerException("Unable to clear OSGi caches", e);
70 }
71 }
72
73 public void validate(final String cacheValidationKey) {
74 ensureDirectoryExists(frameworkBundleCache);
75 ensureDirectoryExists(osgiBundleCache);
76 ensureDirectoryExists(transformedPluginCache);
77
78 try {
79 FileUtils.cleanDirectory(osgiBundleCache);
80 } catch (final IOException e) {
81 throw new OsgiContainerException("Unable to clean the cache directory: " + osgiBundleCache, e);
82 }
83
84 if (cacheValidationKey != null) {
85 final String newHash = Hashing.sha1().hashString(cacheValidationKey, Charsets.UTF_8).toString();
86 final File versionFile = new File(transformedPluginCache, "cache.key");
87 if (versionFile.exists()) {
88 String oldVersion = null;
89 try {
90 oldVersion = FileUtils.readFileToString(versionFile);
91 } catch (final IOException e) {
92 log.debug("Unable to read cache key file", e);
93 }
94 if (!newHash.equals(oldVersion)) {
95 log.info("Application upgrade detected, clearing OSGi cache directories");
96 clear();
97 } else {
98 return;
99 }
100 }
101
102 try {
103 FileUtils.writeStringToFile(versionFile, newHash);
104 } catch (final IOException e) {
105 log.warn("Unable to write cache key file, so will be unable to detect upgrades", e);
106 }
107 }
108 }
109
110 private void ensureDirectoryExists(final File dir) {
111 if (dir.exists() && !dir.isDirectory()) {
112 throw new IllegalArgumentException("'" + dir + "' is not a directory");
113 }
114
115 if (!dir.exists() && !dir.mkdir()) {
116 throw new IllegalArgumentException("Directory '" + dir + "' cannot be created");
117 }
118 }
119 }