2020
2121package  com .arangodb .internal .net ;
2222
23+ import  java .util .ArrayList ;
2324import  java .util .Arrays ;
2425import  java .util .Collection ;
26+ import  java .util .Collections ;
2527import  java .util .List ;
28+ import  java .util .Map ;
2629
2730import  org .slf4j .Logger ;
2831import  org .slf4j .LoggerFactory ;
2932
33+ import  com .arangodb .ArangoDBException ;
34+ import  com .arangodb .internal .ArangoExecutor .ResponseDeserializer ;
35+ import  com .arangodb .internal .ArangoExecutorSync ;
36+ import  com .arangodb .internal .ArangoRequestParam ;
3037import  com .arangodb .internal .util .HostUtils ;
38+ import  com .arangodb .util .ArangoSerialization ;
39+ import  com .arangodb .velocypack .VPackSlice ;
40+ import  com .arangodb .velocypack .exception .VPackException ;
41+ import  com .arangodb .velocystream .Request ;
42+ import  com .arangodb .velocystream .RequestType ;
43+ import  com .arangodb .velocystream .Response ;
3144
3245/** 
3346 * @author Mark Vollmary 
3447 * 
3548 */ 
3649public  class  ExtendedHostResolver  implements  HostResolver  {
37- 
50+ 
3851private  static  final  Logger  LOGGER  = LoggerFactory .getLogger (ExtendedHostResolver .class );
3952
4053private  static  final  long  MAX_CACHE_TIME  = 60  * 60  * 1000 ;
41- 
42- private  EndpointResolver  resolver ;
54+ 
4355private  HostSet  hosts ;
44- 
56+ 
4557private  final  Integer  maxConnections ;
4658private  final  ConnectionFactory  connectionFactory ;
47- 
59+ 
4860private  long  lastUpdate ;
4961
62+ private  ArangoExecutorSync  executor ;
63+ private  ArangoSerialization  arangoSerialization ;
64+ 
5065public  ExtendedHostResolver (final  List <Host > hosts , final  Integer  maxConnections ,
5166final  ConnectionFactory  connectionFactory ) {
5267super ();
@@ -57,52 +72,93 @@ public ExtendedHostResolver(final List<Host> hosts, final Integer maxConnections
5772}
5873
5974@ Override 
60- public  void  init (final  EndpointResolver  resolver ) {
61- this .resolver  = resolver ;
75+ public  void  init (ArangoExecutorSync  executor , ArangoSerialization  arangoSerialization ) {
76+ this .executor  = executor ;
77+ this .arangoSerialization  = arangoSerialization ;
6278}
6379
6480@ Override 
6581
6682public  HostSet  resolve (final  boolean  initial , final  boolean  closeConnections ) {
67- 
83+ 
6884if  (!initial  && isExpired ()) {
69- 
85+ 
7086lastUpdate  = System .currentTimeMillis ();
71- 
72- final  Collection <String > endpoints  = resolver . resolve ( closeConnections );
87+ 
88+ final  Collection <String > endpoints  = resolveFromServer ( );
7389LOGGER .debug ("Resolve "  + endpoints .size () + " Endpoints" );
7490LOGGER .debug ("Endpoints "  + Arrays .deepToString (endpoints .toArray ()));
75- 
91+ 
7692if  (!endpoints .isEmpty ()) {
7793hosts .clear ();
7894}
79- 
95+ 
8096for  (final  String  endpoint  : endpoints ) {
8197LOGGER .debug ("Create HOST from "  + endpoint );
82- 
98+ 
8399if  (endpoint .matches (".*://.+:[0-9]+" )) {
84- 
100+ 
85101final  String [] s  = endpoint .replaceAll (".*://" , "" ).split (":" );
86102if  (s .length  == 2 ) {
87103final  HostDescription  description  = new  HostDescription (s [0 ], Integer .valueOf (s [1 ]));
88104hosts .addHost (HostUtils .createHost (description , maxConnections , connectionFactory ));
89105} else  if  (s .length  == 4 ) {
90-  // IPV6 Address - TODO: we need a proper function to resolve AND support IPV4 & IPV6 functions globally 
106+ // IPV6 Address - TODO: we need a proper function to resolve AND support IPV4 & IPV6 functions 
107+ // globally 
91108final  HostDescription  description  = new  HostDescription ("127.0.0.1" , Integer .valueOf (s [3 ]));
92109hosts .addHost (HostUtils .createHost (description , maxConnections , connectionFactory ));
93110} else  {
94111LOGGER .warn ("Skip Endpoint (Missing Port)"  + endpoint );
95112}
96- 
113+ 
97114} else  {
98115LOGGER .warn ("Skip Endpoint (Format)"  + endpoint );
99116}
100117}
101118}
102- 
119+ 
103120return  hosts ;
104121}
105122
123+ private  Collection <String > resolveFromServer () throws  ArangoDBException  {
124+ 
125+ Collection <String > response ;
126+ 
127+ try  {
128+ 
129+ response  = executor .execute (
130+ new  Request (ArangoRequestParam .SYSTEM , RequestType .GET , "/_api/cluster/endpoints" ),
131+ new  ResponseDeserializer <Collection <String >>() {
132+ @ Override 
133+ public  Collection <String > deserialize (final  Response  response ) throws  VPackException  {
134+ final  VPackSlice  field  = response .getBody ().get ("endpoints" );
135+ Collection <String > endpoints ;
136+ if  (field .isNone ()) {
137+ endpoints  = Collections .<String > emptyList ();
138+ } else  {
139+ final  Collection <Map <String , String >> tmp  = arangoSerialization .deserialize (field , Collection .class );
140+ endpoints  = new  ArrayList <String >();
141+ for  (final  Map <String , String > map  : tmp ) {
142+ for  (final  String  value  : map .values ()) {
143+ endpoints .add (value );
144+ }
145+ }
146+ }
147+ return  endpoints ;
148+ }
149+ }, null );
150+ } catch  (final  ArangoDBException  e ) {
151+ final  Integer  responseCode  = e .getResponseCode ();
152+ if  (responseCode  != null  && responseCode  == 403 ) {
153+ response  = Collections .<String > emptyList ();
154+ } else  {
155+ throw  e ;
156+ }
157+ }
158+ 
159+ return  response ;
160+ }
161+ 
106162private  boolean  isExpired () {
107163return  System .currentTimeMillis () > lastUpdate  + MAX_CACHE_TIME ;
108164}
0 commit comments