# HG changeset patch # User Jaroslav Tulach # Date 1213429943 -7200 # Node ID 716af5f2ebd19a40371109c9ea0cce9d49218c36 # Parent a161a4cdb5972dd3fba69f1dd450739d8268c39e Switching to freeform project diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/build.xml --- a/samples/messagedigest/build.xml Sat Jun 14 09:52:22 2008 +0200 +++ b/samples/messagedigest/build.xml Sat Jun 14 09:52:23 2008 +0200 @@ -1,69 +1,80 @@ - - - - - Builds, tests, and runs the project messagedigest. - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-bridge/META-INF/services/org.apidesign.impl.security.friendapi.DigestProvider --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-bridge/META-INF/services/org.apidesign.impl.security.friendapi.DigestProvider Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,3 @@ +# this shall be in a separate module that provides the "bridge" +org.apidesign.impl.security.extension.BridgeToOldAlgorithmsProvider + diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-bridge/org/apidesign/impl/security/extension/BridgeToOld.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-bridge/org/apidesign/impl/security/extension/BridgeToOld.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,82 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.extension; + +import org.apidesign.api.security.Digest; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * + * @author Jaroslav Tulach + */ +public class BridgeToOld extends Provider { + + public BridgeToOld() { + super("spi.Digestor", 1.0, ""); + Security.addProvider(this); + } + + @Override + public synchronized Service getService(String type, String algorithm) { + if ("MessageDigest".equals(type)) { + Digest dig = Digest.getInstance(algorithm); + if (dig != null) { + return new ServiceImpl(dig, this, type, algorithm, "", Collections.emptyList(), Collections.emptyMap()); + } + } + return null; + } + + private static class ServiceImpl extends Service { + Digest dig; + + public ServiceImpl(Digest dig, Provider provider, String type, String algorithm, String className, List aliases, Map attributes) { + super(provider, type, algorithm, className, aliases, attributes); + this.dig = dig; + } + + @Override + public Object newInstance(Object constructorParameter) throws NoSuchAlgorithmException { + return new MessageDigest(getAlgorithm()) { + private byte[] res; + + @Override + protected void engineUpdate(byte input) { + ByteBuffer bb = ByteBuffer.wrap(new byte[] { input }); + res = dig.digest(bb); + } + + @Override + protected void engineUpdate(byte[] input, int offset, int len) { + ByteBuffer bb = ByteBuffer.wrap(input); + bb.position(offset); + bb.limit(offset + len); + res = dig.digest(bb); + } + + @Override + protected byte[] engineDigest() { + return res; + } + + @Override + protected void engineReset() { + dig = Digest.getInstance(getAlgorithm()); + } + }; + } + + + } + +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-bridge/org/apidesign/impl/security/extension/BridgeToOldAlgorithmsProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-bridge/org/apidesign/impl/security/extension/BridgeToOldAlgorithmsProvider.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.extension; + +import org.apidesign.impl.security.friendapi.DigestImplementation; +import org.apidesign.impl.security.friendapi.DigestProvider; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Jaroslav Tulach + */ +public class BridgeToOldAlgorithmsProvider implements DigestProvider { + + public DigestImplementation create(String algorithm) { + try { + final MessageDigest md = MessageDigest.getInstance(algorithm); + return new DigestImplementation(algorithm) { + + @Override + public void update(ByteBuffer bb) { + md.update(bb); + } + + @Override + public byte[] digest() { + return md.digest(); + } + }; + } catch (NoSuchAlgorithmException ex) { + Logger.getLogger(BridgeToOldAlgorithmsProvider.class.getName()).log(Level.INFO, null, ex); + return null; + } + } + + static { + new BridgeToOld(); + } +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-api/org/apidesign/api/security/Digest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-api/org/apidesign/api/security/Digest.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,44 @@ + +package org.apidesign.api.security; + +import java.nio.ByteBuffer; +import org.apidesign.impl.security.friendapi.DigestImplementation; +import org.apidesign.impl.security.friendapi.DigestProvider; +import java.util.ServiceLoader; + +/** MessageDigest extends MessageDigestSpi, that means the javadoc + * + * @author Jaroslav Tulach + */ +// BEGIN: day.end.bridges.Digest +public final class Digest { + private final DigestImplementation impl; + + /** Factory method is better than constructor */ + private Digest(DigestImplementation impl) { + this.impl = impl; + } + + /** Factory method to create digest for an algorithm. + */ + public static Digest getInstance(String algorithm) { + for (DigestProvider dp : ServiceLoader.load(DigestProvider.class)) { + DigestImplementation impl = dp.create(algorithm); + if (impl != null) { + return new Digest(impl); + } + } + throw new IllegalArgumentException(algorithm); + } + + // + // these methods are kept the same as in original MessageDigest, + // but for simplicity choose just some from the original API + // + + public byte[] digest(ByteBuffer bb) { + impl.update(bb); + return impl.digest(); + } +} +// END: day.end.bridges.Digest diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-api/org/apidesign/impl/security/friendapi/DigestImplementation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-api/org/apidesign/impl/security/friendapi/DigestImplementation.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,23 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.friendapi; + +import java.nio.ByteBuffer; + +/** + * + * @author Jaroslav Tulach + */ +public abstract class DigestImplementation { + final String name; + + protected DigestImplementation(String algorithm) { + this.name = algorithm; + } + + public abstract void update(ByteBuffer bb); + public abstract byte[] digest(); +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-api/org/apidesign/impl/security/friendapi/DigestProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-api/org/apidesign/impl/security/friendapi/DigestProvider.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,14 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.friendapi; + +/** + * + * @author Jaroslav Tulach + */ +public interface DigestProvider { + public abstract DigestImplementation create(String algorithm); +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-spi/META-INF/services/org.apidesign.impl.security.friendapi.DigestProvider --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-spi/META-INF/services/org.apidesign.impl.security.friendapi.DigestProvider Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,2 @@ +# this is a provider for the SPI, shall be in the same module as the api & spi +org.apidesign.impl.security.spi.DigestorProvider diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-spi/org/apidesign/impl/security/spi/DigestorAccessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-spi/org/apidesign/impl/security/spi/DigestorAccessor.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,35 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.spi; + +import java.nio.ByteBuffer; +import org.apidesign.spi.security.Digestor; + +/** + * + * @author jarda + */ +public abstract class DigestorAccessor { + private static DigestorAccessor INSTANCE; + + protected DigestorAccessor() { + assert INSTANCE == null; + INSTANCE = this; + } + + public static DigestorAccessor getDefault() { + try { + Class.forName(Digestor.class.getName(), true, DigestorAccessor.class.getClassLoader()); + return INSTANCE; + } catch (ClassNotFoundException ex) { + throw new IllegalStateException(ex); + } + } + + protected abstract byte[] digest(Digestor dig, Data data); + protected abstract Data create(Digestor dig, String algorithm); + protected abstract void update(Digestor dig, Data data, ByteBuffer input); +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-spi/org/apidesign/impl/security/spi/DigestorProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-spi/org/apidesign/impl/security/spi/DigestorProvider.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,61 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.impl.security.spi; + +import org.apidesign.impl.security.friendapi.DigestImplementation; +import org.apidesign.impl.security.friendapi.DigestProvider; +import java.nio.ByteBuffer; +import java.util.ServiceLoader; +import org.apidesign.spi.security.Digestor; + +/** + * + * @author Jaroslav Tulach + */ +public class DigestorProvider implements DigestProvider { + + public DigestImplementation create(String algorithm) { + for (Digestor d : ServiceLoader.load(Digestor.class)) { + Handler h = create(d, algorithm); + if (h != null) { + return h; + } + } + return null; + } + + private static Handler create(Digestor dig, String algorithm) { + Data d = DigestorAccessor.getDefault().create(dig, algorithm); + if (d == null) { + return null; + } else { + return new Handler(algorithm, dig, d); + } + } + + private static final class Handler extends DigestImplementation { + private final Digestor dig; + private final Data data; + + public Handler(String algorithm, Digestor dig, Data data) { + super(algorithm); + this.dig = dig; + this.data = data; + } + + + @Override + public void update(ByteBuffer bb) { + DigestorAccessor.getDefault().update(dig, data, bb); + } + + @Override + public byte[] digest() { + return DigestorAccessor.getDefault().digest(dig, data); + } + + } +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-new-spi/org/apidesign/spi/security/Digestor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-new-spi/org/apidesign/spi/security/Digestor.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,40 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package org.apidesign.spi.security; + +import org.apidesign.impl.security.spi.DigestorAccessor; +import java.nio.ByteBuffer; + +/** + * + * @author Jaroslav Tulach + */ +// BEGIN: day.end.bridges.Digestor +public abstract class Digestor { + protected abstract byte[] digest(Data data); + protected abstract Data create(String algorithm); + protected abstract void update(Data data, ByteBuffer input); + +// END: day.end.bridges.Digestor + static { + new DigestorAccessor() { + @Override + protected byte[] digest(Digestor dig, Data data) { + return dig.digest(data); + } + + @Override + protected Data create(Digestor dig, String algorithm) { + return dig.create(algorithm); + } + + @Override + protected void update(Digestor dig, Data data, ByteBuffer input) { + dig.update(data, input); + } + }; + } +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-test/META-INF/services/org.apidesign.spi.security.Digestor --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-test/META-INF/services/org.apidesign.spi.security.Digestor Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,3 @@ +# the provider registered from tests +test.CountingDigestor + diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-test/test/CountingDigestor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-test/test/CountingDigestor.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,35 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package test; + +import java.nio.ByteBuffer; +import org.apidesign.spi.security.Digestor; + +/** + * + * @author jarda + */ +public final class CountingDigestor extends Digestor { + + @Override + protected byte[] digest(int[] data) { + int i = data[0]; + byte[] arr = { (byte) (i & 255), (byte) ((i >> 8) & 255), (byte) ((i >> 16) & 255), (byte) ((i >> 24) & 255) }; + return arr; + } + + @Override + protected int[] create(String algorithm) { + return "cnt".equals(algorithm) ? new int[1] : null; // NOI18N + } + + @Override + protected void update(int[] data, ByteBuffer input) { + data[0] += input.remaining(); + input.position(input.position() + input.remaining()); + } + +} diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-test/test/NewAPIToOldAPITest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-test/test/NewAPIToOldAPITest.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,65 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package test; + +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Random; +import org.apidesign.api.security.Digest; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** Compares that the MessageDigest and Digest yield the same results for + * default provider. + * + * @author Jaroslav Tulach + */ +public class NewAPIToOldAPITest { + private static byte[] arr; + private static long time; + private static byte[] resOld; + private static byte[] resNew; + + public NewAPIToOldAPITest() { + } + + @BeforeClass + public static void setUp() { + time = System.currentTimeMillis(); + Random r = new Random(time); + arr = new byte[r.nextInt(1024)]; + r.nextBytes(arr); + } + + @After + public void tearDown() { + } + + @Test + public void generateHashUsingMessageDigest() throws Exception { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] res = md.digest(arr); + resOld = res; + } + + @Test + public void generateHashUsingNewDigest() throws Exception { + Digest d = Digest.getInstance("MD5"); + ByteBuffer bb = ByteBuffer.wrap(arr); + byte[] res = d.digest(bb); + resNew = res; + } + + @Test + public void compareTheHashes() throws Exception { + if (!Arrays.equals(resOld, resNew)) { + fail("Arrays are different:\n" + Arrays.toString(resOld) + "\n" + Arrays.toString(resNew)); + } + } +} \ No newline at end of file diff -r a161a4cdb597 -r 716af5f2ebd1 samples/messagedigest/src-test/test/OldAPIToNewAPITest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/messagedigest/src-test/test/OldAPIToNewAPITest.java Sat Jun 14 09:52:23 2008 +0200 @@ -0,0 +1,77 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +package test; + +import org.apidesign.api.security.*; +import java.nio.ByteBuffer; +import java.security.MessageDigest; +import java.util.Arrays; +import java.util.Random; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.junit.Assert.*; + +/** Compares that the MessageDigest and Digest yield the same results for + * default provider. + * + * @author Jaroslav Tulach + */ +public class OldAPIToNewAPITest { + private static byte[] arr; + private static long time; + private static byte[] resOld; + private static byte[] resNew; + + public OldAPIToNewAPITest() { + } + + @BeforeClass + public static void setUp() { + time = System.currentTimeMillis(); + Random r = new Random(time); + arr = new byte[r.nextInt(1024)]; + r.nextBytes(arr); + } + + @After + public void tearDown() { + } + + @Test + public void generateHashUsingMessageDigest() throws Exception { + // The java.security.Providers cannot be registered in META-INF/services + // that is why one needs to either configure various properties or + // make some dummy call that will initialize our bridge class. + // Then the bridge class registers itself as a MessageDigest provider + // in its constructor. + // + // This is the call: + Digest initialize = Digest.getInstance("MD5"); + + MessageDigest md = MessageDigest.getInstance("cnt"); + byte[] res = md.digest(arr); + resOld = res; + } + + + @Test + public void generateHashUsingNewDigest() throws Exception { + Digest d = Digest.getInstance("cnt"); + ByteBuffer bb = ByteBuffer.wrap(arr); + byte[] res = d.digest(bb); + resNew = res; + } + + + + @Test + public void compareTheHashes() throws Exception { + if (!Arrays.equals(resOld, resNew)) { + fail("Arrays are different:\n" + Arrays.toString(resOld) + "\n" + Arrays.toString(resNew)); + } + } +} \ No newline at end of file