// Path: here-oauth-client/src/main/java/com/here/account/http/HttpProvider.java
// public static interface HttpRequest {
//         
//     /**
//      * Add the Authorization header to this request, with the specified 
//      * <tt>value</tt>.
//      * See also 
//      * <a href="https://tools.ietf.org/html/rfc7235#section-4.2">RFC 7235</a>.
//      * 
//      * @param value the value to add in the Authorization header
//      */
//     void addAuthorizationHeader(String value);
// 
//     /**
//      * Adds the additional (name, value)-pair to be sent as HTTP Headers
//      * on the HTTP Request.
//      * See also
//      * <a href="https://tools.ietf.org/html/rfc7230#section-3.2">RFC 7230</a>.
//      *
//      * @param name the name of the HTTP Header to add
//      * @param value the value of the HTTP Header to add
//      */
//     default void addHeader(String name, String value) {
//         throw new UnsupportedOperationException("addHeader not supported");
//     }
// 
// }
// 
// Path: here-oauth-client/src/main/java/com/here/account/util/Clock.java
// public interface Clock {
//     
//     /**
//      * java.lang.System Clock (digital approximation of wall clock).
//      */
//     Clock SYSTEM = new Clock() {
//         
//         /**
//          * {@inheritDoc}
//          */
//         @Override
//         public long currentTimeMillis() {
//             return System.currentTimeMillis();
//         }
//         
//         /**
//          * {@inheritDoc}
//          */
//         @Override
//         public void schedule(ScheduledExecutorService scheduledExecutorService, 
//                 Runnable runnable,
//                 long millisecondsInTheFutureToSchedule
//                 ) {
//             scheduledExecutorService.schedule(
//                     runnable,
//                     millisecondsInTheFutureToSchedule,
//                     TimeUnit.MILLISECONDS
//                 );
// 
//         }
//     };
// 
//     /**
//      * Returns the milliseconds UTC since the epoch.
//      * 
//      * @return this clock's currentTimeMillis in UTC since the epoch.
//      */
//     long currentTimeMillis();
// 
//     /**
//      * Schedules <tt>runnable</tt> the specified <tt>millisecondsInTheFutureToSchedule</tt>
//      * using <tt>scheduledExecutorService</tt>.
//      * 
//      * @param scheduledExecutorService the ScheduledExecutorService to submit the runnable to
//      * @param runnable the runnable to execute on a schedule
//      * @param millisecondsInTheFutureToSchedule the schedule of milliseconds in the future, 
//      *      approximating when the runnable should run.
//      */
//     void schedule(ScheduledExecutorService scheduledExecutorService, 
//             Runnable runnable,
//             long millisecondsInTheFutureToSchedule
//             );
// }
// 
// Path: here-oauth-client/src/main/java/com/here/account/util/OAuthConstants.java
// public class OAuthConstants {
//     
//     /**
//      * We commonly use "UTF-8" charset, this String is its name.
//      */
//     public static final String UTF_8_STRING = "UTF-8";
//     
//     /**
//      * This is the constant for the "UTF-8" Charset already loaded.
//      */
//     public static final Charset UTF_8_CHARSET = Charset.forName(UTF_8_STRING);
// }


import org.junit.Before;
import org.junit.Test;
import com.here.account.http.HttpProvider.HttpRequest;
import com.here.account.util.Clock;
import com.here.account.util.OAuthConstants;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
        String shaVariant = "SHA256";//"SHA1";
        
        String requestParameters = "oauth_consumer_key="+accessKeyId+"&oauth_nonce="+nonce+"&oauth_signature_method=HMAC-"+shaVariant+"&oauth_timestamp="+oauth_timestamp+"&oauth_version=1.0";
        String signatureBaseString = "GET&"
                +urlEncode(url)+"&"
                + urlEncode(requestParameters); // no request parameters in this test case
        

        System.out.println("test       signatureBaseString "+signatureBaseString);
        
        String key = urlEncode(accessKeySecret) + "&"; // no token shared-secret
        
        String expectedSignature = HmacSHAN(key, "Hmac"+shaVariant, signatureBaseString);

        String expectedSignatureInAuthorizationHeader = urlEncode(expectedSignature);
        
        oauth1Signer.authorize(httpRequest, method, url, null);
        String actualHeader = httpRequest.getAuthorizationHeader();
        
        Pattern pattern = Pattern.compile("\\A.*oauth_signature=\\\"([^\\\"]+).*\\z");
        Matcher matcher = pattern.matcher(actualHeader);
        assertTrue("pattern wasn't matched: "+actualHeader, matcher.matches());
        String actualSignature = matcher.group(1);
        
        
        assertTrue("expected signature "+expectedSignatureInAuthorizationHeader+", actual signature "+actualSignature, 
                expectedSignatureInAuthorizationHeader.equals(actualSignature));
    }
    
    private String urlEncode(String s) throws UnsupportedEncodingException {
// Path: here-oauth-client/src/main/java/com/here/account/http/HttpProvider.java
// public static interface HttpRequest {
//         
//     /**
//      * Add the Authorization header to this request, with the specified 
//      * <tt>value</tt>.
//      * See also 
//      * <a href="https://tools.ietf.org/html/rfc7235#section-4.2">RFC 7235</a>.
//      * 
//      * @param value the value to add in the Authorization header
//      */
//     void addAuthorizationHeader(String value);
// 
//     /**
//      * Adds the additional (name, value)-pair to be sent as HTTP Headers
//      * on the HTTP Request.
//      * See also
//      * <a href="https://tools.ietf.org/html/rfc7230#section-3.2">RFC 7230</a>.
//      *
//      * @param name the name of the HTTP Header to add
//      * @param value the value of the HTTP Header to add
//      */
//     default void addHeader(String name, String value) {
//         throw new UnsupportedOperationException("addHeader not supported");
//     }
// 
// }
// 
// Path: here-oauth-client/src/main/java/com/here/account/util/Clock.java
// public interface Clock {
//     
//     /**
//      * java.lang.System Clock (digital approximation of wall clock).
//      */
//     Clock SYSTEM = new Clock() {
//         
//         /**
//          * {@inheritDoc}
//          */
//         @Override
//         public long currentTimeMillis() {
//             return System.currentTimeMillis();
//         }
//         
//         /**
//          * {@inheritDoc}
//          */
//         @Override
//         public void schedule(ScheduledExecutorService scheduledExecutorService, 
//                 Runnable runnable,
//                 long millisecondsInTheFutureToSchedule
//                 ) {
//             scheduledExecutorService.schedule(
//                     runnable,
//                     millisecondsInTheFutureToSchedule,
//                     TimeUnit.MILLISECONDS
//                 );
// 
//         }
//     };
// 
//     /**
//      * Returns the milliseconds UTC since the epoch.
//      * 
//      * @return this clock's currentTimeMillis in UTC since the epoch.
//      */
//     long currentTimeMillis();
// 
//     /**
//      * Schedules <tt>runnable</tt> the specified <tt>millisecondsInTheFutureToSchedule</tt>
//      * using <tt>scheduledExecutorService</tt>.
//      * 
//      * @param scheduledExecutorService the ScheduledExecutorService to submit the runnable to
//      * @param runnable the runnable to execute on a schedule
//      * @param millisecondsInTheFutureToSchedule the schedule of milliseconds in the future, 
//      *      approximating when the runnable should run.
//      */
//     void schedule(ScheduledExecutorService scheduledExecutorService, 
//             Runnable runnable,
//             long millisecondsInTheFutureToSchedule
//             );
// }
// 
// Path: here-oauth-client/src/main/java/com/here/account/util/OAuthConstants.java
// public class OAuthConstants {
//     
//     /**
//      * We commonly use "UTF-8" charset, this String is its name.
//      */
//     public static final String UTF_8_STRING = "UTF-8";
//     
//     /**
//      * This is the constant for the "UTF-8" Charset already loaded.
//      */
//     public static final Charset UTF_8_CHARSET = Charset.forName(UTF_8_STRING);
// }


// Path: here-oauth-client/src/test/java/com/here/account/auth/OAuth1SignerTest.java
import org.junit.Before;
import org.junit.Test;
import com.here.account.http.HttpProvider.HttpRequest;
import com.here.account.util.Clock;
import com.here.account.util.OAuthConstants;
import static org.junit.Assert.assertTrue;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

        String shaVariant = "SHA256";//"SHA1";
        
        String requestParameters = "oauth_consumer_key="+accessKeyId+"&oauth_nonce="+nonce+"&oauth_signature_method=HMAC-"+shaVariant+"&oauth_timestamp="+oauth_timestamp+"&oauth_version=1.0";
        String signatureBaseString = "GET&"
                +urlEncode(url)+"&"
                + urlEncode(requestParameters); // no request parameters in this test case
        

        System.out.println("test       signatureBaseString "+signatureBaseString);
        
        String key = urlEncode(accessKeySecret) + "&"; // no token shared-secret
        
        String expectedSignature = HmacSHAN(key, "Hmac"+shaVariant, signatureBaseString);

        String expectedSignatureInAuthorizationHeader = urlEncode(expectedSignature);
        
        oauth1Signer.authorize(httpRequest, method, url, null);
        String actualHeader = httpRequest.getAuthorizationHeader();
        
        Pattern pattern = Pattern.compile("\\A.*oauth_signature=\\\"([^\\\"]+).*\\z");
        Matcher matcher = pattern.matcher(actualHeader);
        assertTrue("pattern wasn't matched: "+actualHeader, matcher.matches());
        String actualSignature = matcher.group(1);
        
        
        assertTrue("expected signature "+expectedSignatureInAuthorizationHeader+", actual signature "+actualSignature, 
                expectedSignatureInAuthorizationHeader.equals(actualSignature));
    }
    
    private String urlEncode(String s) throws UnsupportedEncodingException {
        return URLEncoder.encode(s, OAuthConstants.UTF_8_STRING).replaceAll("\\+", "%20");