/* @Copyright (c) 2002-2009 The Regents of the University of California. All rights reserved. Permission is hereby granted, without written agreement and without license or royalty fees, to use, copy, modify, and distribute this software and its documentation for any purpose, provided that the above copyright notice and the following two paragraphs appear in all copies of this software. IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. PT_COPYRIGHT_VERSION_2 COPYRIGHTENDKEY */ package ptolemy.actor.lib.jxta; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Properties; import net.jxta.credential.AuthenticationCredential; import net.jxta.credential.Credential; import net.jxta.discovery.DiscoveryEvent; import net.jxta.discovery.DiscoveryListener; import net.jxta.discovery.DiscoveryService; import net.jxta.document.AdvertisementFactory; import net.jxta.document.MimeMediaType; import net.jxta.document.StructuredDocument; import net.jxta.exception.DiscardQueryException; import net.jxta.exception.NoResponseException; import net.jxta.exception.PeerGroupException; import net.jxta.exception.ResendQueryException; import net.jxta.impl.protocol.ResolverQuery; import net.jxta.impl.protocol.ResolverResponse; import net.jxta.membership.Authenticator; import net.jxta.membership.MembershipService; import net.jxta.peergroup.PeerGroup; import net.jxta.peergroup.PeerGroupFactory; import net.jxta.protocol.DiscoveryResponseMsg; import net.jxta.protocol.PeerAdvertisement; import net.jxta.protocol.PeerGroupAdvertisement; import net.jxta.protocol.ResolverQueryMsg; import net.jxta.protocol.ResolverResponseMsg; import net.jxta.resolver.QueryHandler; import net.jxta.resolver.ResolverService; import org.apache.log4j.PropertyConfigurator; import ptolemy.actor.TypedAtomicActor; import ptolemy.actor.TypedIOPort; import ptolemy.data.StringToken; import ptolemy.data.expr.Parameter; import ptolemy.data.type.BaseType; import ptolemy.kernel.CompositeEntity; import ptolemy.kernel.util.IllegalActionException; import ptolemy.kernel.util.NameDuplicationException; /** * @author liuxj, Yang @version $Id$ @since Ptolemy II 7.1 * * To change this generated comment edit the template variable "typecomment": * Window>Preferences>Java>Templates. * To enable and disable the creation of type comments go to * Window>Preferences>Java>Code Generation. * * Use a timer task for peer discovery, and actor query. */ public class Peer extends TypedAtomicActor implements QueryHandler, DiscoveryListener { public Peer(CompositeEntity container, String name) throws NameDuplicationException, IllegalActionException { super(container, name); trigQuery = new TypedIOPort(this, "trigQuery", true, false); trigQuery.setTypeEquals(BaseType.GENERAL); queryResult = new TypedIOPort(this, "queryResult", false, true); queryResult.setTypeEquals(BaseType.STRING); //trigResult = new TypedIOPort(this, "trigResult", true, false); //trigResult.setTypeEquals(BaseType.GENERAL); /*configDir = new Parameter(this, "configDir", new StringToken("")); configDir.setTypeEquals(BaseType.STRING); actorList = new Parameter(this, "actorList", new StringToken("")); actorList.setTypeEquals(BaseType.STRING); */ } /////////////////////////////////////////////////////////////////// //// ports and parameters //// /** */ public TypedIOPort trigQuery; //public TypedIOPort trigResult; /** The output port with. */ public TypedIOPort queryResult; public Parameter configDir; public Parameter actorList; /////////////////////////////////////////////////////////////////// //// public methods //// public void preinitialize() throws IllegalActionException { super.preinitialize(); PropertyConfigurator.configure(System.getProperties()); //if (configDir.hasToken()) { //String Dir = ((StringToken)configDir.getToken()).stringValue(); //} else { String Dir = "c:/Cygwin/home/ellen_zh/ptII/ptolemy/actor/lib/jxta"; //} //if (actorList.hasToken()) { //String _actorListFileName = ((StringToken)actorList.getToken()).stringValue(); //} else { String _actorListFileName = "c:/Cygwin/home/ellen_zh/ptII/ptolemy/actor/lib/jxta/actors.xml"; //} _properties = new Properties(System.getProperties()); InputStream configProperties = null; try { configProperties = new FileInputStream(_CONFIG_FILE); _properties.load(configProperties); } catch (IOException e) { System.out .println("Warning: Can't find configuration propertiees file. ' " + e.getMessage() + "'"); } finally { if (configProperties != null) { try { configProperties.close(); } catch (Throwable throwable) { System.out.println("Ignoring failure to close stream " + "on '" + _CONFIG_FILE + "'"); throwable.printStackTrace(); } } } PeerGroup netPeerGroup = null; try { netPeerGroup = PeerGroupFactory.newNetPeerGroup(); } catch (PeerGroupException ex) { System.out.println("Error: cannot locate net peer group.\n" + ex.getMessage()); } // load the peer group adv for actor exchange String groupAdvFileName = _properties.getProperty("GroupAdvFileName"); if (groupAdvFileName == null) { System.out .println("Error: property undefined - GroupAdvFileName.\n"); } PeerGroupAdvertisement groupAdv = null; try { groupAdv = (PeerGroupAdvertisement) AdvertisementFactory .newAdvertisement(XML_MIME_TYPE, new FileInputStream(Dir + "/" + groupAdvFileName)); } catch (FileNotFoundException ex) { System.out.println("Error: cannot find group adv file.\n" + ex.getMessage()); } catch (IOException ex) { System.out.println("Error: reading group adv file.\n" + ex.getMessage()); } System.out.println("peer groupAdv: " + groupAdvFileName); System.out.println("success before instantiate peer group"); // instantiate the peer group for actor exchange try { _group = netPeerGroup.newGroup(groupAdv); } catch (PeerGroupException ex) { System.out.println("Error: cannot instantiate peer group.\n" + ex.getMessage()); } // join the peer group for actor exchange // no authentication is done here // modeled after JoinDemo from JXTA Examples StructuredDocument identityInfo = null; try { AuthenticationCredential authCred = new AuthenticationCredential( _group, null, identityInfo); MembershipService membershipService = _group.getMembershipService(); _authenticator = membershipService.apply(authCred); if (_authenticator.isReadyForJoin()) { _credential = membershipService.join(_authenticator); System.out.println("Info: join group successful."); _credential.getDocument(XML_MIME_TYPE).sendToStream(System.out); } else { System.out.println("Error: unable to join group."); } } catch (Exception ex) { System.out.println("Error: failure in authentication.\n" + ex.getMessage()); } _discoveryService = _group.getDiscoveryService(); _discoveryService.addDiscoveryListener(this); _resolverService = _group.getResolverService(); // register this as a query handler _resolverService.registerHandler(_ACTOR_QUERY_HANDLER_NAME, this); // construct the actor query message StringBuffer queryTextBuffer = new StringBuffer( "<?xml version=\"1.0\"?>\n\n"); queryTextBuffer = queryTextBuffer.append("<ActorQuery>\n"); queryTextBuffer = queryTextBuffer.append("What actors do you have?"); queryTextBuffer = queryTextBuffer.append("\n</ActorQuery>\n"); _actorQueryMessage = new ResolverQuery(_ACTOR_QUERY_HANDLER_NAME, null, null, queryTextBuffer.toString(), 0); _actorQueryMessage.setSrc(_group.getPeerID().toString()); // construct the actor query response message if (_actorListFileName != null) { StringBuffer actorListText = new StringBuffer(); BufferedReader fileReader = null; try { fileReader = new BufferedReader(new FileReader( _actorListFileName)); String newline = System.getProperty("line.separator"); while (true) { String line = fileReader.readLine(); if (line == null) { break; } actorListText = actorListText.append(line); actorListText = actorListText.append(newline); } _actorQueryResponse = new ResolverResponse( _ACTOR_QUERY_HANDLER_NAME, null, 0, actorListText .toString()); } catch (IOException ex) { System.out.println("Warning: error reading actor list file.\n" + ex.getMessage()); } finally { if (fileReader != null) { try { fileReader.close(); } catch (Exception ex) { System.out.println("Failed to close: " + ex.getMessage()); } } } } } public void fire() throws IllegalActionException { super.fire(); try { if (trigQuery.hasToken(0)) { trigQuery.get(0); System.out.println("Send peer discovery message..."); // send a query message that is // - propagated within the group // - for peer discovery // - no attribute/value matching // - each response contains at most 5 peers _discoveryService.getRemoteAdvertisements(null, DiscoveryService.PEER, null, null, 5); System.out.println("Send actor query message..."); _actorQueryMessage .setQueryId(_actorQueryMessage.getQueryId() + 1); _resolverService.sendQuery(null, _actorQueryMessage); } if (_inToken != null) { queryResult.send(0, _inToken); _inToken = null; System.out.println("send data "); } } catch (Exception e) { System.out.println("Error : " + e); } } /** Record the most recent output count as the actual count. * @exception IllegalActionException If the base class throws it. */ public boolean postfire() throws IllegalActionException { //_discoveryService.removeDiscoveryListener(this) ; //_resolverService.unregisterHandler(_ACTOR_QUERY_HANDLER_NAME); return super.postfire(); } /** * @see net.jxta.resolver.QueryHandler#processQuery(ResolverQueryMsg) */ public ResolverResponseMsg processQuery(ResolverQueryMsg query) throws NoResponseException, ResendQueryException, DiscardQueryException, IOException { System.out.println("Got query from " + query.getSrc() + " " + query.getQueryId()); System.out.println("Query is:\n" + query.getQuery()); if (_actorQueryResponse == null) { throw new DiscardQueryException(); } System.out.println("Send query response..."); _actorQueryResponse.setQueryId(query.getQueryId()); return _actorQueryResponse; } /** * @see net.jxta.resolver.QueryHandler#processResponse(ResolverResponseMsg) */ public void processResponse(ResolverResponseMsg response) { String responseString = response.getResponse(); _inToken = new StringToken(responseString); System.out.println("Got response:\n" + response.getResponse()); } /** * @see net.jxta.discovery.DiscoveryListener#discoveryEvent(DiscoveryEvent) */ public void discoveryEvent(DiscoveryEvent event) { // copied from JXTA Examples - PeerDiscovery System.out.println("Process discovery event..."); DiscoveryResponseMsg response = event.getResponse(); // Get the responding peer's advertisement as a string String responderAdvString = response.getPeerAdv(); InputStream is = null; try { // create a peer advertisement is = new ByteArrayInputStream(responderAdvString.getBytes()); PeerAdvertisement responderAdv = (PeerAdvertisement) AdvertisementFactory .newAdvertisement(XML_MIME_TYPE, is); System.out.println(" [ Got a Discovery Response [" + response.getResponseCount() + " elements] from peer: " + responderAdv.getName() + " ]"); } catch (java.io.IOException e) { // bogus peer, skip this message alltogether. System.out .println("Warning: cannot parse remote peer's advertisement.\n" + e.getMessage()); return; } finally { if (is != null) { try { is.close(); } catch (Throwable throwable) { System.out.println("Ignoring failure to close stream " + "on remote peer's advertisement"); throwable.printStackTrace(); } } } // now print out each discovered peer PeerAdvertisement newAdv = null; Enumeration responses = response.getResponses(); while (responses.hasMoreElements()) { try { String responseString = (String) responses.nextElement(); // create an advertisement object from each element newAdv = (PeerAdvertisement) AdvertisementFactory .newAdvertisement(XML_MIME_TYPE, new ByteArrayInputStream(responseString .getBytes())); System.out.println(" Peer name = " + newAdv.getName()); } catch (java.io.IOException e) { // got a bad response. continue to the next response System.out.println("Warning: cannot parse response element.\n" + e.getMessage()); continue; } } // end while } /////////////////////////////////////////////////////////////////// //// private members //// private Properties _properties; private PeerGroup _group; private DiscoveryService _discoveryService; private ResolverService _resolverService; private Authenticator _authenticator; private Credential _credential; private ResolverQueryMsg _actorQueryMessage; private ResolverResponseMsg _actorQueryResponse; private String _CONFIG_FILE = "c:/Cygwin/home/ellen_zh/ptII/ptolemy/actor/lib/jxta/Peer.properties"; private String _ACTOR_QUERY_HANDLER_NAME = "ActorQueryHandler"; private MimeMediaType XML_MIME_TYPE = new MimeMediaType("text/xml"); private ptolemy.data.Token _inToken = null; }