/* * Copyright 2011 the original author or authors. * * 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 org.springframework.social.lastfm.auth; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.converter.ByteArrayHttpMessageConverter; import org.springframework.http.converter.FormHttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; import org.springframework.social.ApiBinding; import org.springframework.social.lastfm.api.impl.UserAgentHelper; import org.springframework.social.lastfm.connect.RestTemplateWithHeaders; import org.springframework.social.support.ClientHttpRequestFactorySelector; import org.springframework.web.client.RestTemplate; /** * Base class for LastFm-Auth-based provider API bindings. * * @author Michael Lavelle */ public abstract class AbstractLastFmAuthApiBinding implements ApiBinding { private LastFmAccessGrant lastFmAccessGrant; private final RestTemplate restTemplate; /** * Constructs the API template without user authorization. This is useful * for accessing operations on a provider's API that do not require user * authorization. */ protected AbstractLastFmAuthApiBinding() { this.lastFmAccessGrant = null; HttpHeaders headers = new HttpHeaders(); headers.add("User-Agent", UserAgentHelper.getUserAgent()); restTemplate = new RestTemplateWithHeaders( ClientHttpRequestFactorySelector.getRequestFactory(), headers); restTemplate.setMessageConverters(getMessageConverters(true)); configureRestTemplate(restTemplate); } /** * Constructs the API template with LastFm credentials necessary to perform * operations on behalf of a user. * * @param accessToken * the access token */ protected AbstractLastFmAuthApiBinding( LastFmAccessGrant lastFmAccessGrant) { this.lastFmAccessGrant = lastFmAccessGrant; HttpHeaders headers = new HttpHeaders(); headers.add("User-Agent", UserAgentHelper.getUserAgent()); restTemplate = new RestTemplateWithHeaders( ClientHttpRequestFactorySelector.getRequestFactory(), headers); restTemplate.setMessageConverters(getMessageConverters(true)); configureRestTemplate(restTemplate); } /** * Set the ClientHttpRequestFactory. This is useful when custom * configuration of the request factory is required, such as configuring * custom SSL details. * * @param requestFactory * the request factory */ public void setRequestFactory(ClientHttpRequestFactory requestFactory) { restTemplate.setRequestFactory(requestFactory); } // implementing ApiBinding public boolean isAuthorized() { return lastFmAccessGrant != null; } // public implementation operations /** * Obtains a reference to the REST client backing this API binding and used * to perform API calls. Callers may use the RestTemplate to invoke other * API operations not yet modeled by the binding interface. Callers may also * modify the configuration of the RestTemplate to support unit testing the * API binding with a mock server in a test environment. During * construction, subclasses may apply customizations to the RestTemplate * needed to invoke a specific API. * * @see RestTemplate#setMessageConverters(java.util.List) * @see RestTemplate#setErrorHandler(org.springframework.web.client.ResponseErrorHandler) */ public RestTemplate getRestTemplate() { return restTemplate; } // subclassing hooks /** * Subclassing hook to enable customization of the RestTemplate used to * consume provider API resources. An example use case might be to configure * a custom error handler. Note that this method is called after the * RestTemplate has been configured with the message converters returned * from getMessageConverters(). * * @param restTemplate * the RestTemplate to configure. */ protected void configureRestTemplate(RestTemplate restTemplate) { } /** * Returns a list of {@link HttpMessageConverter}s to be used by the * internal {@link RestTemplate}. By default, this includes a * {@link StringHttpMessageConverter}, a * {@link MappingJacksonHttpMessageConverter}, a * {@link ByteArrayHttpMessageConverter}, and a * {@link FormHttpMessageConverter}. The {@link FormHttpMessageConverter} is * set to use "UTF-8" character encoding. Override this method to add * additional message converters or to replace the default list of message * converters. */ protected List<HttpMessageConverter<?>> getMessageConverters(boolean json) { List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>(); messageConverters.add(new StringHttpMessageConverter()); messageConverters.add(getFormMessageConverter()); if (json) { messageConverters.add(getJsonMessageConverter()); } messageConverters.add(getByteArrayMessageConverter()); return messageConverters; } /** * Returns an {@link FormHttpMessageConverter} to be used by the internal * {@link RestTemplate}. By default, the message converter is set to use * "UTF-8" character encoding. Override to customize the message converter * (for example, to set supported media types or message converters for the * parts of a multipart message). To remove/replace this or any of the other * message converters that are registered by default, override the * getMessageConverters() method instead. */ protected FormHttpMessageConverter getFormMessageConverter() { FormHttpMessageConverter converter = new FormHttpMessageConverter(); converter.setCharset(Charset.forName("UTF-8")); return converter; } /** * Returns a {@link MappingJacksonHttpMessageConverter} to be used by the * internal {@link RestTemplate}. Override to customize the message * converter (for example, to set a custom object mapper or supported media * types). To remove/replace this or any of the other message converters * that are registered by default, override the getMessageConverters() * method instead. */ protected MappingJackson2HttpMessageConverter getJsonMessageConverter() { return new MappingJackson2HttpMessageConverter(); } /** * Returns a {@link ByteArrayHttpMessageConverter} to be used by the * internal {@link RestTemplate} when consuming image or other binary * resources. By default, the message converter supports "image/jpeg", * "image/gif", and "image/png" media types. Override to customize the * message converter (for example, to set supported media types). To * remove/replace this or any of the other message converters that are * registered by default, override the getMessageConverters() method * instead. */ protected ByteArrayHttpMessageConverter getByteArrayMessageConverter() { ByteArrayHttpMessageConverter converter = new ByteArrayHttpMessageConverter(); converter.setSupportedMediaTypes(Arrays.asList(MediaType.IMAGE_JPEG, MediaType.IMAGE_GIF, MediaType.IMAGE_PNG)); return converter; } }