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 org.apache.commons.io.FileUtils;
6 import org.slf4j.Logger;
7 import org.slf4j.LoggerFactory;
8
9 import java.io.File;
10 import java.io.IOException;
11
12 import static com.google.common.base.Preconditions.checkNotNull;
13 import static com.google.common.base.Preconditions.checkState;
14
15
16
17
18
19
20 public class DefaultOsgiPersistentCache implements OsgiPersistentCache
21 {
22 private final File osgiBundleCache;
23 private final File frameworkBundleCache;
24 private final File transformedPluginCache;
25 private final Logger log = LoggerFactory.getLogger(DefaultOsgiPersistentCache.class);
26
27
28
29
30
31 public DefaultOsgiPersistentCache(final File baseDir)
32 {
33 checkState(checkNotNull(baseDir).exists(), "The base directory for OSGi persistent caches should exist, %s", baseDir);
34 osgiBundleCache = new File(baseDir, "felix");
35 frameworkBundleCache = new File(baseDir, "framework-bundles");
36 transformedPluginCache = new File(baseDir, "transformed-plugins");
37 validate(null);
38 }
39
40
41
42
43
44 @Deprecated
45 public DefaultOsgiPersistentCache(final File baseDir, final String applicationVersion)
46 {
47 this(baseDir);
48 }
49
50 public File getFrameworkBundleCache()
51 {
52 return frameworkBundleCache;
53 }
54
55 public File getOsgiBundleCache()
56 {
57 return osgiBundleCache;
58 }
59
60 public File getTransformedPluginCache()
61 {
62 return transformedPluginCache;
63 }
64
65 public void clear() throws OsgiContainerException
66 {
67 try
68 {
69 FileUtils.cleanDirectory(frameworkBundleCache);
70 FileUtils.cleanDirectory(osgiBundleCache);
71 FileUtils.cleanDirectory(transformedPluginCache);
72 }
73 catch (final IOException e)
74 {
75 throw new OsgiContainerException("Unable to clear OSGi caches", e);
76 }
77 }
78
79 public void validate(final String cacheValidationKey)
80 {
81 ensureDirectoryExists(frameworkBundleCache);
82 ensureDirectoryExists(osgiBundleCache);
83 ensureDirectoryExists(transformedPluginCache);
84
85 try
86 {
87 FileUtils.cleanDirectory(osgiBundleCache);
88 }
89 catch (final IOException e)
90 {
91 throw new OsgiContainerException("Unable to clean the cache directory: " + osgiBundleCache, e);
92 }
93
94 if (cacheValidationKey != null)
95 {
96 final String newHash = String.valueOf(cacheValidationKey.hashCode());
97 final File versionFile = new File(transformedPluginCache, "cache.key");
98 if (versionFile.exists())
99 {
100 String oldVersion = null;
101 try
102 {
103 oldVersion = FileUtils.readFileToString(versionFile);
104 }
105 catch (final IOException e)
106 {
107 log.debug("Unable to read cache key file", e);
108 }
109 if (!newHash.equals(oldVersion))
110 {
111 log.info("Application upgrade detected, clearing OSGi cache directories");
112 clear();
113 }
114 else
115 {
116 return;
117 }
118 }
119
120 try
121 {
122 FileUtils.writeStringToFile(versionFile, newHash);
123 }
124 catch (final IOException e)
125 {
126 log.warn("Unable to write cache key file, so will be unable to detect upgrades", e);
127 }
128 }
129 }
130
131 private void ensureDirectoryExists(final File dir)
132 {
133 if (dir.exists() && !dir.isDirectory())
134 {
135 throw new IllegalArgumentException("'"+dir+"' is not a directory");
136 }
137
138 if (!dir.exists() && !dir.mkdir())
139 {
140 throw new IllegalArgumentException("Directory '"+dir+"' cannot be created");
141 }
142 }
143 }