2424import java .util .ArrayList ;
2525import java .util .Collection ;
2626import java .util .Collections ;
27+ import java .util .EnumSet ;
2728import java .util .HashMap ;
2829import java .util .HashSet ;
2930import java .util .LinkedList ;
3233import java .util .Map .Entry ;
3334import java .util .Properties ;
3435import java .util .Set ;
36+ import java .util .concurrent .TimeUnit ;
3537
3638import javax .json .Json ;
3739import javax .json .JsonArray ;
38- import javax .json .JsonNumber ;
3940import javax .json .JsonObject ;
4041import javax .json .JsonObjectBuilder ;
4142import javax .json .JsonReader ;
@@ -469,8 +470,26 @@ Channel loadChannel(HFClient client, String channelName) throws NetworkConfigura
469470 throw new NetworkConfigurationException (format ("Channel %s is already configured in the client!" , channelName ));
470471 }
471472 channel = reconstructChannel (client , channelName , jsonChannel );
473+ } else {
474+
475+ final Set <String > channelNames = getChannelNames ();
476+ if (channelNames .isEmpty ()) {
477+ throw new NetworkConfigurationException ("Channel configuration has no channels defined." );
478+ }
479+ final StringBuilder sb = new StringBuilder (1000 );
480+
481+ channelNames .forEach (s -> {
482+ if (sb .length () != 0 ) {
483+ sb .append (", " );
484+ }
485+ sb .append (s );
486+ });
487+ throw new NetworkConfigurationException (format ("Channel %s not found in configuration file. Found channel names: %s " , channelName , sb .toString ()));
488+
472489 }
473490
491+ } else {
492+ throw new NetworkConfigurationException ("Channel configuration has no channels defined." );
474493 }
475494
476495 return channel ;
@@ -500,6 +519,9 @@ private void createAllOrderers() throws NetworkConfigurationException {
500519 }
501520
502521 Node orderer = createNode (ordererName , jsonOrderer , "url" );
522+ if (orderer == null ) {
523+ throw new NetworkConfigurationException (format ("Error loading config. Invalid orderer entry: %s" , ordererName ));
524+ }
503525 orderers .put (ordererName , orderer );
504526 }
505527 }
@@ -536,11 +558,16 @@ private void createAllPeers() throws NetworkConfigurationException {
536558 }
537559
538560 Node peer = createNode (peerName , jsonPeer , "url" );
561+ if (peer == null ) {
562+ throw new NetworkConfigurationException (format ("Error loading config. Invalid peer entry: %s" , peerName ));
563+ }
539564 peers .put (peerName , peer );
540565
541566 // Also create an event hub with the same name as the peer
542- Node eventHub = createNode (peerName , jsonPeer , "eventUrl" );
543- eventHubs .put (peerName , eventHub );
567+ Node eventHub = createNode (peerName , jsonPeer , "eventUrl" ); // may not be present
568+ if (null != eventHub ) {
569+ eventHubs .put (peerName , eventHub );
570+ }
544571 }
545572 }
546573
@@ -660,17 +687,17 @@ private Channel reconstructChannel(HFClient client, String channelName, JsonObje
660687 setPeerRole (channelName , peerOptions , jsonPeer , PeerRole .LEDGER_QUERY );
661688 setPeerRole (channelName , peerOptions , jsonPeer , PeerRole .EVENT_SOURCE );
662689
663- channel .addPeer (peer , peerOptions );
664-
665690 foundPeer = true ;
666691
667692 // Add the event hub associated with this peer
668693 EventHub eventHub = getEventHub (client , peerName );
669- if (eventHub == null ) {
670- // By rights this should never happen!
671- throw new NetworkConfigurationException (format ("Error constructing channel %s. EventHub for %s not defined in configuration" , channelName , peerName ));
694+ if (eventHub != null ) {
695+ channel .addEventHub (eventHub );
696+ if (peerOptions .peerRoles == null ) { // means no roles were found but there is an event hub so define all roles but eventing.
697+ peerOptions .setPeerRoles (EnumSet .of (PeerRole .ENDORSING_PEER , PeerRole .CHAINCODE_QUERY , PeerRole .LEDGER_QUERY ));
698+ }
672699 }
673- channel .addEventHub ( eventHub );
700+ channel .addPeer ( peer , peerOptions );
674701
675702 }
676703
@@ -714,33 +741,49 @@ private Orderer getOrderer(HFClient client, String ordererName) throws InvalidAr
714741 }
715742
716743 // Creates a new Node instance from a JSON object
717- private Node createNode (String nodeName , JsonObject jsonOrderer , String urlPropName ) throws NetworkConfigurationException {
744+ private Node createNode (String nodeName , JsonObject jsonNode , String urlPropName ) throws NetworkConfigurationException {
745+
746+ // jsonNode.
747+ // if (jsonNode.isNull(urlPropName)) {
748+ // return null;
749+ // }
718750
719- String url = jsonOrderer .getString (urlPropName );
751+ String url = jsonNode .getString (urlPropName , null );
752+ if (url == null ) {
753+ return null ;
754+ }
755+
756+ Properties props = extractProperties (jsonNode , "grpcOptions" );
757+
758+ if (null != props ) {
759+ String value = props .getProperty ("grpc.keepalive_time_ms" );
760+ if (null != value ) {
761+ props .remove ("grpc.keepalive_time_ms" );
762+ props .put ("grpc.NettyChannelBuilderOption.keepAliveTime" , new Object [] {new Long (value ), TimeUnit .MILLISECONDS });
763+ }
720764
721- Properties props = extractProperties (jsonOrderer , "grpcOptions" );
765+ value = props .getProperty ("grpc.keepalive_timeout_ms" );
766+ if (null != value ) {
767+ props .remove ("grpc.keepalive_timeout_ms" );
768+ props .put ("grpc.NettyChannelBuilderOption.keepAliveTimeout" , new Object [] {new Long (value ), TimeUnit .MILLISECONDS });
769+ }
770+ }
722771
723772 // Extract the pem details
724- getTLSCerts (nodeName , jsonOrderer , props );
773+ getTLSCerts (nodeName , jsonNode , props );
725774
726775 return new Node (nodeName , url , props );
727776 }
728777
729- private void getTLSCerts (String nodeName , JsonObject jsonOrderer , Properties props ) throws NetworkConfigurationException {
778+ private void getTLSCerts (String nodeName , JsonObject jsonOrderer , Properties props ) {
730779 JsonObject jsonTlsCaCerts = getJsonObject (jsonOrderer , "tlsCACerts" );
731780 if (jsonTlsCaCerts != null ) {
732781 String pemFilename = getJsonValueAsString (jsonTlsCaCerts .get ("path" ));
733782 String pemBytes = getJsonValueAsString (jsonTlsCaCerts .get ("pem" ));
734783
735- if (pemFilename != null && pemBytes != null ) {
736- throw new NetworkConfigurationException (format ("Endpoint %s should not specify both tlsCACerts path and pem" , nodeName ));
737- }
738-
739784 if (pemFilename != null ) {
740- // Determine full pathname and ensure the file exists
741- File pemFile = new File (pemFilename );
742- String fullPathname = pemFile .getAbsolutePath ();
743- props .put ("pemFile" , fullPathname );
785+ // let the sdk handle non existing errors could be they don't exist during parsing but are there later.
786+ props .put ("pemFile" , pemFilename );
744787 }
745788
746789 if (pemBytes != null ) {
@@ -795,9 +838,9 @@ private OrgInfo createOrg(String orgName, JsonObject jsonOrg, Map<String, JsonOb
795838 PrivateKey privateKey = null ;
796839
797840 try {
798- privateKey = getPrivateKeyFromString (adminPrivateKeyString );
841+ privateKey = getPrivateKeyFromString (adminPrivateKeyString );
799842 } catch (IOException ioe ) {
800- throw new NetworkConfigurationException (format ("%s: Invalid private key" , msgPrefix ), ioe );
843+ throw new NetworkConfigurationException (format ("%s: Invalid private key" , msgPrefix ), ioe );
801844 }
802845
803846 final PrivateKey privateKeyFinal = privateKey ;
@@ -815,7 +858,6 @@ public String getCert() {
815858 }
816859 });
817860
818-
819861 }
820862
821863 return org ;
@@ -997,7 +1039,7 @@ private static String getJsonValueAsString(JsonValue value) {
9971039
9981040 // Returns the specified JsonValue as a String, or null if it's not a string
9991041 private static String getJsonValueAsNumberString (JsonValue value ) {
1000- return (value != null && value .getValueType () == ValueType .NUMBER ) ? (( JsonNumber ) value ) .toString () : null ;
1042+ return (value != null && value .getValueType () == ValueType .NUMBER ) ? value .toString () : null ;
10011043 }
10021044
10031045 // Returns the specified JsonValue as a Boolean, or null if it's not a boolean
@@ -1022,6 +1064,25 @@ private static JsonObject getJsonObject(JsonObject object, String propName) {
10221064 return obj ;
10231065 }
10241066
1067+ /**
1068+ * Get the channel names found.
1069+ *
1070+ * @return A set of the channel names found in the configuration file or empty set if none found.
1071+ */
1072+
1073+ public Set <String > getChannelNames () {
1074+ Set <String > ret = Collections .EMPTY_SET ;
1075+
1076+ JsonObject channels = getJsonObject (jsonConfig , "channels" );
1077+ if (channels != null ) {
1078+ final Set <String > channelNames = channels .keySet ();
1079+ if (channelNames != null && !channelNames .isEmpty ()) {
1080+ ret = new HashSet <>(channelNames );
1081+ }
1082+ }
1083+ return ret ;
1084+ }
1085+
10251086 // Holds a network "node" (eg. Peer, Orderer, EventHub)
10261087 private class Node {
10271088
@@ -1167,7 +1228,6 @@ public String getMspId() {
11671228 return mspId ;
11681229 }
11691230
1170-
11711231 public List <String > getPeerNames () {
11721232 return peerNames ;
11731233 }
@@ -1186,7 +1246,6 @@ public UserInfo getPeerAdmin() {
11861246 return peerAdmin ;
11871247 }
11881248
1189-
11901249 }
11911250
11921251 /**
0 commit comments