Author: cziegeler Date: Wed Jan 12 11:00:27 2011 New Revision: 1058067 URL: http://svn.apache.org/viewvc?rev=1058067&view=rev Log: SLING-1923 : Improve the (internal) resource handling
Added: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java (contents, props changed) - copied, changed from r1057284, sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileUtil.java Removed: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileUtil.java Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/DictionaryDigestTest.java sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceComparatorTest.java sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceTest.java sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/EntityResourceList.java Wed Jan 12 11:00:27 2011 @@ -135,6 +135,9 @@ public class EntityResourceList implemen } } toActivate.setState(state); + if ( state == RegisteredResource.State.UNINSTALLED ) { + this.cleanup(toActivate); + } } } @@ -195,6 +198,9 @@ public class EntityResourceList implemen } } + /** + * Compact the resource group by removing uninstalled entries + */ public boolean compact() { boolean changed = false; final List<RegisteredResource> toDelete = new ArrayList<RegisteredResource>(); Copied: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java (from r1057284, sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileUtil.java) URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java?p2=sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java&p1=sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileUtil.java&r1=1057284&r2=1058067&rev=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileUtil.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java Wed Jan 12 11:00:27 2011 @@ -24,13 +24,16 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; import org.osgi.framework.BundleContext; +import org.slf4j.LoggerFactory; /** * Utility class for all file handling. */ -public class FileUtil { +public class FileDataStore { /** * The name of the bundle context property defining the location for the @@ -46,12 +49,16 @@ public class FileUtil { private final File directory; - public static FileUtil SHARED; + /** Public instance - to avoid passing a reference to this service to each data object. */ + public static FileDataStore SHARED; + + /** Cache for url to digest mapping. */ + private final Map<String, String> digestCache = new HashMap<String, String>(); /** * Create a file util instance and detect the installer directory. */ - public FileUtil( final BundleContext bundleContext ) { + public FileDataStore( final BundleContext bundleContext ) { String location = bundleContext.getProperty(CONFIG_DIR); // no configured location, use the config dir in the bundle persistent @@ -97,13 +104,6 @@ public class FileUtil { } /** - * Return the installer directory. - */ - public File getDirectory() { - return this.directory; - } - - /** * Return a file with the given name in the installer directory. * @param fileName The file name */ @@ -120,16 +120,46 @@ public class FileUtil { } } - /** Create a new unique data file. */ - public File createNewDataFile(final String hint) { + /** + * Create a new unique data file. + */ + public File createNewDataFile(final InputStream stream, + final String url, + final String digest, + final String hint) + throws IOException { + // check if we already have this data + if ( digest != null ) { + synchronized ( this.digestCache ) { + final String storedDigest = this.digestCache.get(url); + if ( storedDigest != null && storedDigest.equals(digest) ) { + return null; + } + } + } final String filename = hint + "-resource-" + getNextSerialNumber() + ".ser"; - return this.getDataFile(filename); + final File file = this.getDataFile(filename); + + this.copyToLocalStorage(stream, file); + + if ( digest != null ) { + synchronized ( this.digestCache ) { + this.digestCache.put(url, digest); + } + } + return file; + } + + public void updateDigestCache(final String url, final String digest) { + synchronized ( this.digestCache ) { + this.digestCache.put(url, digest); + } } /** * Copy data to local storage. */ - public void copyToLocalStorage(final InputStream data, + protected void copyToLocalStorage(final InputStream data, final File dataFile) throws IOException { final OutputStream os = new BufferedOutputStream(new FileOutputStream(dataFile)); try { @@ -143,4 +173,24 @@ public class FileUtil { os.close(); } } + + public File createNewDataFile(final String hint, final InputStream stream) + throws IOException { + final String filename = hint + "-resource-" + getNextSerialNumber() + ".ser"; + final File file = this.getDataFile(filename); + + this.copyToLocalStorage(stream, file); + + return file; + } + + public void removeFromDigestCache(final String url, final String digest) { + synchronized ( this.digestCache ) { + final String storedDigest = this.digestCache.get(url); + if ( storedDigest != null && storedDigest.equals(digest) ) { + LoggerFactory.getLogger(this.getClass()).warn("Remove {} : {}", url, digest); + this.digestCache.remove(url); + } + } + } } \ No newline at end of file Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java ------------------------------------------------------------------------------ svn:keywords = author date id revision rev url Propchange: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/FileDataStore.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/InternalResource.java Wed Jan 12 11:00:27 2011 @@ -85,14 +85,18 @@ public class InternalResource extends In digest = (resource.getDigest() != null && resource.getDigest().length() > 0 ? resource.getDigest() : resource.getId() + ":" + computeDigest(dict)); } else { + final String url = scheme + ':' + resource.getId(); // if input stream is not null, file is expected! - dataFile = FileUtil.SHARED.createNewDataFile(resource.getType()); - FileUtil.SHARED.copyToLocalStorage(is, dataFile); + dataFile = FileDataStore.SHARED.createNewDataFile(is, + url, + resource.getDigest(), + resource.getType()); type = (type != null ? type : InstallableResource.TYPE_FILE); if (resource.getDigest() != null && resource.getDigest().length() > 0) { digest = resource.getDigest(); } else { digest = computeDigest(dataFile); + FileDataStore.SHARED.updateDigestCache(url, digest); } } return new InternalResource(scheme, @@ -152,10 +156,6 @@ public class InternalResource extends In * Copy the given file and return it. */ public File getPrivateCopyOfFile() throws IOException { - if ( this.dataFile == null && this.getInputStream() != null ) { - this.dataFile = FileUtil.SHARED.createNewDataFile(this.getType()); - FileUtil.SHARED.copyToLocalStorage(this.getInputStream(), this.dataFile); - } return this.dataFile; } Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/OsgiInstallerImpl.java Wed Jan 12 11:00:27 2011 @@ -105,8 +105,8 @@ public class OsgiInstallerImpl public OsgiInstallerImpl(final BundleContext ctx) { this.ctx = ctx; // Initialize file util - new FileUtil(ctx); - final File f = FileUtil.SHARED.getDataFile("RegisteredResourceList.ser"); + new FileDataStore(ctx); + final File f = FileDataStore.SHARED.getDataFile("RegisteredResourceList.ser"); this.persistentList = new PersistentResourceList(f); } @@ -124,9 +124,6 @@ public class OsgiInstallerImpl ctx.removeBundleListener(this); ctx.removeFrameworkListener(this); - // remove file util - FileUtil.SHARED = null; - // wake up sleeping thread this.wakeUp(); this.logger.debug("Waiting for installer thread to stop"); @@ -136,6 +133,9 @@ public class OsgiInstallerImpl // we simply ignore this } + // remove file util + FileDataStore.SHARED = null; + this.logger.info("Apache Sling OSGi Installer Service stopped."); } Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/PersistentResourceList.java Wed Jan 12 11:00:27 2011 @@ -100,8 +100,30 @@ public class PersistentResourceList { } data = restoredData != null ? restoredData : new HashMap<String, EntityResourceList>(); this.unknownResources = unknownList != null ? unknownList : new ArrayList<RegisteredResource>(); + + this.updateCache(); + } + + /** + * Update the url to digest cache + */ + private void updateCache() { + for(final EntityResourceList group : this.data.values()) { + for(final RegisteredResource rr : group.getResources()) { + try { + if ( rr.getInputStream() != null ) { + FileDataStore.SHARED.updateDigestCache(rr.getURL(), rr.getDigest()); + } + } catch (final IOException ioe) { + // we just ignore this + } + } + } } + /** + * Persist the current state + */ public void save() { try { final ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(dataFile))); @@ -188,6 +210,9 @@ public class PersistentResourceList { } } + /** + * Remove a resource. + */ public void remove(final RegisteredResource r) { final EntityResourceList group = this.data.get(r.getEntityId()); if ( group != null ) { @@ -199,6 +224,9 @@ public class PersistentResourceList { return this.data.get(entityId); } + /** + * Compact the internal state and remove empty groups. + */ public boolean compact() { boolean changed = false; final Iterator<Map.Entry<String, EntityResourceList>> i = this.data.entrySet().iterator(); Modified: sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java (original) +++ sling/trunk/installer/core/src/main/java/org/apache/sling/installer/core/impl/RegisteredResourceImpl.java Wed Jan 12 11:00:27 2011 @@ -77,6 +77,8 @@ public class RegisteredResourceImpl /** Temporary attributes. */ private transient Map<String, Object> temporaryAttributes; + private boolean cleanedUp = false; + /** * Serialize the object * - write version id @@ -169,12 +171,23 @@ public class RegisteredResourceImpl } /** + * Remove the data file + */ + private void removeDataFile() { + if ( this.dataFile != null && this.dataFile.exists() ) { + dataFile.delete(); + } + } + + /** * Clean up used data files. */ public void cleanup() { - if ( this.dataFile != null && this.dataFile.exists() ) { - dataFile.delete(); - } + if ( !cleanedUp ) { + cleanedUp = true; + this.removeDataFile(); + FileDataStore.SHARED.removeFromDigestCache(this.url, this.digest); + } } /** @@ -397,9 +410,8 @@ public class RegisteredResourceImpl } if ( is != null ) { try { - final File newDataFile = FileUtil.SHARED.createNewDataFile(this.getType()); - FileUtil.SHARED.copyToLocalStorage(is, newDataFile); - this.cleanup(); + final File newDataFile = FileDataStore.SHARED.createNewDataFile(this.getType(), is); + this.removeDataFile(); this.dataFile = newDataFile; } finally { try { Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/DictionaryDigestTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/DictionaryDigestTest.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/DictionaryDigestTest.java (original) +++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/DictionaryDigestTest.java Wed Jan 12 11:00:27 2011 @@ -37,7 +37,7 @@ public class DictionaryDigestTest { } private InternalResource create(final InstallableResource is) throws IOException { - new FileUtil(new MockBundleContext()); + new FileDataStore(new MockBundleContext()); return InternalResource.create("test", is); } Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceComparatorTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceComparatorTest.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceComparatorTest.java (original) +++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceComparatorTest.java Wed Jan 12 11:00:27 2011 @@ -54,7 +54,7 @@ public class RegisteredResourceComparato data = new Hashtable<String, Object>(); data.put("foo", "bar"); } - new FileUtil(new MockBundleContext()); + new FileDataStore(new MockBundleContext()); final InstallableResource r = new InstallableResource(url, null, data, digest, null, priority); final InternalResource internal = InternalResource.create("test", r); final RegisteredResourceImpl rr = RegisteredResourceImpl.create(internal); Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceTest.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceTest.java (original) +++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/RegisteredResourceTest.java Wed Jan 12 11:00:27 2011 @@ -84,10 +84,12 @@ public class RegisteredResourceTest { final BundleContext bc = new MockBundleContext(); final File f = getTestBundle("testbundle-1.0.jar"); final InputStream s = new FileInputStream(f); - FileUtil.SHARED = new FileUtil(bc) { + FileDataStore.SHARED = new FileDataStore(bc) { @Override - public File createNewDataFile(final String hint) { + public File createNewDataFile(InputStream stream, String url, + String digest, String hint) throws IOException { + this.copyToLocalStorage(stream, localFile); return localFile; } @@ -161,7 +163,7 @@ public class RegisteredResourceTest { } private RegisteredResource create(final InstallableResource is) throws IOException { - new FileUtil(new MockBundleContext()); + new FileDataStore(new MockBundleContext()); final InternalResource internal = InternalResource.create("test", is); final RegisteredResourceImpl rr = RegisteredResourceImpl.create(internal); final TransformationResult tr = new DefaultTransformer().transform(rr); Modified: sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java URL: http://svn.apache.org/viewvc/sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java?rev=1058067&r1=1058066&r2=1058067&view=diff ============================================================================== --- sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java (original) +++ sling/trunk/installer/core/src/test/java/org/apache/sling/installer/core/impl/TaskOrderingTest.java Wed Jan 12 11:00:27 2011 @@ -50,7 +50,7 @@ public class TaskOrderingTest { } private static EntityResourceList getRegisteredResource(String url) throws IOException { - new FileUtil(new MockBundleContext()); + new FileDataStore(new MockBundleContext()); final InternalResource internal = InternalResource.create("test", new InstallableResource(url, null, new Hashtable<String, Object>(), null, null, null)); final RegisteredResourceImpl rr = RegisteredResourceImpl.create(internal);