001/******************************************************************************* 002 * Copyright 2017 The MIT Internet Trust Consortium 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 *******************************************************************************/ 016 017package org.mitre.openid.connect.service.impl; 018 019import java.io.IOException; 020import java.util.concurrent.ExecutionException; 021import java.util.concurrent.TimeUnit; 022 023import org.apache.commons.io.IOUtils; 024import org.apache.http.HttpEntity; 025import org.apache.http.HttpResponse; 026import org.apache.http.client.HttpClient; 027import org.apache.http.client.methods.HttpGet; 028import org.apache.http.impl.client.HttpClientBuilder; 029import org.mitre.oauth2.model.ClientDetailsEntity; 030import org.mitre.openid.connect.model.CachedImage; 031import org.mitre.openid.connect.service.ClientLogoLoadingService; 032import org.springframework.stereotype.Service; 033 034import com.google.common.base.Strings; 035import com.google.common.cache.CacheBuilder; 036import com.google.common.cache.CacheLoader; 037import com.google.common.cache.LoadingCache; 038import com.google.common.util.concurrent.UncheckedExecutionException; 039 040/** 041 * @author jricher 042 * 043 */ 044@Service("inMemoryClientLogoLoadingService") 045public class InMemoryClientLogoLoadingService implements ClientLogoLoadingService { 046 047 private LoadingCache<ClientDetailsEntity, CachedImage> cache; 048 049 public InMemoryClientLogoLoadingService() { 050 this(HttpClientBuilder.create().useSystemProperties().build()); 051 } 052 053 /** 054 * 055 */ 056 public InMemoryClientLogoLoadingService(HttpClient httpClient) { 057 058 cache = CacheBuilder.newBuilder() 059 .maximumSize(100) 060 .expireAfterAccess(14, TimeUnit.DAYS) 061 .build(new ClientLogoFetcher(httpClient)); 062 063 } 064 065 066 /* (non-Javadoc) 067 * @see org.mitre.openid.connect.service.ClientLogoLoadingService#getLogo(org.mitre.oauth2.model.ClientDetailsEntity) 068 */ 069 @Override 070 public CachedImage getLogo(ClientDetailsEntity client) { 071 try { 072 if (client != null && !Strings.isNullOrEmpty(client.getLogoUri())) { 073 return cache.get(client); 074 } else { 075 return null; 076 } 077 } catch (UncheckedExecutionException | ExecutionException e) { 078 return null; 079 } 080 } 081 082 /** 083 * @author jricher 084 * 085 */ 086 public class ClientLogoFetcher extends CacheLoader<ClientDetailsEntity, CachedImage> { 087 private HttpClient httpClient; 088 089 public ClientLogoFetcher() { 090 this(HttpClientBuilder.create().useSystemProperties().build()); 091 } 092 093 public ClientLogoFetcher(HttpClient httpClient) { 094 this.httpClient = httpClient; 095 } 096 097 /* (non-Javadoc) 098 * @see com.google.common.cache.CacheLoader#load(java.lang.Object) 099 */ 100 @Override 101 public CachedImage load(ClientDetailsEntity key) throws Exception { 102 try { 103 HttpResponse response = httpClient.execute(new HttpGet(key.getLogoUri())); 104 105 HttpEntity entity = response.getEntity(); 106 107 CachedImage image = new CachedImage(); 108 109 image.setContentType(entity.getContentType().getValue()); 110 image.setLength(entity.getContentLength()); 111 image.setData(IOUtils.toByteArray(entity.getContent())); 112 113 return image; 114 } catch (IOException e) { 115 throw new IllegalArgumentException("Unable to load client image."); 116 } 117 } 118 119 } 120 121 122}