VolD 0.1

RESTClient.java

Go to the documentation of this file.
00001 package de.zib.vold.client;
00002 
00003 import de.zib.vold.common.VoldInterface;
00004 import de.zib.vold.common.Key;
00005 import de.zib.vold.common.URIKey;
00006 
00007 import java.util.Collection;
00008 import java.util.List;
00009 import java.util.ArrayList;
00010 import java.util.Set;
00011 import java.util.HashSet;
00012 import java.util.Map;
00013 import java.util.HashMap;
00014 
00015 import org.springframework.util.MultiValueMap;
00016 import org.springframework.util.LinkedMultiValueMap;
00017 
00018 import org.slf4j.Logger;
00019 import org.slf4j.LoggerFactory;
00020 
00021 import org.springframework.context.ApplicationContext;
00022 import org.springframework.context.support.ClassPathXmlApplicationContext;
00023 
00024 import org.springframework.web.client.RestTemplate;
00025 import org.springframework.http.ResponseEntity;
00026 import org.springframework.http.HttpStatus;
00027 
00033 public class RESTClient implements VoldInterface
00034 {
00035         protected final Logger log = LoggerFactory.getLogger( this.getClass() );
00036 
00037         private String baseURL;
00038 
00039         private ApplicationContext context;
00040         private RestTemplate rest;
00041 
00042         private String enc = "utf-8";
00043 
00047         public RESTClient( )
00048         {
00049                 baseURL = null;
00050 
00051                 context = new ClassPathXmlApplicationContext( "classpath:META-INF/client-context.xml" );
00052                 rest = ( RestTemplate )context.getBean( "restTemplate", RestTemplate.class );
00053 
00054                 if( null == rest )
00055                 {
00056                         throw new IllegalStateException( "Could not get bean rest out of client-context.xml!" );
00057                 }
00058         }
00059 
00065         public RESTClient( String baseURL )
00066         {
00067                 context = new ClassPathXmlApplicationContext( "classpath:META-INF/client-context.xml" );
00068                 rest = ( RestTemplate )context.getBean( "restTemplate", RestTemplate.class );
00069 
00070                 if( null == rest )
00071                 {
00072                         throw new IllegalStateException( "Could not get bean rest out of client-context.xml!" );
00073                 }
00074 
00075                 this.baseURL = baseURL;
00076         }
00077 
00083         public void setBaseURL( String baseURL )
00084         {
00085                 this.baseURL = baseURL;
00086         }
00087 
00091         public void setEnc( String enc )
00092         {
00093                 this.enc = enc;
00094         }
00095 
00099         public void checkState( )
00100         {
00101                 if( null == this.baseURL )
00102                 {
00103                         throw new IllegalStateException( "Tried to operate on VoldClient while it had not been initialized yet. Set the baseURL before!" );
00104                 }
00105         }
00106 
00110         @Override
00111         public Map< String, String > insert( String source, Map< Key, Set< String > > map )
00112         {
00113                 // guard
00114                 {
00115                         log.trace( "Insert: " + map.toString() );
00116 
00117                         checkState();
00118 
00119                         if( null == map )
00120                         {
00121                                 throw new IllegalArgumentException( "null is no valid argument!" );
00122                         }
00123                 }
00124 
00125                 // build greatest common scope
00126                 String commonscope;
00127                 {
00128                         List< String > scopes = new ArrayList< String >( map.size() );
00129 
00130                         for( Key k: map.keySet() )
00131                         {
00132                                 scopes.add( k.get_scope() );
00133                         }
00134 
00135                         commonscope = getGreatestCommonPrefix( scopes );
00136                 }
00137 
00138                 // build variable map
00139                 String uri;
00140                 {
00141                         uri = buildURI( null );
00142                         log.debug( "URI: " + uri );
00143                 }
00144 
00145                 // build request body
00146                 MultiValueMap< String, String > request = new LinkedMultiValueMap< String, String >();
00147                 {
00148                         for( Map.Entry< Key, Set< String > > entry: map.entrySet() )
00149                         {
00150                                 // remove common prefix from scope
00151                                 String scope = entry.getKey().get_scope().substring( commonscope.length() );
00152                                 String type = entry.getKey().get_type();
00153                                 String keyname = entry.getKey().get_keyname();
00154 
00155                                 URIKey key = new URIKey( source, scope, type, keyname, false, false, enc );
00156                                 String urikey = key.toURIString();
00157 
00158                                 for( String value: entry.getValue() )
00159                                 {
00160                                         request.add( urikey, value );
00161                                 }
00162                         }
00163                 }
00164 
00165                 // get response from Server
00166                 ResponseEntity< Map< String, String > > response;
00167                 {
00168                         Object obj = rest.postForEntity( baseURL + commonscope, request, HashMap.class );
00169 
00170                         if( obj instanceof ResponseEntity< ? > )
00171                         {
00172                                 response = ( ResponseEntity< Map< String, String > > )obj;
00173                         }
00174                         else
00175                         {
00176                                 throw new RuntimeException( "THIS SHOULD NEVER HAPPEN!" );
00177                         }
00178                 }
00179 
00180                 return response.getBody();
00181         }
00182 
00189         @Override
00190         public Map< String, String > refresh( String source, Set< Key > set )
00191         {
00192                 // guard
00193                 {
00194                         log.trace( "Refresh: " + set.toString() );
00195 
00196                         checkState();
00197 
00198                         if( null == set )
00199                         {
00200                                 throw new IllegalArgumentException( "null is no valid argument!" );
00201                         }
00202                 }
00203 
00204                 // build greatest common scope
00205                 String commonscope;
00206                 {
00207                         List< String > scopes = new ArrayList< String >( set.size() );
00208 
00209                         for( Key k: set )
00210                         {
00211                                 scopes.add( k.get_scope() );
00212                         }
00213 
00214                         commonscope = getGreatestCommonPrefix( scopes );
00215                 }
00216 
00217                 // build variable map
00218                 String uri;
00219                 {
00220                         uri = buildURI( null );
00221                         log.debug( "URI: " + uri );
00222                 }
00223 
00224                 // build request body
00225                 MultiValueMap< String, String > request = new LinkedMultiValueMap< String, String >();
00226                 {
00227                         for( Key entry: set )
00228                         {
00229                                 // remove common prefix from scope
00230                                 String scope = entry.get_scope().substring( commonscope.length() );
00231                                 String type = entry.get_type();
00232                                 String keyname = entry.get_keyname();
00233 
00234                                 URIKey key = new URIKey( source, scope, type, keyname, true, false, enc );
00235                                 String urikey = key.toURIString();
00236 
00237                                 request.add( urikey, "" );
00238                         }
00239                 }
00240 
00241                 // get response from Server
00242                 ResponseEntity< Map< String, String > > response;
00243                 {
00244                         Object obj = rest.postForEntity( baseURL + commonscope, request, HashMap.class );
00245 
00246                         if( obj instanceof ResponseEntity< ? > )
00247                         {
00248                                 response = ( ResponseEntity< Map< String, String > > )obj;
00249                         }
00250                         else
00251                         {
00252                                 throw new RuntimeException( "THIS SHOULD NEVER HAPPEN!" );
00253                         }
00254                 }
00255 
00256                 return response.getBody();
00257         }
00258 
00265         @Override
00266         public Map< String, String > delete( String source, Set< Key > set )
00267         {
00268                 // guard
00269                 {
00270                         log.trace( "Delete: " + set.toString() );
00271 
00272                         checkState();
00273 
00274                         if( null == set )
00275                         {
00276                                 throw new IllegalArgumentException( "null is no valid argument!" );
00277                         }
00278                 }
00279 
00280                 // build greatest common scope
00281                 String commonscope;
00282                 {
00283                         List< String > scopes = new ArrayList< String >( set.size() );
00284 
00285                         for( Key k: set )
00286                         {
00287                                 scopes.add( k.get_scope() );
00288                         }
00289 
00290                         commonscope = getGreatestCommonPrefix( scopes );
00291                 }
00292 
00293                 // build variable map
00294                 String uri;
00295                 {
00296                         uri = buildURI( null );
00297                         log.debug( "URI: " + uri );
00298                 }
00299 
00300                 // build request body
00301                 MultiValueMap< String, String > request = new LinkedMultiValueMap< String, String >();
00302                 {
00303                         for( Key entry: set )
00304                         {
00305                                 // remove common prefix from scope
00306                                 String scope = entry.get_scope().substring( commonscope.length() );
00307                                 String type = entry.get_type();
00308                                 String keyname = entry.get_keyname();
00309 
00310                                 URIKey key = new URIKey( source, scope, type, keyname, false, true, enc );
00311                                 String urikey = key.toURIString();
00312 
00313                                 request.add( urikey, "" );
00314                         }
00315                 }
00316 
00317                 // get response from Server
00318                 ResponseEntity< Map< String, String > > response;
00319                 {
00320                         Object obj = rest.postForEntity( baseURL + commonscope, request, HashMap.class );
00321 
00322                         if( obj instanceof ResponseEntity< ? > )
00323                         {
00324                                 response = ( ResponseEntity< Map< String, String > > )obj;
00325                         }
00326                         else
00327                         {
00328                                 throw new RuntimeException( "THIS SHOULD NEVER HAPPEN!" );
00329                         }
00330                 }
00331 
00332                 return response.getBody();
00333         }
00334 
00341         @Override
00342         public Map< Key, Set< String > > lookup( Set< Key > keys )
00343         {
00344                 // TODO: lookup has to adjust scope appropriate and eventually merge different requests
00345 
00346                 // guard
00347                 {
00348                         log.trace( "Lookup: " + keys.toString() );
00349 
00350                         checkState();
00351 
00352                         if( null == keys )
00353                         {
00354                                 throw new IllegalArgumentException( "null is no valid argument!" );
00355                         }
00356                 }
00357 
00358                 // build variable map
00359                 String uri;
00360                 {
00361                         uri = buildURI( keys );
00362                         log.debug( "URI: " + uri );
00363                 }
00364 
00365                 // get responseEntity from Server
00366                 ResponseEntity< Map< Key, Set< String > > > response;
00367                 {
00368                         Object obj = rest.getForEntity( uri, Map.class, new HashMap< String, String >() );
00369 
00370                         if( obj instanceof ResponseEntity< ? > )
00371                         {
00372                                 response = ( ResponseEntity< Map< Key, Set< String > > > )obj;
00373                         }
00374                         else
00375                         {
00376                                 throw new RuntimeException( "THIS SHOULD NEVER HAPPEN!" );
00377                         }
00378 
00379                         if( response.getStatusCode() != HttpStatus.OK )
00380                         {
00381                                 if( response.hasBody() )
00382                                 {
00383                                         throw new RuntimeException( "Something went wrong on server (" + baseURL + ")... Got body: " + response.getBody() );
00384                                 }
00385                                 else
00386                                 {
00387                                         throw new RuntimeException( "Something went wrong on remote server (" + baseURL + ")..." );
00388                                 }
00389                         }
00390                 }
00391 
00392                 // process and return results
00393                 {
00394                         if( response.hasBody() )
00395                         {
00396                                 return response.getBody();
00397                         }
00398                         else
00399                         {
00400                                 return null;
00401                         }
00402                 }
00403         }
00404 
00412         public Map< String, String > insert( String source, Key key, Set< String > values )
00413         {
00414                 Map< Key, Set< String > > map = new HashMap< Key, Set< String > >();
00415                 map.put( key, values );
00416                 return insert( source, map );
00417         }
00418 
00425         public Map< Key, Set< String > > lookup( Key key )
00426         {
00427                 Set< Key > keys = new HashSet< Key >();
00428                 keys.add( key );
00429                 return lookup( keys );
00430         }
00431 
00438         private String getGreatestCommonPrefix( Collection< String > words )
00439         {
00440                 if( null == words )
00441                 {
00442                         throw new IllegalArgumentException( "Cannot build the greatest common prefix out of an empty set of words!" );
00443                 }
00444 
00445                 String commonprefix = words.iterator().next();
00446 
00447                 for( String w: words )
00448                 {
00449                         commonprefix = getCommonPrefix( commonprefix, w );
00450                 }
00451 
00452                 return commonprefix;
00453         }
00454 
00462         private String getCommonPrefix( String a, String b )
00463         {
00464                 for( int i = 1; i < b.length(); ++i )
00465                 {
00466                         if( a.length() < i )
00467                         {
00468                                 return a;
00469                         }
00470 
00471                         if( ! a.substring( i-1, i ).equals( b.substring( i-1, i ) ) )
00472                         {
00473                                 return a.substring( 0, i-1 );
00474                         }
00475                 }
00476 
00477                 return b;
00478         }
00479 
00486         private String buildURI( Collection< Key > keys )
00487         {
00488                 if( null == keys )
00489                 {
00490                         return baseURL;
00491                 }
00492 
00493                 StringBuilder sb = new StringBuilder( baseURL + "?" );
00494 
00495                 for( Key k: keys )
00496                 {
00497 
00498                         // TODO: urlencode keyname and type...
00499                         sb.append( k.get_keyname() );
00500                         sb.append( ":" );
00501                         sb.append( k.get_type() );
00502                         sb.append( "&" );
00503                 }
00504 
00505                 return sb.toString();
00506         }
00507 }