source: josm/trunk/src/oauth/signpost/AbstractOAuthConsumer.java@ 6168

Last change on this file since 6168 was 4231, checked in by stoecker, 13 years ago

add signpost and metadata extractor code to repository directly

File size: 9.0 KB
Line 
1/* Copyright (c) 2009 Matthias Kaeppler
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package oauth.signpost;
16
17import java.io.IOException;
18import java.io.InputStream;
19import java.util.Random;
20
21import oauth.signpost.basic.UrlStringRequestAdapter;
22import oauth.signpost.exception.OAuthCommunicationException;
23import oauth.signpost.exception.OAuthExpectationFailedException;
24import oauth.signpost.exception.OAuthMessageSignerException;
25import oauth.signpost.http.HttpParameters;
26import oauth.signpost.http.HttpRequest;
27import oauth.signpost.signature.AuthorizationHeaderSigningStrategy;
28import oauth.signpost.signature.HmacSha1MessageSigner;
29import oauth.signpost.signature.OAuthMessageSigner;
30import oauth.signpost.signature.QueryStringSigningStrategy;
31import oauth.signpost.signature.SigningStrategy;
32
33/**
34 * ABC for consumer implementations. If you're developing a custom consumer you
35 * will probably inherit from this class to save you a lot of work.
36 *
37 * @author Matthias Kaeppler
38 */
39public abstract class AbstractOAuthConsumer implements OAuthConsumer {
40
41 private static final long serialVersionUID = 1L;
42
43 private String consumerKey, consumerSecret;
44
45 private String token;
46
47 private OAuthMessageSigner messageSigner;
48
49 private SigningStrategy signingStrategy;
50
51 // these are params that may be passed to the consumer directly (i.e.
52 // without going through the request object)
53 private HttpParameters additionalParameters;
54
55 // these are the params which will be passed to the message signer
56 private HttpParameters requestParameters;
57
58 private boolean sendEmptyTokens;
59
60 public AbstractOAuthConsumer(String consumerKey, String consumerSecret) {
61 this.consumerKey = consumerKey;
62 this.consumerSecret = consumerSecret;
63 setMessageSigner(new HmacSha1MessageSigner());
64 setSigningStrategy(new AuthorizationHeaderSigningStrategy());
65 }
66
67 public void setMessageSigner(OAuthMessageSigner messageSigner) {
68 this.messageSigner = messageSigner;
69 messageSigner.setConsumerSecret(consumerSecret);
70 }
71
72 public void setSigningStrategy(SigningStrategy signingStrategy) {
73 this.signingStrategy = signingStrategy;
74 }
75
76 public void setAdditionalParameters(HttpParameters additionalParameters) {
77 this.additionalParameters = additionalParameters;
78 }
79
80 public HttpRequest sign(HttpRequest request) throws OAuthMessageSignerException,
81 OAuthExpectationFailedException, OAuthCommunicationException {
82 if (consumerKey == null) {
83 throw new OAuthExpectationFailedException("consumer key not set");
84 }
85 if (consumerSecret == null) {
86 throw new OAuthExpectationFailedException("consumer secret not set");
87 }
88
89 requestParameters = new HttpParameters();
90 try {
91 if (additionalParameters != null) {
92 requestParameters.putAll(additionalParameters, false);
93 }
94 collectHeaderParameters(request, requestParameters);
95 collectQueryParameters(request, requestParameters);
96 collectBodyParameters(request, requestParameters);
97
98 // add any OAuth params that haven't already been set
99 completeOAuthParameters(requestParameters);
100
101 requestParameters.remove(OAuth.OAUTH_SIGNATURE);
102
103 } catch (IOException e) {
104 throw new OAuthCommunicationException(e);
105 }
106
107 String signature = messageSigner.sign(request, requestParameters);
108 OAuth.debugOut("signature", signature);
109
110 signingStrategy.writeSignature(signature, request, requestParameters);
111 OAuth.debugOut("Auth header", request.getHeader("Authorization"));
112 OAuth.debugOut("Request URL", request.getRequestUrl());
113
114 return request;
115 }
116
117 public HttpRequest sign(Object request) throws OAuthMessageSignerException,
118 OAuthExpectationFailedException, OAuthCommunicationException {
119 return sign(wrap(request));
120 }
121
122 public String sign(String url) throws OAuthMessageSignerException,
123 OAuthExpectationFailedException, OAuthCommunicationException {
124 HttpRequest request = new UrlStringRequestAdapter(url);
125
126 // switch to URL signing
127 SigningStrategy oldStrategy = this.signingStrategy;
128 this.signingStrategy = new QueryStringSigningStrategy();
129
130 sign(request);
131
132 // revert to old strategy
133 this.signingStrategy = oldStrategy;
134
135 return request.getRequestUrl();
136 }
137
138 /**
139 * Adapts the given request object to a Signpost {@link HttpRequest}. How
140 * this is done depends on the consumer implementation.
141 *
142 * @param request
143 * the native HTTP request instance
144 * @return the adapted request
145 */
146 protected abstract HttpRequest wrap(Object request);
147
148 public void setTokenWithSecret(String token, String tokenSecret) {
149 this.token = token;
150 messageSigner.setTokenSecret(tokenSecret);
151 }
152
153 public String getToken() {
154 return token;
155 }
156
157 public String getTokenSecret() {
158 return messageSigner.getTokenSecret();
159 }
160
161 public String getConsumerKey() {
162 return this.consumerKey;
163 }
164
165 public String getConsumerSecret() {
166 return this.consumerSecret;
167 }
168
169 /**
170 * <p>
171 * Helper method that adds any OAuth parameters to the given request
172 * parameters which are missing from the current request but required for
173 * signing. A good example is the oauth_nonce parameter, which is typically
174 * not provided by the client in advance.
175 * </p>
176 * <p>
177 * It's probably not a very good idea to override this method. If you want
178 * to generate different nonces or timestamps, override
179 * {@link #generateNonce()} or {@link #generateTimestamp()} instead.
180 * </p>
181 *
182 * @param out
183 * the request parameter which should be completed
184 */
185 protected void completeOAuthParameters(HttpParameters out) {
186 if (!out.containsKey(OAuth.OAUTH_CONSUMER_KEY)) {
187 out.put(OAuth.OAUTH_CONSUMER_KEY, consumerKey, true);
188 }
189 if (!out.containsKey(OAuth.OAUTH_SIGNATURE_METHOD)) {
190 out.put(OAuth.OAUTH_SIGNATURE_METHOD, messageSigner.getSignatureMethod(), true);
191 }
192 if (!out.containsKey(OAuth.OAUTH_TIMESTAMP)) {
193 out.put(OAuth.OAUTH_TIMESTAMP, generateTimestamp(), true);
194 }
195 if (!out.containsKey(OAuth.OAUTH_NONCE)) {
196 out.put(OAuth.OAUTH_NONCE, generateNonce(), true);
197 }
198 if (!out.containsKey(OAuth.OAUTH_VERSION)) {
199 out.put(OAuth.OAUTH_VERSION, OAuth.VERSION_1_0, true);
200 }
201 if (!out.containsKey(OAuth.OAUTH_TOKEN)) {
202 if (token != null && !token.equals("") || sendEmptyTokens) {
203 out.put(OAuth.OAUTH_TOKEN, token, true);
204 }
205 }
206 }
207
208 public HttpParameters getRequestParameters() {
209 return requestParameters;
210 }
211
212 public void setSendEmptyTokens(boolean enable) {
213 this.sendEmptyTokens = enable;
214 }
215
216 /**
217 * Collects OAuth Authorization header parameters as per OAuth Core 1.0 spec
218 * section 9.1.1
219 */
220 protected void collectHeaderParameters(HttpRequest request, HttpParameters out) {
221 HttpParameters headerParams = OAuth.oauthHeaderToParamsMap(request.getHeader(OAuth.HTTP_AUTHORIZATION_HEADER));
222 out.putAll(headerParams, false);
223 }
224
225 /**
226 * Collects x-www-form-urlencoded body parameters as per OAuth Core 1.0 spec
227 * section 9.1.1
228 */
229 protected void collectBodyParameters(HttpRequest request, HttpParameters out)
230 throws IOException {
231
232 // collect x-www-form-urlencoded body params
233 String contentType = request.getContentType();
234 if (contentType != null && contentType.startsWith(OAuth.FORM_ENCODED)) {
235 InputStream payload = request.getMessagePayload();
236 out.putAll(OAuth.decodeForm(payload), true);
237 }
238 }
239
240 /**
241 * Collects HTTP GET query string parameters as per OAuth Core 1.0 spec
242 * section 9.1.1
243 */
244 protected void collectQueryParameters(HttpRequest request, HttpParameters out) {
245
246 String url = request.getRequestUrl();
247 int q = url.indexOf('?');
248 if (q >= 0) {
249 // Combine the URL query string with the other parameters:
250 out.putAll(OAuth.decodeForm(url.substring(q + 1)), true);
251 }
252 }
253
254 protected String generateTimestamp() {
255 return Long.toString(System.currentTimeMillis() / 1000L);
256 }
257
258 protected String generateNonce() {
259 return Long.toString(new Random().nextLong());
260 }
261}
Note: See TracBrowser for help on using the repository browser.