001/******************************************************************************* 002 * Copyright 2017 The MIT Internet Trust Consortium 003 * 004 * Portions copyright 2011-2013 The MITRE Corporation 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 *******************************************************************************/ 018/** 019 * 020 */ 021package org.mitre.openid.connect.client.service.impl; 022 023import java.io.File; 024import java.io.FileReader; 025import java.io.FileWriter; 026import java.io.IOException; 027import java.lang.reflect.Type; 028import java.util.HashMap; 029import java.util.Map; 030 031import org.mitre.oauth2.model.RegisteredClient; 032import org.mitre.openid.connect.ClientDetailsEntityJsonProcessor; 033import org.mitre.openid.connect.client.service.RegisteredClientService; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037import com.google.common.reflect.TypeToken; 038import com.google.gson.Gson; 039import com.google.gson.GsonBuilder; 040import com.google.gson.JsonDeserializationContext; 041import com.google.gson.JsonDeserializer; 042import com.google.gson.JsonElement; 043import com.google.gson.JsonParseException; 044import com.google.gson.JsonSerializationContext; 045import com.google.gson.JsonSerializer; 046 047/** 048 * @author jricher 049 * 050 */ 051public class JsonFileRegisteredClientService implements RegisteredClientService { 052 053 /** 054 * Logger for this class 055 */ 056 private static final Logger logger = LoggerFactory.getLogger(JsonFileRegisteredClientService.class); 057 058 private Gson gson = new GsonBuilder() 059 .registerTypeAdapter(RegisteredClient.class, new JsonSerializer<RegisteredClient>() { 060 @Override 061 public JsonElement serialize(RegisteredClient src, Type typeOfSrc, JsonSerializationContext context) { 062 return ClientDetailsEntityJsonProcessor.serialize(src); 063 } 064 }) 065 .registerTypeAdapter(RegisteredClient.class, new JsonDeserializer<RegisteredClient>() { 066 @Override 067 public RegisteredClient deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 068 return ClientDetailsEntityJsonProcessor.parseRegistered(json); 069 } 070 }) 071 .setPrettyPrinting() 072 .create(); 073 074 private File file; 075 076 private Map<String, RegisteredClient> clients = new HashMap<>(); 077 078 public JsonFileRegisteredClientService(String filename) { 079 this.file = new File(filename); 080 load(); 081 } 082 083 /* (non-Javadoc) 084 * @see org.mitre.openid.connect.client.service.RegisteredClientService#getByIssuer(java.lang.String) 085 */ 086 @Override 087 public RegisteredClient getByIssuer(String issuer) { 088 return clients.get(issuer); 089 } 090 091 /* (non-Javadoc) 092 * @see org.mitre.openid.connect.client.service.RegisteredClientService#save(java.lang.String, org.mitre.oauth2.model.RegisteredClient) 093 */ 094 @Override 095 public void save(String issuer, RegisteredClient client) { 096 clients.put(issuer, client); 097 write(); 098 } 099 100 /** 101 * Sync the map of clients out to disk. 102 */ 103 @SuppressWarnings("serial") 104 private void write() { 105 try { 106 if (!file.exists()) { 107 // create a new file 108 logger.info("Creating saved clients list in " + file); 109 file.createNewFile(); 110 } 111 FileWriter out = new FileWriter(file); 112 113 gson.toJson(clients, new TypeToken<Map<String, RegisteredClient>>(){}.getType(), out); 114 115 out.close(); 116 117 } catch (IOException e) { 118 logger.error("Could not write to output file", e); 119 } 120 } 121 122 /** 123 * Load the map in from disk. 124 */ 125 @SuppressWarnings("serial") 126 private void load() { 127 try { 128 if (!file.exists()) { 129 logger.info("No sved clients file found in " + file); 130 return; 131 } 132 FileReader in = new FileReader(file); 133 134 clients = gson.fromJson(in, new TypeToken<Map<String, RegisteredClient>>(){}.getType()); 135 136 in.close(); 137 138 } catch (IOException e) { 139 logger.error("Could not read from input file", e); 140 } 141 } 142 143}