001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.gae.auth;
018    
019    import java.security.PrivateKey;
020    
021    import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
022    import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
023    import com.google.gdata.client.authn.oauth.OAuthHelper;
024    import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
025    import com.google.gdata.client.authn.oauth.OAuthRsaSha1Signer;
026    import com.google.gdata.client.authn.oauth.OAuthSigner;
027    
028    import org.apache.camel.Component;
029    import org.apache.camel.Consumer;
030    import org.apache.camel.Processor;
031    import org.apache.camel.Producer;
032    import org.apache.camel.component.gae.bind.OutboundBinding;
033    import org.apache.camel.impl.DefaultEndpoint;
034    
035    /**
036     * Represents a <a href="http://camel.apache.org/gauth.html">GAuth Endpoint</a>.
037     * Instances can have one of two names, either <code>authorize</code> for
038     * requesting an unauthorized request token or <code>upgrade</code> for
039     * upgrading an authorized request token to an access token. The corresponding
040     * endpoint URIs are <code>gauth:authorize</code> and <code>gauth:upgrade</code>
041     * , respectively.
042     */
043    public class GAuthEndpoint  extends DefaultEndpoint {
044    
045        public static enum Name {
046            
047            /**
048             * Name of the endpoint for requesting an unauthorized request token. 
049             */
050            AUTHORIZE,
051    
052            /**
053             * Name of the endpoint for upgrading an authorized request token to an
054             * access token.
055             */
056            UPGRADE
057            
058        }
059        
060        private OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> authorizeBinding;
061    
062        private OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> upgradeBinding;
063        
064        private Name name;
065        
066        private String callback;
067        
068        private String scope;
069    
070        private String consumerKey;
071        
072        private String consumerSecret;
073    
074        private GAuthKeyLoader keyLoader;
075    
076        private GAuthService service;
077        
078        private PrivateKey cachedKey;
079        
080        /**
081         * Creates a new GAuthEndpoint.
082         * 
083         * @param endpointUri
084         * @param component
085         *            component that created this endpoint.
086         * @param name
087         *            either <code>authorize</code> or <code>upgrade</code>.
088         * @throws IllegalArgumentException
089         *             if the endpoint name is invalid.
090         */
091        public GAuthEndpoint(String endpointUri, Component component, String name) {
092            super(endpointUri, component);
093            this.name = Name.valueOf(name.toUpperCase());
094            this.service = new GAuthServiceImpl(this);
095        }
096        
097        public OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> getAuthorizeBinding() {
098            return authorizeBinding;
099        }
100    
101        /**
102         * Sets the binding for <code>gauth:authorize</code> endpoints.  
103         * 
104         * @param authorizeBinding
105         * @see GAuthAuthorizeBinding
106         */
107        public void setAuthorizeBinding(OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> authorizeBinding) {
108            this.authorizeBinding = authorizeBinding;
109        }
110    
111        public OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> getUpgradeBinding() {
112            return upgradeBinding;
113        }
114    
115        /**
116         * Sets the binding for <code>gauth:upgrade</code> endpoints. 
117         * 
118         * @param upgradeBinding
119         * @see GAuthUpgradeBinding
120         */
121        public void setUpgradeBinding(OutboundBinding<GAuthEndpoint, GoogleOAuthParameters, GoogleOAuthParameters> upgradeBinding) {
122            this.upgradeBinding = upgradeBinding;
123        }
124    
125        /**
126         * Returns the component instance that created this endpoint.
127         */
128        public GAuthComponent getComponent() {
129            return (GAuthComponent)super.getComponent();
130        }
131    
132        /**
133         * Returns the endpoint name.
134         */
135        public Name getName() {
136            return name;
137        }
138    
139        /**
140         * Returns the value of callback query parameter in the
141         * <code>gauth:authorize</code> endpoint URI.
142         */
143        public String getCallback() {
144            return callback;
145        }
146    
147        public void setCallback(String callback) {
148            this.callback = callback;
149        }
150    
151        /**
152         * Returns the value of the scope query parameter in
153         * <code>gauth:authorize</code> endpoint URI. This can be a single scope or
154         * a comma-separated list of scopes.
155         */
156        public String getScope() {
157            return scope;
158        }
159    
160        public void setScope(String services) {
161            this.scope = services;
162        }
163    
164        /**
165         * Returns the value of the scope query parameter as array.
166         * @see #getScope()
167         */
168        public String[] getScopeArray() {
169            return getScope().split(",");
170        }
171    
172        /**
173         * Returns the consumer key. If this endpoint's consumer key is
174         * <code>null</code> then {@link GAuthComponent#getConsumerKey()} is
175         * returned.
176         */
177        public String getConsumerKey() {
178            if (consumerKey == null) {
179                return getComponent().getConsumerKey();
180            }
181            return consumerKey;
182        }
183    
184        /**
185         * Sets the consumer key. This key is generated when a web application is
186         * registered at Google.  
187         * 
188         * @param consumerKey
189         *            consumer key to set.
190         */
191        public void setConsumerKey(String consumerKey) {
192            this.consumerKey = consumerKey;
193        }
194    
195        /**
196         * Returns the consumer secret. If this endpoint's consumer secret is
197         * <code>null</code> then {@link GAuthComponent#getConsumerSecret()} is
198         * returned.
199         */
200        public String getConsumerSecret() {
201            if (consumerSecret == null) {
202                return getComponent().getConsumerSecret();
203            }
204            return consumerSecret;
205        }
206    
207        /**
208         * Sets the consumer secret. This secret is generated when a web application
209         * is registered at Google. Only set the consumer secret if the HMAC-SHA1 
210         * signature method shall be used.
211         * 
212         * @param consumerSecret
213         *            consumer secret to set.
214         */
215        public void setConsumerSecret(String consumerSecret) {
216            this.consumerSecret = consumerSecret;
217        }
218    
219        /**
220         * Returns the key loader. If this endpoint's key loader is
221         * <code>null</code> then {@link GAuthComponent#getKeyLoader()} is
222         * returned.
223         */
224        public GAuthKeyLoader getKeyLoader() {
225            if (keyLoader == null) {
226                return getComponent().getKeyLoader();
227            }
228            return keyLoader;
229        }
230    
231        /**
232         * Sets a key loader for loading a private key. A private key is required
233         * when the RSA-SHA1 signature method shall be used.    
234         * 
235         * @param keyLoader
236         *            key loader to set.
237         */
238        public void setKeyLoader(GAuthKeyLoader keyLoader) {
239            this.keyLoader = keyLoader;
240        }
241    
242        public GAuthService getService() {
243            return service;
244        }
245    
246        /**
247         * Sets the service that makes the remote calls to Google services. Testing
248         * code should inject a mock service here (using serviceRef in endpoint
249         * URI).
250         * 
251         * @param service
252         */
253        public void setService(GAuthService service) {
254            this.service = service;
255        }
256    
257        /**
258         * @throws UnsupportedOperationException
259         */
260        public Consumer createConsumer(Processor processor) throws Exception {
261            throw new UnsupportedOperationException("consumption from gauth endpoint not supported");
262        }
263    
264        /**
265         * Returns a {@link GAuthProducer}
266         */
267        public Producer createProducer() throws Exception {
268            return new GAuthProducer(this);
269        }
270    
271        /**
272         * Returns <code>true</code>.
273         */
274        public boolean isSingleton() {
275            return true;
276        }
277    
278        /**
279         * Creates an {@link OAuthHelper} configured with either an
280         * {@link OAuthHmacSha1Signer} or an {@link OAuthRsaSha1Signer}, depending
281         * on this endpoint's properties.
282         * 
283         * @return
284         * @throws Exception
285         */
286        OAuthHelper newOAuthHelper() throws Exception {
287            OAuthSigner signer = null;
288            if (getKeyLoader() == null) {
289                signer = new OAuthHmacSha1Signer();
290            } else {
291                signer = new OAuthRsaSha1Signer(getPrivateKey());
292            }
293            return new GoogleOAuthHelper(signer);
294        }
295        
296        private synchronized PrivateKey getPrivateKey() throws Exception {
297            if (cachedKey == null) {
298                cachedKey = getKeyLoader().loadPrivateKey();
299            }
300            return cachedKey;
301        }
302        
303    }