incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bdelacre...@apache.org
Subject svn commit: r804142 - in /sling/trunk/installer/osgi/installer/src: main/java/org/apache/sling/osgi/installer/ main/java/org/apache/sling/osgi/installer/impl/ main/java/org/apache/sling/osgi/installer/impl/tasks/ test/java/org/apache/sling/osgi/install...
Date Fri, 14 Aug 2009 09:43:00 GMT
Author: bdelacretaz
Date: Fri Aug 14 09:42:59 2009
New Revision: 804142

URL: http://svn.apache.org/viewvc?rev=804142&view=rev
Log:
SLING-1078 - client must supply digest for InstallableResource that wraps an InputStream

Added:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiInstaller.java
      - copied, changed from r804107, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiController.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
      - copied, changed from r804107, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
Removed:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiController.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/InputStreamDigestTest.java
Modified:
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
    sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallRemoveTask.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
    sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/Utilities.java

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/InstallableResource.java
Fri Aug 14 09:42:59 2009
@@ -28,6 +28,7 @@
 public class InstallableResource {
 	private final String url;
 	private final String extension;
+	private final String digest;
 	private final InputStream inputStream;
 	private final Dictionary<String, Object> dictionary;
 	
@@ -37,22 +38,41 @@
 		this.extension = getExtension(url);
 		this.inputStream = null;
 		this.dictionary = null;
+		this.digest = null;
 	}
 	
-	/** Create a data object that wraps an InputStream */
-	public InstallableResource(String url, InputStream is) {
+	/** Create a data object that wraps an InputStream 
+	 *  @param url unique URL of the supplied data, must start with the scheme used 
+	 *     {@link OsgiInstaller#registerResources} call
+	 *  @param is the resource contents
+	 *  @param digest must be supplied by client. Does not need to be an actual digest
+	 *     of the contents, but must change if the contents change. Having this supplied
+	 *     by the client avoids having to compute real digests to find out if a resource
+	 *     has changed, which can be expensive.        
+	 */
+	public InstallableResource(String url, InputStream is, String digest) {
 		this.url = url;
 		this.extension = getExtension(url);
 		this.inputStream = is;
 		this.dictionary = null;
+		this.digest = digest;
 	}
 	
-	/** Create a data object that wraps a Dictionary */
+	/** Create a data object that wraps a Dictionary. Digest will be computed
+	 *  by the installer in this case, as configuration dictionaries are 
+	 *  usually small so computing a real digest to find out if they changed
+	 *  is ok.
+	 *  
+     *  @param url unique URL of the supplied data, must start with the scheme used 
+     *     {@link OsgiInstaller#registerResources} call
+     *  @param is the resource contents
+	 */
 	public InstallableResource(String url, Dictionary<String, Object> d) {
 		this.url = url;
 		this.extension = getExtension(url);
 		this.inputStream = null;
 		this.dictionary = d;
+        this.digest = null;
 	}
 
 	@Override
@@ -66,9 +86,9 @@
 		return (pos < 0 ? "" : url.substring(pos+1));
 	}
 	
-	/** Return this data's URL. It is opaque for the {@link OsgiController}
+	/** Return this data's URL. It is opaque for the {@link OsgiInstaller}
 	 * 	but the scheme must be the one used in the 
-	 * 	{@link OsgiController#registerResources} call.
+	 * 	{@link OsgiInstaller#registerResources} call.
 	 */
 	public String getURL() {
 		return url;
@@ -89,4 +109,8 @@
 	public Dictionary<String, Object> getDictionary() {
 		return dictionary;
 	}
+	
+	public String getDigest() {
+	    return digest;
+	}
 }

Copied: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiInstaller.java
(from r804107, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiController.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiInstaller.java?p2=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiInstaller.java&p1=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiController.java&r1=804107&r2=804142&rev=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiController.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/OsgiInstaller.java
Fri Aug 14 09:42:59 2009
@@ -22,21 +22,23 @@
 import java.util.Collection;
 import java.util.Map;
 
-/** Controller that installs/updates/removes InstallableData
- * 	in the OSGi framework. The client can register a number of such
- *  resources, and the controller decides based on the resource weights,
- *	bundle version numbers, etc. which ones are actually installed.
+/** OSGi Service that installs/updates/removes InstallableData
+ * 	in the OSGi framework. 
+ * 
+ *  The client can register a number of such resources, and the 
+ *  installer decides based on the resource weights, bundle version 
+ *  numbers, etc. which ones are actually installed.
  *
  *	An InstallableResource can be a bundle, a configuration, and later 
  *	we might support deployment packages as well.    	
  */
-public interface OsgiController {
+public interface OsgiInstaller {
 	
-	/** Provide the controller with the complete list of installable
+	/** Provide the installer with the complete list of installable
 	 * 	resources for a given client.
 	 * 
-	 * 	Client must call this at startup and/or when the controller 
-	 * 	service becomes available. The controller stores the list of
+	 * 	Client must call this at startup and/or when the installer 
+	 * 	service becomes available. The installer stores the list of
 	 * 	previously registered/added resources, compares with the new
 	 * 	list and removes resources that have disappeared.
 	 * 
@@ -46,14 +48,14 @@
 	 */
 	void registerResources(Collection<InstallableResource> data, String urlScheme) throws
IOException;
 	
-	/** Inform the controller that a resource is available for installation.
+	/** Inform the installer that a resource is available for installation.
 	 * 	also called if the resource has been modified since it was registered.
 	 */
 	void addResource(InstallableResource d) throws IOException;
 	
-	/** Inform the controller that a resource is no longer available */
+	/** Inform the installer that a resource is no longer available */
 	void removeResource(InstallableResource d) throws IOException;
 	
 	/** Return counters used for statistics, console display, testing, etc. */
 	Map<String, Long> getCounters();
-}
+}
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/Activator.java
Fri Aug 14 09:42:59 2009
@@ -20,7 +20,7 @@
 
 import java.util.Hashtable;
 
-import org.apache.sling.osgi.installer.OsgiController;
+import org.apache.sling.osgi.installer.OsgiInstaller;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
@@ -43,7 +43,7 @@
     private ServiceTracker startLevelTracker;
     private ServiceTracker packageAdminTracker;
     private ServiceTracker logServiceTracker;
-    private OsgiControllerImpl osgiControllerService;
+    private OsgiInstallerImpl osgiControllerService;
     private ServiceRegistration osgiControllerServiceReg;
     
     private static long eventsCount;
@@ -71,11 +71,11 @@
             
             // Assume PackageAdmin is available before this bundle is started.
             // That's the case when using Felix OSGi, not sure about other frameworks.
-            this.osgiControllerService = new OsgiControllerImpl(context,
+            this.osgiControllerService = new OsgiInstallerImpl(context,
                     (PackageAdmin)checkNotNull(this.packageAdminTracker.getService(), "PackageAdmin"),
                     logServiceTracker);
             final String [] serviceInterfaces = {
-                    OsgiController.class.getName()
+                    OsgiInstaller.class.getName()
             };
             osgiControllerServiceReg = context.registerService(serviceInterfaces, osgiControllerService,
props);
         }

Copied: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
(from r804107, sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java)
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java?p2=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java&p1=sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java&r1=804107&r2=804142&rev=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiControllerImpl.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/OsgiInstallerImpl.java
Fri Aug 14 09:42:59 2009
@@ -24,7 +24,7 @@
 import java.util.Map;
 
 import org.apache.sling.osgi.installer.InstallableResource;
-import org.apache.sling.osgi.installer.OsgiController;
+import org.apache.sling.osgi.installer.OsgiInstaller;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.cm.ConfigurationAdmin;
@@ -32,15 +32,15 @@
 import org.osgi.service.packageadmin.PackageAdmin;
 import org.osgi.util.tracker.ServiceTracker;
 
-/** OsgiController service */
-public class OsgiControllerImpl implements OsgiController, OsgiControllerContext {
+/** OsgiInstaller service implementation */
+public class OsgiInstallerImpl implements OsgiInstaller, OsgiControllerContext {
 
 	private final BundleContext bundleContext;
     private final PackageAdmin packageAdmin;
     private final ServiceTracker logServiceTracker;
     private Map<String, Long> counters = new HashMap<String, Long>();
 
-    public OsgiControllerImpl(final BundleContext bc,
+    public OsgiInstallerImpl(final BundleContext bc,
                               final PackageAdmin pa,
                               final ServiceTracker logServiceTracker)
     throws IOException {
@@ -52,7 +52,7 @@
     public void deactivate() {
         if(getLogService() != null) {
             getLogService().log(LogService.LOG_WARNING,
-                    OsgiController.class.getName()
+                    OsgiInstaller.class.getName()
                     + " service deactivated - this warning can be ignored if system is shutting
down");
         }
     }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/RegisteredResource.java
Fri Aug 14 09:42:59 2009
@@ -31,8 +31,12 @@
 import java.math.BigInteger;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Dictionary;
+import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 
@@ -58,6 +62,8 @@
 	public RegisteredResource(BundleContext ctx, InstallableResource input) throws IOException
{
 		url = input.getUrl();
 		
+		// TODO if input.url ends with a "config" extension, convert to dictionary
+		
 		try {
 			if(input.getDictionary() == null) {
 				dictionary = null;
@@ -65,12 +71,16 @@
 					throw new IllegalArgumentException("input provides no Dictionary and no InputStream:"
+ input);
 				} else {
 					dataFile = getDataFile(ctx);
-					digest = copyToLocalStorage(input.getInputStream(), dataFile);
+					copyToLocalStorage(input.getInputStream(), dataFile);
+					digest = input.getDigest();
+					if(digest == null || digest.length() == 0) {
+					    throw new IllegalArgumentException(
+					            "Digest must be supplied for an InstallableResource that wraps an InputStream");
+					}
 				}
 			} else {
-				// TODO Copy dictionary
 				dataFile = null;
-				dictionary = input.getDictionary();
+				dictionary = copy(input.getDictionary());
 				digest = computeDigest(dictionary);
 			}
 			
@@ -135,16 +145,14 @@
         return new String(bigInt.toString(16));
     }
     
-    /** Copy data to local storage and return digest */
-	private String copyToLocalStorage(InputStream data, File f) throws IOException, NoSuchAlgorithmException
{
-        final MessageDigest d = MessageDigest.getInstance(DIGEST_TYPE);
+    /** Copy data to local storage */
+	private void copyToLocalStorage(InputStream data, File f) throws IOException, NoSuchAlgorithmException
{
 		final OutputStream os = new BufferedOutputStream(new FileOutputStream(f));
 		try {
 			final byte[] buffer = new byte[16384];
 			int count = 0;
 			while( (count = data.read(buffer, 0, buffer.length)) > 0) {
 				os.write(buffer, 0, count);
-				d.update(buffer, 0, count);
 			}
 			os.flush();
 		} finally {
@@ -152,7 +160,6 @@
 				os.close();
 			}
 		}
-		return digestToString(d);
 	}
 	
 	/** Convert InputStream to Dictionary using our extended properties format,
@@ -169,4 +176,19 @@
         }
         return result;
 	}
+	
+	/** Copy given Dictionary, sorting keys */
+	static Dictionary<String, Object> copy(Dictionary<String, Object> d) {
+	    final Dictionary<String, Object> result = new Hashtable<String, Object>();
+	    final List<String> keys = new ArrayList<String>();
+	    final Enumeration<String> e = d.keys();
+	    while(e.hasMoreElements()) {
+	        keys.add(e.nextElement());
+	    }
+	    Collections.sort(keys);
+	    for(String key : keys) {
+	        result.put(key, d.get(key));
+	    }
+	    return result;
+	}
 }

Modified: sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallRemoveTask.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallRemoveTask.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallRemoveTask.java
(original)
+++ sling/trunk/installer/osgi/installer/src/main/java/org/apache/sling/osgi/installer/impl/tasks/BundleInstallRemoveTask.java
Fri Aug 14 09:42:59 2009
@@ -24,7 +24,7 @@
 import java.util.jar.Manifest;
 
 import org.apache.sling.osgi.installer.impl.OsgiControllerContext;
-import org.apache.sling.osgi.installer.impl.OsgiControllerImpl;
+import org.apache.sling.osgi.installer.impl.OsgiInstallerImpl;
 import org.apache.sling.osgi.installer.impl.RegisteredResource;
 import org.apache.sling.osgi.installer.impl.Storage;
 import org.osgi.framework.Bundle;

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
(original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/RegisteredResourceTest.java
Fri Aug 14 09:42:59 2009
@@ -20,11 +20,13 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.FilterInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Hashtable;
 
 import org.apache.sling.osgi.installer.InstallableResource;
 
@@ -49,7 +51,7 @@
 		}
 		
 		final TestInputStream t = new TestInputStream(new ByteArrayInputStream(data.getBytes()));
-		final InstallableResource ir = new InstallableResource(data, t);
+		final InstallableResource ir = new InstallableResource(data, t, "somedigest");
 		assertEquals("TestInputStream must not be closed before test", 0, t.closeCount);
 		new LocalFileRegisteredResource(ir);
 		assertEquals("TestInputStream must be closed by RegisteredResource", 1, t.closeCount);
@@ -58,9 +60,42 @@
 	@org.junit.Test public void testLocalFileCopy() throws Exception {
 		final String data = "This is some data";
 		final InputStream in = new ByteArrayInputStream(data.getBytes());
-		final LocalFileRegisteredResource r = new LocalFileRegisteredResource(new InstallableResource(data,
in));
+		final LocalFileRegisteredResource r = new LocalFileRegisteredResource(new InstallableResource(data,
in, "somedigest"));
 		assertTrue("Local file exists", r.getDataFile(null).exists());
 		assertEquals("Local file length matches our data", data.getBytes().length, r.getDataFile(null).length());
 	}
 	
-}
+    @org.junit.Test public void testMissingDigest() throws Exception {
+        final String data = "This is some data";
+        final InputStream in = new ByteArrayInputStream(data.getBytes());
+        try {
+            new LocalFileRegisteredResource(new InstallableResource(data, in, null));
+            fail("Expected an IllegalArgumentException as digest is null");
+        } catch(IllegalArgumentException asExpected) {
+        }
+    }
+    
+    @org.junit.Test public void testDictionaryDigestOutOfOrderData() throws Exception {
+        final Hashtable<String, Object> d1 = new Hashtable<String, Object>();
+        final Hashtable<String, Object> d2 = new Hashtable<String, Object>();
+        
+        final String [] keys = { "foo", "bar", "something" };
+        for(int i=0 ; i < keys.length; i++) {
+            d1.put(keys[i], keys[i] + "." + keys[i]);
+        }
+        for(int i=keys.length - 1 ; i >= 0; i--) {
+            d2.put(keys[i], keys[i] + "." + keys[i]);
+        }
+        
+        final RegisteredResource r1 = new RegisteredResource(null, new InstallableResource("url1",
d1));
+        final RegisteredResource r2 = new RegisteredResource(null, new InstallableResource("url1",
d2));
+        
+        assertEquals(
+                "Two RegisteredResource with same values but different key orderings must
have the same key", 
+                r1.getDigest(),
+                r2.getDigest()
+        );
+        
+        // TODO do the same test starting with an InputStream, for configs
+    }
+}
\ No newline at end of file

Modified: sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/Utilities.java
URL: http://svn.apache.org/viewvc/sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/Utilities.java?rev=804142&r1=804141&r2=804142&view=diff
==============================================================================
--- sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/Utilities.java
(original)
+++ sling/trunk/installer/osgi/installer/src/test/java/org/apache/sling/osgi/installer/impl/Utilities.java
Fri Aug 14 09:42:59 2009
@@ -30,7 +30,7 @@
         return result;
     }
     
-    static void setStorage(OsgiControllerImpl c, Storage s) throws Exception {
+    static void setStorage(OsgiInstallerImpl c, Storage s) throws Exception {
         final Field f = c.getClass().getDeclaredField("storage");
         f.setAccessible(true);
         f.set(c, s);



Mime
View raw message