/* * Copyright (c) 2002-2007 Sun Microsystems, Inc. All rights reserved. * * The Sun Project JXTA(TM) Software License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by Sun Microsystems, Inc. for JXTA(TM) technology." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must * not be used to endorse or promote products derived from this software * without prior written permission. For written permission, please contact * Project JXTA at http://www.jxta.org. * * 5. Products derived from this software may not be called "JXTA", nor may * "JXTA" appear in their name, without prior written permission of Sun. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * JXTA is a registered trademark of Sun Microsystems, Inc. in the United * States and other countries. * * Please see the license information page at : * <http://www.jxta.org/project/www/license.html> for instructions on use of * the license in source files. * * ==================================================================== * * This software consists of voluntary contributions made by many individuals * on behalf of Project JXTA. For more information on Project JXTA, please see * http://www.jxta.org. * * This license is based on the BSD license adopted by the Apache Foundation. */ package net.jxta.impl.peergroup; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import junit.framework.JUnit4TestAdapter; import net.jxta.discovery.DiscoveryService; import net.jxta.document.AdvertisementFactory; import net.jxta.document.Element; import net.jxta.document.MimeMediaType; import net.jxta.document.XMLElement; import net.jxta.id.IDFactory; import net.jxta.impl.protocol.PeerGroupConfigAdv; import net.jxta.impl.protocol.PeerGroupConfigFlag; import net.jxta.peergroup.PeerGroup; import net.jxta.peergroup.PeerGroupID; import net.jxta.platform.JxtaLoader; import net.jxta.platform.Module; import net.jxta.platform.ModuleClassID; import net.jxta.platform.ModuleSpecID; import net.jxta.platform.NetworkManager; import net.jxta.protocol.ModuleImplAdvertisement; import net.jxta.protocol.PeerGroupAdvertisement; import net.jxta.test.util.TempDir; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class PeerGroupTest { static final Logger LOG = Logger.getLogger(PeerGroupTest.class.getName()); static TempDir home; static NetworkManager netMan; static PeerGroup pg1; PeerGroup pg11; PeerGroup pg111; PeerGroup pg12; PeerGroup pg121; ModuleImplAdvertisement pojoMIA; ModuleImplAdvertisement moduleMIA; public static junit.framework.Test suite() { return new JUnit4TestAdapter(PeerGroupTest.class); } @BeforeClass public static void setupClass() throws Exception { LOG.info("============ Begin setupClass"); home = new TempDir(); netMan = new NetworkManager(NetworkManager.ConfigMode.ADHOC, "test"); netMan.setInstanceHome(home.toURI()); pg1 = netMan.startNetwork(); netMan.waitForRendezvousConnection(1000); LOG.finest("NPG PGA: " + pg1.getPeerGroupAdvertisement()); LOG.info("============ End setupClass"); } @AfterClass public static void tearDownClass() throws InterruptedException { LOG.info("============ Begin tearDownClass"); home.delete(); netMan.stopNetwork(); LOG.info("============ End tearDownClass"); } @Before public void setup() throws Exception { LOG.info("============ Begin setup"); PeerGroupAdvertisement pga; /* * We now create a tree of peer groups for testign various * scenarios. */ pga = createGroupAdv(pg1.getDiscoveryService(), "pg11"); pg11 = pg1.newGroup(pga); pga = createGroupAdv(pg11.getDiscoveryService(), "pg111"); pg111 = pg11.newGroup(pga); pga = createGroupAdv(pg1.getDiscoveryService(), "pg12"); pg12 = pg1.newGroup(pga); pga = createGroupAdv(pg12.getDiscoveryService(), "pg121", PeerGroupConfigFlag.SHUNT_PARENT_CLASSLOADER); pg121 = pg12.newGroup(pga); /* * Setup some stuff to load. */ URL testJar = getClass().getResource("/TestJar.jar"); assertNotNull("TestJar could not be located", testJar); ModuleClassID baseClass = IDFactory.newModuleClassID(); pojoMIA = (ModuleImplAdvertisement) AdvertisementFactory.newAdvertisement( ModuleImplAdvertisement.getAdvertisementType()); pojoMIA.setModuleSpecID(IDFactory.newModuleSpecID(baseClass)); pojoMIA.setCode("TestPOJO"); pojoMIA.setUri(testJar.toString()); pojoMIA.setCompat(pg1.getAllPurposePeerGroupImplAdvertisement().getCompat()); pojoMIA.setDescription("Test non-Module in a jar"); moduleMIA = (ModuleImplAdvertisement) AdvertisementFactory.newAdvertisement( ModuleImplAdvertisement.getAdvertisementType()); moduleMIA.setModuleSpecID(IDFactory.newModuleSpecID(baseClass)); moduleMIA.setCode("TestModule"); moduleMIA.setUri(testJar.toString()); moduleMIA.setCompat(pg1.getAllPurposePeerGroupImplAdvertisement().getCompat()); moduleMIA.setDescription("Test Module in a jar"); LOG.info("============ End setup"); } @After public void tearDown() throws Exception { LOG.info("============ Begin tearDown"); pg111.unref(); pg11.unref(); pg121.unref(); pg12.unref(); Thread.sleep(300); LOG.info("============ End tearDown"); } @Test public void newGroupFromAdv() { try { ModuleClassID baseClass = IDFactory.newModuleClassID(); ModuleSpecID msid = IDFactory.newModuleSpecID(baseClass); ModuleImplAdvertisement mia = pg1.getAllPurposePeerGroupImplAdvertisement(); mia.setModuleSpecID(msid); LOG.info("New MIA:\n" + mia); pg1.getDiscoveryService().publish(mia); PeerGroupAdvertisement pga = (PeerGroupAdvertisement) AdvertisementFactory.newAdvertisement(PeerGroupAdvertisement.getAdvertisementType()); pga.setPeerGroupID(IDFactory.newPeerGroupID()); pga.setModuleSpecID(mia.getModuleSpecID()); LOG.info("New PGA:\n" + pga); PeerGroup newpg = pg1.newGroup(pga); assertTrue("Group id should match", newpg.getPeerGroupID().equals(pga.getPeerGroupID())); newpg.unref(); newpg = null; } catch (Exception caught) { LOG.log(Level.SEVERE, "Caught exception", caught); fail("exception thrown : " + caught.getMessage()); } } @Test public void newGroupFromParams() { try { ModuleImplAdvertisement mia = pg1.getAllPurposePeerGroupImplAdvertisement(); pg1.getDiscoveryService().publish(mia); PeerGroupID pgid = IDFactory.newPeerGroupID(); PeerGroup newpg = pg1.newGroup(pgid, mia, "test", "testdesc"); assertTrue("Group id should match", newpg.getPeerGroupID().equals(pgid)); newpg.unref(); newpg = null; newpg = pg1.newGroup(null, mia, null, null); assertTrue("Group id should match", !newpg.getPeerGroupID().equals(pg1.getPeerGroupID())); newpg.unref(); newpg = null; } catch (Exception caught) { caught.printStackTrace(); fail("exception thrown : " + caught.getMessage()); } } @Test public void newFromID() { try { PeerGroup newpg = pg1.newGroup(PeerGroupID.defaultNetPeerGroupID); assertTrue("Group id should match", newpg.getPeerGroupID().equals(PeerGroupID.defaultNetPeerGroupID)); newpg.unref(); newpg = null; } catch (Exception caught) { caught.printStackTrace(); fail("exception thrown : " + caught.getMessage()); } } /** * Verify that the static loader by default cannot load the class in * our test jar. */ @Test public void staticJxtaLoader() { ClassLoader loader = GenericPeerGroup.getJxtaLoader(); try { Class clazz = loader.loadClass("TestClass"); fail("Static loader could see the test class: " + clazz); } catch (ClassNotFoundException cnfx) { // Good. Fall through. } } /** * Make sure the PeerGroups dont use, but inherit the static loader. * This will make it easier to remove the static loader altogether at * some point in the future. */ @Test public void staticInheritedOnly() { JxtaLoader staticLoader = GenericPeerGroup.getJxtaLoader(); PeerGroup group = pg111; do { PeerGroup parentGroup = group.getParentGroup(); JxtaLoader groupLoader = group.getLoader(); // Make sure the groupLoader is not the staticLoader if (groupLoader == staticLoader) { fail("groupLoader should never be the staticLoader"); } if (parentGroup == null) { // Make sure our class loader's parent loader is staticLoader ClassLoader rootLoader = groupLoader.getParent(); if (rootLoader != staticLoader) { fail("root loader was not staticLoader"); } } group = parentGroup; } while (group != null); } /** * Make sure each group has it's own, unique loader instance */ @Test public void uniqueGroupLoaders() { JxtaLoader lastLoader = null; PeerGroup group = pg111; do { if (lastLoader == group.getLoader()) { fail("Group loader was not unique"); } lastLoader = group.getLoader(); group = group.getParentGroup(); } while (group != null); } /** * Test class loading inheritance. */ @Test public void classLoadingInheritance() { assertFlagState(pg11, PeerGroupConfigFlag.SHUNT_PARENT_CLASSLOADER, false); assertFlagState(pg111, PeerGroupConfigFlag.SHUNT_PARENT_CLASSLOADER, false); // Define it pg11.getLoader().defineClass(moduleMIA); Class<? extends Module> mod11 = null; try { mod11 = pg11.getLoader().loadClass(moduleMIA.getModuleSpecID()); } catch (ClassNotFoundException cnfx) { fail("Could not load moduleMIA into pg11"); } // Check that child inherits the same definition Class<? extends Module> mod111 = null; try { mod111 = pg111.getLoader().loadClass(moduleMIA.getModuleSpecID()); } catch (ClassNotFoundException cnfx) { fail("Could not load moduleMIA from child group pg111"); } assertSame(mod11, mod111); // Check that the parent is unable to load it Class<? extends Module> mod1 = null; try { mod1 = pg1.getLoader().loadClass(moduleMIA.getModuleSpecID()); fail("Parent group pg1 was able to load moduleMIA"); } catch (ClassNotFoundException cnfx) { // Good } // Check that the peer is unable to load it Class<? extends Module> mod12 = null; try { mod1 = pg12.getLoader().loadClass(moduleMIA.getModuleSpecID()); fail("Parent group pg12 was able to load moduleMIA"); } catch (ClassNotFoundException cnfx) { // Good } } /** * Test parent classloading disable flag. */ @Test public void testParentClassLoadDisabled() { assertFlagState(pg12, PeerGroupConfigFlag.SHUNT_PARENT_CLASSLOADER, false); assertFlagState(pg121, PeerGroupConfigFlag.SHUNT_PARENT_CLASSLOADER, true); // Define it LOG.info("Defining Module in pg12"); pg12.getLoader().defineClass(moduleMIA); LOG.info("Checking for Module in pg12"); Class<? extends Module> mod12 = null; try { mod12 = pg12.getLoader().loadClass(moduleMIA.getModuleSpecID()); } catch (ClassNotFoundException cnfx) { fail("Could not load moduleMIA into pg12"); } // Check that child does not load it from it's parent LOG.info("Checking for Module in pg121"); Class<? extends Module> mod121 = null; try { mod121 = pg121.getLoader().loadClass(moduleMIA.getModuleSpecID()); fail("pg121 was able to load the module from it's parent"); } catch (ClassNotFoundException cnfx) { // Good } } /////////////////////////////////////////////////////////////////////////// // Private methods: /** * Creates a peer group advertisement set for testing. * * @param disco discovery service to publish into * @param name peer group name * @return peer group advertisement * @throws java.lang.Exception on error */ private PeerGroupAdvertisement createGroupAdv( DiscoveryService disco, String name, PeerGroupConfigFlag ... flags) throws Exception { ModuleClassID mcid = IDFactory.newModuleClassID(); ModuleImplAdvertisement mia = pg1.getAllPurposePeerGroupImplAdvertisement(); ModuleSpecID msid = IDFactory.newModuleSpecID(mcid); mia.setDescription(name + " impl"); mia.setModuleSpecID(msid); disco.publish(mia); LOG.finest(name + " MIA:\n" + mia); PeerGroupID pgid = IDFactory.newPeerGroupID(); PeerGroupConfigAdv pgca = (PeerGroupConfigAdv) AdvertisementFactory.newAdvertisement( PeerGroupConfigAdv.getAdvertisementType()); pgca.setPeerGroupID(pgid); for (PeerGroupConfigFlag flag : flags) { pgca.setFlag(flag); } PeerGroupAdvertisement pga = (PeerGroupAdvertisement) AdvertisementFactory.newAdvertisement( PeerGroupAdvertisement.getAdvertisementType()); pga.setName(name); pga.setModuleSpecID(msid); pga.setPeerGroupID(pgid); pga.putServiceParam(PeerGroup.peerGroupClassID, (Element) pgca.getDocument(MimeMediaType.XMLUTF8)); disco.publish(pga); LOG.finest(name + " PGA:\n" + pga); return pga; } /** * Asserts that the peer group provided is configured as expected with * respect to a specific flag's value. * * @param pg peer group to assert * @param flag flag to check for * @param enabled expected value */ private void assertFlagState( PeerGroup pg, PeerGroupConfigFlag flag, boolean enabled) { LOG.fine("Testing PeerGroup: " + pg.getClass() + " " + pg); PeerGroupAdvertisement pga = pg.getPeerGroupAdvertisement(); PeerGroupConfigAdv pgca = (PeerGroupConfigAdv) AdvertisementFactory.newAdvertisement((XMLElement) pga.getServiceParam(PeerGroup.peerGroupClassID)); if (enabled) { assertTrue(pgca.isFlagSet(flag)); } else { assertFalse(pgca.isFlagSet(flag)); } } }