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.http;
018    
019    import java.lang.reflect.Proxy;
020    import java.net.URI;
021    import java.net.URISyntaxException;
022    import java.net.URL;
023    import java.util.Map;
024    
025    import javax.servlet.http.HttpServletRequest;
026    import javax.servlet.http.HttpServletResponse;
027    
028    import com.google.appengine.api.urlfetch.HTTPRequest;
029    import com.google.appengine.api.urlfetch.HTTPResponse;
030    import com.google.appengine.api.urlfetch.URLFetchService;
031    
032    import org.apache.camel.Exchange;
033    import org.apache.camel.Producer;
034    import org.apache.camel.component.gae.bind.HttpBindingInvocationHandler;
035    import org.apache.camel.component.gae.bind.InboundBinding;
036    import org.apache.camel.component.gae.bind.OutboundBinding;
037    import org.apache.camel.component.gae.bind.OutboundBindingSupport;
038    import org.apache.camel.component.http.HttpBinding;
039    import org.apache.camel.component.http.HttpClientConfigurer;
040    import org.apache.camel.component.servlet.ServletComponent;
041    import org.apache.camel.component.servlet.ServletEndpoint;
042    import org.apache.camel.util.URISupport;
043    import org.apache.camel.util.UnsafeUriCharactersEncoder;
044    import org.apache.commons.httpclient.HttpConnectionManager;
045    import org.apache.commons.httpclient.params.HttpClientParams;
046    
047    /**
048     * Represents a <a href="http://camel.apache.org/todo.html">Google App Engine
049     * HTTP endpoint</a>.
050     */
051    public class GHttpEndpoint extends ServletEndpoint implements OutboundBindingSupport<GHttpEndpoint, HTTPRequest, HTTPResponse> {
052    
053        public static final String GHTTP_SCHEME = "ghttp";
054        public static final String GHTTPS_SCHEME = "ghttps";
055        
056        public static final String HTTP_SCHEME = "http";
057        public static final String HTTPS_SCHEME = "https";
058        
059        private URLFetchService urlFetchService;
060        
061        private OutboundBinding<GHttpEndpoint, HTTPRequest, HTTPResponse> outboundBinding;
062        private InboundBinding<GHttpEndpoint, HttpServletRequest, HttpServletResponse> inboundBinding;
063        
064        public GHttpEndpoint(String endpointUri, ServletComponent component,
065                URI httpUri, HttpClientParams params,
066                HttpConnectionManager httpConnectionManager,
067                HttpClientConfigurer clientConfigurer) throws URISyntaxException {
068            super(endpointUri, component, httpUri, params, httpConnectionManager, clientConfigurer);
069        }
070    
071        /**
072         * Constructs a {@link URL} from an <code>uri</code> and an optional
073         * <code>query</code> string. The encoding strategy follow those of the
074         * Camel HTTP component.
075         * 
076         * @param uri
077         *            must be encoded with
078         *            {@link UnsafeUriCharactersEncoder#encode(String)}.
079         * @param query
080         *            decoded query string. Replaces the query part of
081         *            <code>uri</code> if not <code>null</code>.
082         */
083        @SuppressWarnings("unchecked")
084        static URL getEndpointUrl(String uri, String query) throws Exception {
085            Map<String, Object> parameters = null;
086            URI uriObj = new URI(uri);
087            if (query == null) {
088                parameters = URISupport.parseParameters(uriObj);
089            } else {
090                parameters = URISupport.parseQuery(query);
091            }
092            if (uriObj.getScheme().equals(GHTTPS_SCHEME)) {
093                uriObj = new URI(HTTPS_SCHEME + ":" + uriObj.getRawSchemeSpecificPart());
094            } else { // ghttp or anything else
095                uriObj = new URI(HTTP_SCHEME + ":" + uriObj.getRawSchemeSpecificPart());
096            }
097            return URISupport.createRemainingURI(uriObj, (Map)parameters).toURL();
098        }
099        
100        public URL getEndpointUrl() throws Exception {
101            return getEndpointUrl(getEndpointUri(), null);
102        }
103        
104        public URLFetchService getUrlFetchService() {
105            return urlFetchService;
106        }
107    
108        public void setUrlFetchService(URLFetchService urlFetchService) {
109            this.urlFetchService = urlFetchService;
110        }
111    
112        public OutboundBinding<GHttpEndpoint, HTTPRequest, HTTPResponse> getOutboundBinding() {
113            return outboundBinding;
114        }
115        
116        public void setOutboundBinding(OutboundBinding<GHttpEndpoint, HTTPRequest, HTTPResponse> outboundBinding) {
117            this.outboundBinding = outboundBinding;
118        }
119        
120        public InboundBinding<GHttpEndpoint, HttpServletRequest, HttpServletResponse> getInboundBinding() {
121            return inboundBinding;
122        }
123    
124        public void setInboundBinding(
125                InboundBinding<GHttpEndpoint, HttpServletRequest, HttpServletResponse> inboundBinding) {
126            this.inboundBinding = inboundBinding;
127        }
128    
129        /**
130         * Proxies the {@link HttpBinding} returned by {@link super#getBinding()}
131         * with a dynamic proxy. The proxy's invocation handler further delegates to
132         * {@link InboundBinding#readRequest(org.apache.camel.Endpoint, Exchange, Object)}
133         * .
134         * 
135         * @return proxied {@link HttpBinding}.
136         */
137        @Override
138        public HttpBinding getBinding() {
139            return (HttpBinding)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] {HttpBinding.class}, 
140                    new HttpBindingInvocationHandler<GHttpEndpoint, HttpServletRequest, HttpServletResponse>(
141                            this, super.getBinding(), getInboundBinding()));
142        }
143    
144        public Producer createProducer() throws Exception {
145            return new GHttpProducer(this);
146        }
147    
148    }