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}