/*
 * Copyright 2012 Research Studios Austria Forschungsges.m.b.H. Licensed under
 * the Apache License, Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the License
 * at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable
 * law or agreed to in writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package won.protocol.rest;

import org.apache.http.ssl.TrustStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import won.cryptography.keymanagement.KeyPairAliasDerivationStrategy;
import won.cryptography.service.CryptographyUtils;
import won.cryptography.service.TrustStoreService;
import won.cryptography.service.keystore.KeyStoreService;
import won.cryptography.ssl.PredefinedAliasPrivateKeyStrategy;

import javax.annotation.PostConstruct;
import java.lang.invoke.MethodHandles;
import java.net.URI;

/**
 * User: ypanchenko Date: 07.10.15
 */
public class LinkedDataRestClientHttps extends LinkedDataRestClient {
    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
    private HttpMessageConverter datasetConverter;
    String acceptHeaderValue = null;
    private Integer readTimeout;
    private Integer connectionTimeout;
    private KeyStoreService keyStoreService;
    private TrustStoreService trustStoreService;
    private TrustStrategy trustStrategy;
    private KeyPairAliasDerivationStrategy keyPairAliasDerivationStrategy;

    public LinkedDataRestClientHttps(KeyStoreService keyStoreService, TrustStoreService trustStoreService,
                    TrustStrategy trustStrategy, KeyPairAliasDerivationStrategy keyPairAliasDerivationStrategy) {
        this.readTimeout = 5000;
        this.connectionTimeout = 5000; // DEF. TIMEOUT IS 5 sec
        this.keyStoreService = keyStoreService;
        this.trustStoreService = trustStoreService;
        this.trustStrategy = trustStrategy;
        this.keyPairAliasDerivationStrategy = keyPairAliasDerivationStrategy;
    }

    @PostConstruct
    public void initialize() {
        datasetConverter = new RdfDatasetConverter();
        // HttpHeaders headers = new HttpHeaders();
        this.acceptHeaderValue = MediaType.toString(datasetConverter.getSupportedMediaTypes());
    }

    private RestTemplate createRestTemplateForReadingLinkedData(String webID) {
        RestTemplate template;
        try {
            template = CryptographyUtils.createSslRestTemplate(this.keyStoreService.getUnderlyingKeyStore(),
                            this.keyStoreService.getPassword(),
                            new PredefinedAliasPrivateKeyStrategy(
                                            keyPairAliasDerivationStrategy.getAliasForAtomUri(webID)),
                            this.trustStoreService.getUnderlyingKeyStore(), this.trustStrategy, readTimeout,
                            connectionTimeout, true);
        } catch (Exception e) {
            throw new RuntimeException("Failed to create rest template for webID '" + webID + "'", e);
        }
        // we add our DatasetConverter before any other converter because the jackson
        // converter feels responsible for "application/*+json" (which matches
        // "application/ld+json") and is confident it can produce a jena Dataset - but
        // then of course fails to instantiate one. By putting our converter first, we
        // can be sure it is used when a jena Dataset is requested.
        template.getMessageConverters().add(0, datasetConverter);
        return template;
    }

    @Override
    public DatasetResponseWithStatusCodeAndHeaders readResourceDataWithHeaders(final URI resourceURI) {
        return readResourceDataWithHeaders(resourceURI, (URI) null);
    }

    @Override
    public DatasetResponseWithStatusCodeAndHeaders readResourceDataWithHeaders(URI resourceURI,
                    final URI requesterWebID) {
        HttpMessageConverter datasetConverter = new RdfDatasetConverter();
        RestTemplate restTemplate;
        try {
            restTemplate = getRestTemplateForReadingLinkedData(
                            requesterWebID == null ? null : requesterWebID.toString());
        } catch (Exception e) {
            logger.error("Failed to create ssl tofu rest template", e);
            throw new RuntimeException(e);
        }
        restTemplate.getMessageConverters().add(datasetConverter);
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add(HttpHeaders.ACCEPT, this.acceptHeaderValue);
        return super.readResourceData(resourceURI, restTemplate, requestHeaders);
    }

    @Override
    public DatasetResponseWithStatusCodeAndHeaders readResourceDataWithHeaders(final URI resourceURI,
                    final URI requesterWebID, final HttpHeaders requestHeaders) {
        requestHeaders.add(HttpHeaders.ACCEPT, this.acceptHeaderValue);
        return super.readResourceData(resourceURI,
                        getRestTemplateForReadingLinkedData(requesterWebID == null ? null : requesterWebID.toString()),
                        requestHeaders);
    }

    private RestTemplate getRestTemplateForReadingLinkedData(String webID) {
        return createRestTemplateForReadingLinkedData(webID);
    }

    @Override
    public DatasetResponseWithStatusCodeAndHeaders readResourceDataWithHeaders(final URI resourceURI,
                    HttpHeaders requestHeaders) {
        return readResourceDataWithHeaders(resourceURI, null, requestHeaders);
    }

    public void setReadTimeout(final Integer readTimeout) {
        this.readTimeout = readTimeout;
    }

    public void setConnectionTimeout(final Integer connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }
}

@@ -631,16 +631,117 @@
 .rest;%0A%0A
+import java.lang.invoke.MethodHandles;%0Aimport java.net.URI;%0A%0Aimport javax.annotation.PostConstruct;%0A%0A
 import o
@@ -770,24 +770,24 @@
 stStrategy;%0A
-
 import org.s
@@ -1035,16 +1035,17 @@
 mplate;%0A
+%0A
 import w
@@ -1258,32 +1258,32 @@
 eyStoreService;%0A
+
 import won.crypt
@@ -1334,108 +1334,8 @@
 y;%0A%0A
-import javax.annotation.PostConstruct;%0Aimport java.lang.invoke.MethodHandles;%0Aimport java.net.URI;%0A%0A
 /**%0A
@@ -2841,32 +2841,202 @@
 ;%0A        try %7B%0A
+            if (logger.isDebugEnabled()) %7B%0A                logger.debug(%22creating rest template for webID %7B%7D %22, webID == null ? %22%5Bnone provided%5D%22 : webID);%0A            %7D%0A
             temp
@@ -3521,24 +3521,192 @@
 out, true);%0A
+            if (logger.isDebugEnabled()) %7B%0A                logger.debug(%22rest template for webID %7B%7D created%22, webID == null ? %22%5Bnone provided%5D%22 : webID);%0A            %7D%0A
         %7D ca

Add debug output