com.limegroup.gnutella.licenses.CCLicenseTest.java Source code

Java tutorial

Introduction

Here is the source code for com.limegroup.gnutella.licenses.CCLicenseTest.java

Source

package com.limegroup.gnutella.licenses;

import java.io.*;
import java.util.*;

import junit.framework.Test;

import com.limegroup.gnutella.*;
import com.limegroup.gnutella.util.*;
import com.limegroup.gnutella.bootstrap.*;

import org.apache.commons.httpclient.*;

public final class CCLicenseTest extends BaseTestCase {

    private static final String RDF_GOOD = "<rdf:RDF xmlns=\"http://web.resource.org/cc/\""
            + "   xmlns:dc=\"http://purl.org/dc/elements/1.1/\""
            + "   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
            + "  <Work rdf:about=\"urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD\">" + "     <dc:date>2003</dc:date>"
            + "     <dc:format>audio/mpeg</dc:format>"
            + "     <dc:identifier>http://example.com/mp3s/test.mp3</dc:identifier>"
            + "     <dc:rights><Agent><dc:title>ExampleBand</dc:title></Agent></dc:rights>"
            + "     <dc:title>Example Song</dc:title>"
            + "     <dc:type rdf:resource=\"http://purl.org/dc/dcmitype/Sound\" />"
            + "     <license rdf:resource=\"http://creativecommons.org/licenses/by/2.0/\" />" + "  </Work>"
            + "  <License rdf:about=\"http://creativecommons.org/licenses/by/2.0/\">"
            + "     <requires rdf:resource=\"http://web.resource.org/cc/Attribution\" />"
            + "     <permits rdf:resource=\"http://web.resource.org/cc/Reproduction\" />"
            + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
            + "     <permits rdf:resource=\"http://web.resource.org/cc/DerivativeWorks\" />"
            + "     <prohibits rdf:resource=\"http://web.resource.org/cc/Fun\"/>"
            + "     <requires rdf:resource=\"http://web.resource.org/cc/Notice\" />" + "  </License>"
            + "</rdf:RDF>";

    public CCLicenseTest(String name) {
        super(name);
    }

    public static Test suite() {
        return buildTestSuite(CCLicenseTest.class);
    }

    /**
     * Runs this test individually.
     */
    public static void main(String[] args) {
        junit.textui.TestRunner.run(suite());
    }

    public void testBasicParsingRDF() throws Exception {
        URN good = URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN bad = URN.createSHA1Urn("urn:sha1:SAMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");

        License l = new StubCCLicense(RDF_GOOD);
        Callback c = new Callback();
        assertFalse(c.completed);
        assertFalse(l.isVerified());
        assertFalse(l.isVerifying());
        l.verify(c);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(good));
        assertFalse(l.isValid(bad));
        assertTrue(c.completed);
        assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(null).toExternalForm());
        assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(good).toExternalForm());
        assertEquals(null, l.getLicenseDeed(bad));
        // more stringent than necessary - asserting order too.
        String desc = "Permitted: Reproduction, Distribution, DerivativeWorks\n" + "Prohibited: Fun\n"
                + "Required: Attribution, Notice";
        assertEquals(desc, l.getLicenseDescription(null));
        assertEquals(desc, l.getLicenseDescription(good));
        assertEquals("Permissions unknown.", l.getLicenseDescription(bad));
    }

    public void testGuessLicenseDeed() throws Exception {
        License l = new StubCCLicense("", "");
        assertFalse(l.isVerified());
        assertNull(l.getLicenseDeed(null));

        l = new StubCCLicense("a license, http://creativecommons.org/licenses/mylicese is cool", "");
        assertFalse(l.isVerified());
        assertEquals("http://creativecommons.org/licenses/mylicese", l.getLicenseDeed(null).toExternalForm());

        l = new StubCCLicense("a license, http:// creativecommons.org/licenses/mylicese", "");
        assertFalse(l.isVerified());
        assertNull(l.getLicenseDeed(null));

        l = new StubCCLicense("http://creativecommons.org/licenses/me", "");
        assertEquals("http://creativecommons.org/licenses/me", l.getLicenseDeed(null).toExternalForm());

        l = new StubCCLicense("alazamhttp://creativecommons.org/licenses/me2", "");
        assertNull(l.getLicenseDeed(null));

        l = new StubCCLicense("http://limewire.org", "");
        assertNull(l.getLicenseDeed(null));

        l = new StubCCLicense("creativecommons.org/licenses", "");
        assertNull(l.getLicenseDeed(null));
    }

    public void testCopy() throws Exception {
        License l = new StubCCLicense("text1", "");
        assertEquals("text1", l.getLicense());
        assertEquals("http://1.2.3.4/page", l.getLicenseURI().toString());

        License l2 = l.copy("text3", new URI("http://uri.com".toCharArray()));
        assertEquals("text3", l2.getLicense());
        assertEquals("http://uri.com", l2.getLicenseURI().toString());
    }

    public void testSerializeAndDeserialize() throws Exception {
        License l = new StubCCLicense("license text", "");
        assertEquals("license text", l.getLicense());
        assertNull(l.getLicenseDeed(null));
        assertEquals("http://1.2.3.4/page", l.getLicenseURI().toString());
        assertEquals("Permissions unknown.", l.getLicenseDescription(null));
        assertFalse(l.isVerified());
        assertFalse(l.isValid(null));

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bout);
        out.writeObject(l);

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bin);
        l = (License) in.readObject();
        assertEquals(null, l.getLicense()); // CHANGE -- not serialized
        assertNull(l.getLicenseDeed(null));
        assertEquals(null, l.getLicenseURI()); // CHANGE -- not serialized
        assertEquals("Permissions unknown.", l.getLicenseDescription(null));
        assertTrue(l.isVerified()); // CHANGE -- becomes verified
        assertFalse(l.isValid(null));

        // Now try with a full out parsed License.
        l = new StubCCLicense("good license text", RDF_GOOD);
        l.verify(null);
        assertEquals("good license text", l.getLicense());
        assertTrue(l.isVerified());
        assertTrue(l.isValid(URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD")));
        assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(null).toString());
        // more stringent than necessary - asserting order too.
        assertEquals("Permitted: Reproduction, Distribution, DerivativeWorks\n" + "Prohibited: Fun\n"
                + "Required: Attribution, Notice", l.getLicenseDescription(null));

        bout = new ByteArrayOutputStream();
        out = new ObjectOutputStream(bout);
        out.writeObject(l);

        bin = new ByteArrayInputStream(bout.toByteArray());
        in = new ObjectInputStream(bin);
        l = (License) in.readObject();
        assertEquals(null, l.getLicense()); // CHANGE -- not serialized
        assertTrue(l.isVerified());
        assertTrue(l.isValid(URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD")));
        assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(null).toString());
        // more stringent than necessary - asserting order too.
        assertEquals("Permitted: Reproduction, Distribution, DerivativeWorks\n" + "Prohibited: Fun\n"
                + "Required: Attribution, Notice", l.getLicenseDescription(null));
    }

    public void testAdvancedRDFParsing() throws Exception {
        URN goodUrn = URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN goodUrn2 = URN.createSHA1Urn("urn:sha1:GOODC5VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN badUrn = URN.createSHA1Urn("urn:sha1:BADBC5VEUDLTC26UT5W7GZBAKZHCY2MD");

        // GOOD: within HTML comments.
        License l = new StubCCLicense("<html><--" + "<rdf:RDF xmlns=\"http://web.resource.org/cc/\""
                + "   xmlns:dc=\"http://purl.org/dc/elements/1.1/\""
                + "   xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "  <Work>"
                + "    <license rdf:resource=\"http://creativecommons.org/licenses/by/2.0/\" />" + "  </Work>"
                + "  <License />" + "</rdf:RDF>" + "--></html>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(null).toString());
        assertEquals("Permissions unknown.", l.getLicenseDescription(null));

        // BAD: No data.
        l = new StubCCLicense("<rdf:RDF/>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));

        // BAD: RDF not bound.
        l = new StubCCLicense("<rdf:RDF><Work/></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));

        // BAD: Work, no license for it.
        l = new StubCCLicense(
                "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"><Work/></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));

        // BAD: Work, Valid for specific URN, but no license for it.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<Work rdf:about=\"urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD\"/></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));
        assertFalse(l.isValid(goodUrn));

        // GOOD: Work, license.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work>"
                + "<license rdf:resource=\"http://creativecommons.org/licenses/by/2.0/\" />" + "</Work></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(goodUrn));
        assertTrue(l.isValid(badUrn));

        // GOOD: Work, license & URN.
        l = new StubCCLicense(
                "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work rdf:about=\""
                        + goodUrn + "\">" + "<license rdf:resource=\"http://mydeed.com\" />" + "</Work></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(goodUrn));
        assertEquals("http://mydeed.com", l.getLicenseDeed(goodUrn).toExternalForm());
        assertEquals("http://mydeed.com", l.getLicenseDeed(null).toExternalForm());
        assertFalse(l.isValid(badUrn));

        // GOOD: Multiple works, licenses & URNs.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<Work rdf:about=\"" + goodUrn + "\">" + "<license rdf:resource=\"http://deed1.com\" />"
                + "</Work>" + "<Work rdf:about=\"" + goodUrn2 + "\">"
                + "<license rdf:resource=\"http://deed2.com\" />" + "</Work>" + "</rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(goodUrn));
        assertTrue(l.isValid(goodUrn2));
        assertEquals("http://deed1.com", l.getLicenseDeed(goodUrn).toExternalForm());
        assertEquals("http://deed2.com", l.getLicenseDeed(goodUrn2).toExternalForm());
        assertFalse(l.isValid(badUrn));

        // No Work item.
        l = new StubCCLicense(
                "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<License/></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));

        // Valid, duplicate distribution permission ignored.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work>"
                + "<license rdf:resource=\"http://deed1.com\" />" + "</Work>"
                + "<License rdf:about=\"http://deed1.com\">"
                + "     <requires rdf:resource=\"http://web.resource.org/cc/Attribution\" />"
                + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
                + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
                + "     <permits rdf:resource=\"http://web.resource.org/cc/DerivativeWorks\" />"
                + "  </License></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertEquals("Permitted: Distribution, DerivativeWorks\n" + "Required: Attribution",
                l.getLicenseDescription(null));

        // Valid, unknown License element.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work>"
                + "<license rdf:resource=\"http://deed1.com\" />" + "</Work>"
                + "<License rdf:about=\"http://deed1.com\">"
                + "     <requires rdf:resource=\"http://web.resource.org/cc/Attribution\" />"
                + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
                + "     <unknown rdf:resource=\"http://web.resource.org/cc/Unknown\" />"
                + "     <permits rdf:resource=\"http://web.resource.org/cc/DerivativeWorks\" />"
                + "  </License></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertEquals("Permitted: Distribution, DerivativeWorks\n" + "Required: Attribution",
                l.getLicenseDescription(null));

        // Matches up the licenses among the multiple works correctly.
        // GOOD: Multiple works, licenses & URNs.
        l = new StubCCLicense(
                "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work rdf:about=\""
                        + goodUrn + "\">" + "<license rdf:resource=\"http://deed1.com\" />" + "</Work>"
                        + "<Work rdf:about=\"" + goodUrn2 + "\">" + "<license rdf:resource=\"http://deed2.com\" />"
                        + "</Work>" + "<License rdf:about=\"http://deed1.com\">"
                        + "     <requires rdf:resource=\"http://web.resource.org/cc/Attribution\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
                        + "     <prohibits rdf:resource=\"http://web.resource.org/cc/Evil\" />" + "  </License>"
                        + "<License rdf:about=\"http://deed2.com\">"
                        + "     <requires rdf:resource=\"http://web.resource.org/cc/Peace\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Love\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Happiness\" />" + "  </License>"
                        + "</rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(goodUrn));
        assertTrue(l.isValid(goodUrn2));
        assertEquals("http://deed1.com", l.getLicenseDeed(goodUrn).toExternalForm());
        assertEquals("http://deed2.com", l.getLicenseDeed(goodUrn2).toExternalForm());
        assertFalse(l.isValid(badUrn));
        assertEquals("Permitted: Distribution\n" + "Prohibited: Evil\n" + "Required: Attribution",
                l.getLicenseDescription(goodUrn));
        assertEquals("Permitted: Love, Happiness\n" + "Required: Peace", l.getLicenseDescription(goodUrn2));

        // Valid, unknown body element.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<Work><license rdf:resource=\"http://deed1.com\" /></Work>" + "<Unknown/></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));

        // Invalid -- Work is inside an unknown element.
        l = new StubCCLicense("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<Unknown><Work><license rdf:resource=\"http://deed1.com\" /></Work></Unknown></rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertFalse(l.isValid(null));
    }

    public void testMultipleLicenseElementsInWork() throws Exception {
        URN goodUrn = URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");

        License l = new StubCCLicense("http://creativecommons.org/licenses/mylicense verify at http://nowhere.com",
                "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work rdf:about=\""
                        + goodUrn + "\">" + "<license rdf:resource=\"http://deed1.com\" />"
                        + "<license rdf:resource=\"http://creativecommons.org/licenses/mylicense\" />"
                        + "<license rdf:resource=\"http://deed2.com\" />" + "</Work>"
                        + "<License rdf:about=\"http://deed1.com\">"
                        + "     <requires rdf:resource=\"http://web.resource.org/cc/Attribution\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Distribution\" />"
                        + "     <prohibits rdf:resource=\"http://web.resource.org/cc/Evil\" />" + "  </License>"
                        + "<License rdf:about=\"http://creativecommons.org/licenses/mylicense\">"
                        + "     <requires rdf:resource=\"http://web.resource.org/cc/Peace\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Love\" />"
                        + "     <permits rdf:resource=\"http://web.resource.org/cc/Happiness\" />" + "  </License>"
                        + "</rdf:RDF>");
        l.verify(null);
        assertTrue(l.isVerified());
        assertTrue(l.isValid(null));
        assertTrue(l.isValid(goodUrn));
        assertEquals("http://creativecommons.org/licenses/mylicense", l.getLicenseDeed(goodUrn).toExternalForm());
        assertEquals("Permitted: Love, Happiness\n" + "Required: Peace", l.getLicenseDescription(goodUrn));
    }

    public void testHTTPRetrieval() throws Exception {
        TestBootstrapServer server = new TestBootstrapServer(20181);
        URN good = URN.createSHA1Urn("urn:sha1:MSMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN bad = URN.createSHA1Urn("urn:sha1:SAMBC5VEUDLTC26UT5W7GZBAKZHCY2MD");
        try {
            server.setResponseData("<html><head>Hi</head><body><--\n" + RDF_GOOD + "\n--></body></html>");

            License l = LicenseFactory.create("verify at http://127.0.0.1:20181/");
            l.verify(null);
            Thread.sleep(1000);
            assertTrue(l.isVerified());
            assertTrue(l.isValid(null));
            assertTrue(l.isValid(good));
            assertFalse(l.isValid(bad));
            assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(good).toExternalForm());
            assertEquals("http://creativecommons.org/licenses/by/2.0/", l.getLicenseDeed(null).toExternalForm());
            assertEquals(null, l.getLicenseDeed(bad));
            // more stringent than necessary - asserting order too.
            String desc = "Permitted: Reproduction, Distribution, DerivativeWorks\n" + "Prohibited: Fun\n"
                    + "Required: Attribution, Notice";
            assertEquals(desc, l.getLicenseDescription(good));
            assertEquals(desc, l.getLicenseDescription(null));
            assertEquals("Permissions unknown.", l.getLicenseDescription(bad));
            assertEquals(1, server.getConnectionAttempts());
            assertEquals(1, server.getRequestAttempts());
        } finally {
            server.shutdown();
        }
    }

    public void testSeparateLicenseRetrieval() throws Exception {
        TestBootstrapServer deed1 = new TestBootstrapServer(11111);
        TestBootstrapServer deed2 = new TestBootstrapServer(22222);
        TestBootstrapServer deed3 = new TestBootstrapServer(33333);
        TestBootstrapServer server1 = new TestBootstrapServer(44444);
        TestBootstrapServer server2 = new TestBootstrapServer(55555);
        deed1.setAllowConnectionReuse(true);
        deed2.setAllowConnectionReuse(true);
        deed3.setAllowConnectionReuse(true);

        URN goodUrn1 = URN.createSHA1Urn("urn:sha1:GOOD15VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN goodUrn2 = URN.createSHA1Urn("urn:sha1:GOOD25VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN goodUrn3 = URN.createSHA1Urn("urn:sha1:GOOD35VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN goodUrn4 = URN.createSHA1Urn("urn:sha1:GOOD45VEUDLTC26UT5W7GZBAKZHCY2MD");
        URN badUrn = URN.createSHA1Urn("urn:sha1:BADAC5VEUDLTC26UT5W7GZBAKZHCY2MD");

        String rdf = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work rdf:about=\""
                + goodUrn1 + "\">" + "<license rdf:resource=\"http://127.0.0.1:11111\" />" + "</Work>"
                + "<Work rdf:about=\"" + goodUrn2 + "\">" + "<license rdf:resource=\"http://127.0.0.1:22222\" />"
                + "</Work>" + "<Work rdf:about=\"" + goodUrn3 + "\">"
                + "<license rdf:resource=\"http://127.0.0.1:33333\" />" + "</Work>" + "<Work rdf:about=\""
                + goodUrn4 + "\">" + "<license rdf:resource=\"http://deed4.com\" />" + "</Work>"
                + "<License rdf:about=\"http://deed4.com\">"
                + "<requires rdf:resource=\"http://web.resource.org/cc/Peace\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Love\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Happiness\" />" + "</License>" + "</rdf:RDF>";
        server1.setResponseData(rdf);
        server2.setResponseData(rdf);

        String data = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<License rdf:about=\"http://127.0.0.1:11111\">"
                + "<requires rdf:resource=\"http://web.resource.org/cc/War\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Hate\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Evil\" />" + "</License></rdf:RDF>";
        deed1.setResponseData(data);
        deed1.setResponse("HTTP/1.1 200 OK\r\nContent-Length: " + data.length());

        // throw in an extra work -- make sure it never is added.
        data = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" + "<Work rdf:about=\"" + badUrn
                + "\">" + "<license rdf:resource=\"http://deeddead.com\" />" + "</Work>"
                + "<License rdf:about=\"http://127.0.0.1:22222\">"
                + "<requires rdf:resource=\"http://web.resource.org/cc/Joy\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Fun\" />"
                + "<prohibits rdf:resource=\"http://web.resource.org/cc/Sadness\" />" + "</License></rdf:RDF>";
        deed2.setResponseData(data);
        deed2.setResponse("HTTP/1.1 200 OK\r\nContent-Length: " + data.length());

        data = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">"
                + "<License rdf:about=\"http://127.0.0.1:8080\">" + // wrong about!!
                "<requires rdf:resource=\"http://web.resource.org/cc/Beauty\" />"
                + "<permits rdf:resource=\"http://web.resource.org/cc/Models\" />"
                + "<prohibits rdf:resource=\"http://web.resource.org/cc/UglyPeople\" />" + "</License></rdf:RDF>";
        deed3.setResponseData(data);
        deed3.setResponse("HTTP/1.1 200 OK\r\nContent-Length: " + data.length());

        try {
            License l = LicenseFactory.create("verify at http://127.0.0.1:44444/");
            VerificationListener vl = new Listener();
            synchronized (vl) {
                l.verify(vl);
                vl.wait();
            }
            assertTrue(l.isVerified());
            assertTrue(l.isValid(null));
            assertTrue(l.isValid(goodUrn1));
            assertTrue(l.isValid(goodUrn2));
            assertTrue(l.isValid(goodUrn3));
            assertTrue(l.isValid(goodUrn4));
            assertFalse(l.isValid(badUrn));

            assertEquals("http://127.0.0.1:11111", l.getLicenseDeed(goodUrn1).toExternalForm());
            assertEquals("http://127.0.0.1:22222", l.getLicenseDeed(goodUrn2).toExternalForm());
            assertEquals("http://127.0.0.1:33333", l.getLicenseDeed(goodUrn3).toExternalForm());
            assertEquals("http://deed4.com", l.getLicenseDeed(goodUrn4).toExternalForm());
            assertEquals(null, l.getLicenseDeed(badUrn));

            // Alright -- these are the real tests.
            // Make sure that the license was picked up correctly!
            // (Order is Permit, Prohibit, Require)

            assertEquals("Permitted: Hate, Evil\n" + "Required: War", l.getLicenseDescription(goodUrn1));

            assertEquals("Permitted: Fun\n" + "Prohibited: Sadness\n" + "Required: Joy",
                    l.getLicenseDescription(goodUrn2));

            assertEquals("Permissions unknown.", l.getLicenseDescription(goodUrn3));

            assertEquals("Permitted: Love, Happiness\n" + "Required: Peace", l.getLicenseDescription(goodUrn4));

            assertEquals("Permissions unknown.", l.getLicenseDescription(badUrn));

            assertEquals(1, server1.getConnectionAttempts());
            assertEquals(1, server1.getRequestAttempts());
            assertEquals(0, server2.getConnectionAttempts());
            assertEquals(0, server2.getRequestAttempts());
            assertEquals(1, deed1.getConnectionAttempts());
            assertEquals(1, deed1.getRequestAttempts());
            assertEquals(1, deed2.getConnectionAttempts());
            assertEquals(1, deed2.getRequestAttempts());
            assertEquals(1, deed3.getConnectionAttempts());
            assertEquals(1, deed3.getRequestAttempts());

            // Okay -- now contact again for a new license.
            // The details should already have been cached for 11111 & 22222,
            // and even 33333 (even though it failed 'cause it had the wrong addr).

            l = LicenseFactory.create("verify at http://127.0.0.1:55555/");
            vl = new Listener();
            synchronized (vl) {
                l.verify(vl);
                vl.wait();
            }
            assertTrue(l.isVerified());
            assertTrue(l.isValid(null));
            assertTrue(l.isValid(goodUrn1));
            assertTrue(l.isValid(goodUrn2));
            assertTrue(l.isValid(goodUrn3));
            assertTrue(l.isValid(goodUrn4));
            assertFalse(l.isValid(badUrn));

            assertEquals("http://127.0.0.1:11111", l.getLicenseDeed(goodUrn1).toExternalForm());
            assertEquals("http://127.0.0.1:22222", l.getLicenseDeed(goodUrn2).toExternalForm());
            assertEquals("http://127.0.0.1:33333", l.getLicenseDeed(goodUrn3).toExternalForm());
            assertEquals("http://deed4.com", l.getLicenseDeed(goodUrn4).toExternalForm());
            assertEquals(null, l.getLicenseDeed(badUrn));

            // Alright -- these are the real tests.
            // Make sure that the license was picked up correctly!
            // (Order is Permit, Prohibit, Require)

            assertEquals("Permitted: Hate, Evil\n" + "Required: War", l.getLicenseDescription(goodUrn1));

            assertEquals("Permitted: Fun\n" + "Prohibited: Sadness\n" + "Required: Joy",
                    l.getLicenseDescription(goodUrn2));

            assertEquals("Permissions unknown.", l.getLicenseDescription(goodUrn3));

            assertEquals("Permitted: Love, Happiness\n" + "Required: Peace", l.getLicenseDescription(goodUrn4));

            assertEquals("Permissions unknown.", l.getLicenseDescription(badUrn));

            assertEquals(1, server1.getConnectionAttempts());
            assertEquals(1, server1.getRequestAttempts());
            assertEquals(1, server2.getConnectionAttempts());
            assertEquals(1, server2.getRequestAttempts());
            assertEquals(1, deed1.getConnectionAttempts());
            assertEquals(1, deed1.getRequestAttempts());
            assertEquals(1, deed2.getConnectionAttempts());
            assertEquals(1, deed2.getRequestAttempts());
            assertEquals(1, deed3.getConnectionAttempts());
            assertEquals(1, deed3.getRequestAttempts());
        } finally {
            server1.shutdown();
            server2.shutdown();
            deed1.shutdown();
            deed2.shutdown();
            deed3.shutdown();
        }
    }
}