1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.nnsoft.sameas4j;
23
24 import static java.lang.String.format;
25 import java.io.IOException;
26 import java.io.InputStreamReader;
27 import java.io.Reader;
28 import java.net.HttpURLConnection;
29 import java.net.MalformedURLException;
30 import java.net.URI;
31 import java.net.URL;
32 import java.net.URLConnection;
33 import java.util.concurrent.locks.Lock;
34 import java.util.concurrent.locks.ReentrantLock;
35
36 import org.nnsoft.sameas4j.cache.Cache;
37 import org.nnsoft.sameas4j.cache.CacheKey;
38
39 import com.google.gson.Gson;
40 import com.google.gson.GsonBuilder;
41 import com.google.gson.JsonParseException;
42
43
44
45
46 final class SameAsServiceImpl implements SameAsService {
47
48
49
50
51 private static final String SERVICE_URL = "http://sameas.org/json?uri=%s";
52
53
54
55
56 private static final String SERVICE_KEYWORD = "http://sameas.org/json?q=%s";
57
58
59
60
61 private final GsonBuilder gsonBuilder = new GsonBuilder();
62
63
64
65
66 private final Lock lock = new ReentrantLock();
67
68
69
70
71 private Cache cache;
72
73
74
75
76 public SameAsServiceImpl() {
77 this.gsonBuilder.registerTypeAdapter(Equivalence.class, new EquivalenceDeserializer());
78 this.gsonBuilder.registerTypeAdapter(EquivalenceList.class, new EquivalenceListDeserializer());
79 }
80
81
82
83
84 public void setCache(Cache cache) {
85 this.cache = cache;
86 }
87
88
89
90
91 public Equivalence getDuplicates(URI uri) throws SameAsServiceException {
92 return invokeURL(format(SERVICE_URL, uri), Equivalence.class);
93 }
94
95
96
97
98 public EquivalenceList getDuplicates(String keyword) throws SameAsServiceException {
99 return invokeURL(format(SERVICE_KEYWORD, keyword), EquivalenceList.class);
100 }
101
102
103
104
105
106
107
108
109
110
111 private <T> T invokeURL(String toBeInvoked, Class<T> returnType) throws SameAsServiceException {
112 URL url;
113 try {
114 url = new URL(toBeInvoked);
115 } catch (MalformedURLException e) {
116 throw new SameAsServiceException("An error occurred while building the URL '"
117 + toBeInvoked
118 + "'");
119 }
120
121 URLConnection connection = null;
122 Reader reader = null;
123
124 if (this.cache != null) {
125 lock.lock();
126 }
127
128 try {
129 connection = url.openConnection();
130 long lastModified = connection.getLastModified();
131
132 if (this.cache != null) {
133 CacheKey cacheKey = new CacheKey(toBeInvoked, lastModified);
134 T cached = this.cache.get(cacheKey, returnType);
135 if (cached != null) {
136 return cached;
137 }
138 }
139
140 if (connection instanceof HttpURLConnection) {
141 ((HttpURLConnection) connection).connect();
142 }
143
144 reader = new InputStreamReader(connection.getInputStream());
145 Gson gson = this.gsonBuilder.create();
146 T response = gson.fromJson(reader, returnType);
147
148 if (this.cache != null) {
149 CacheKey cacheKey = new CacheKey(toBeInvoked, lastModified);
150 this.cache.put(cacheKey, response);
151 }
152
153 return response;
154 } catch (IOException e) {
155 throw new SameAsServiceException(format("An error occurred while invoking the URL '%s': %s",
156 toBeInvoked,
157 e.getMessage()));
158 } catch (JsonParseException e) {
159 throw new SameAsServiceException("An error occurred while parsing the JSON response", e);
160 } finally {
161 if (this.cache != null) {
162 lock.unlock();
163 }
164
165 if (connection != null && connection instanceof HttpURLConnection) {
166 ((HttpURLConnection) connection).disconnect();
167 }
168 if (reader != null) {
169 try {
170 reader.close();
171 } catch (IOException e) {
172
173 }
174 }
175 }
176 }
177
178 }