KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > generation > GenericProxyGenerator


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.generation;
17
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import javax.servlet.http.HttpServletRequest JavaDoc;
23 import javax.servlet.http.HttpServletResponse JavaDoc;
24
25 import org.apache.avalon.framework.parameters.Parameters;
26 import org.apache.avalon.framework.service.ServiceException;
27 import org.apache.avalon.framework.service.ServiceManager;
28 import org.apache.cocoon.ProcessingException;
29 import org.apache.cocoon.xml.XMLUtils;
30 import org.apache.cocoon.environment.SourceResolver;
31 import org.apache.cocoon.environment.http.HttpEnvironment;
32 import org.apache.cocoon.util.RequestForwardingHttpMethod;
33 import org.apache.commons.httpclient.Header;
34 import org.apache.commons.httpclient.HttpConnection;
35 import org.apache.commons.httpclient.HttpState;
36 import org.apache.commons.httpclient.HttpURL;
37 import org.apache.commons.httpclient.UsernamePasswordCredentials;
38 import org.apache.excalibur.xml.sax.SAXParser;
39 import org.xml.sax.InputSource JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41
42 /**
43  * This is a generic HTTP proxy, designed to handle any possible HTTP method,
44  * but with a particular bias towards WebDAV. As of now it's pretty unstable, but
45  * still it might be a good proof of concept towards a pure HTTP(++) proxy.
46  *
47  * <br>TODO: doesn't handle authentication properly
48  * <br>TODO: doesn't handle (and doubt it'll ever will) HTTP/1.1 keep-alive
49  *
50  * @author <a HREF="mailto:gianugo@apache.org">Gianugo Rabellino</a>
51  * @version $Id: GenericProxyGenerator.java 278591 2005-09-04 13:24:23Z pier $
52  */

53 public class GenericProxyGenerator extends ServiceableGenerator {
54
55     /** The real URL to forward requests to */
56     HttpURL destination;
57     /** The current request */
58     HttpServletRequest JavaDoc request;
59     /** The current response */
60     HttpServletResponse JavaDoc response;
61     /** The current request */
62     String JavaDoc path;
63     SAXParser parser;
64
65     /**
66      * Compose and get a SAX parser for further use.
67      *
68      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
69      */

70     public void service(ServiceManager manager) throws ServiceException {
71         super.service(manager);
72         this.parser = (SAXParser)manager.lookup(SAXParser.ROLE);
73     }
74
75     /**
76      * Dispose
77      */

78     public void dispose() {
79         if ( this.manager != null ) {
80             this.manager.release( this.parser );
81             this.parser = null;
82         }
83         super.dispose();
84     }
85
86     /**
87      * Setup this component by getting the (required) "url" parameter and the
88      * (optional) "path" parameter. If path is not specified, the request URI will
89      * be used and forwarded.
90      *
91      * TODO: handle query string
92      *
93      * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
94      */

95     public void setup(
96         SourceResolver resolver,
97         Map JavaDoc objectModel,
98         String JavaDoc src,
99         Parameters par)
100         throws ProcessingException, SAXException JavaDoc, IOException JavaDoc {
101             String JavaDoc url = par.getParameter("url", null);
102             request = (HttpServletRequest JavaDoc)objectModel.get(HttpEnvironment.HTTP_REQUEST_OBJECT);
103             response = (HttpServletResponse JavaDoc)objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT);
104
105             if (url == null) {
106                 throw new ProcessingException("Missing the \"url\" parameter");
107             }
108             path = par.getParameter("path", null);
109             if (path == null)
110                 path = request.getRequestURI();
111             destination = new HttpURL(url);
112
113       }
114
115
116     /**
117      * Get the request data, pass them on to the forwarder and return the result.
118      *
119      * TODO: much better header handling
120      * TODO: handle non XML and bodyless responses (probably needs a smarter Serializer,
121      * since some XML has to go through the pipeline anyway.
122      *
123      * @see org.apache.cocoon.generation.Generator#generate()
124      */

125     public void generate()
126         throws IOException JavaDoc, SAXException JavaDoc, ProcessingException {
127             RequestForwardingHttpMethod method =
128                 new RequestForwardingHttpMethod(request, destination);
129
130             // Build the forwarded connection
131
HttpConnection conn = new HttpConnection(destination.getHost(), destination.getPort());
132             HttpState state = new HttpState();
133             state.setCredentials(null, destination.getHost(),
134                 new UsernamePasswordCredentials(destination.getUser(), destination.getPassword()));
135             method.setPath(path);
136
137             // Execute the method
138
method.execute(state, conn);
139
140             // Send the output to the client: set the status code...
141
response.setStatus(method.getStatusCode());
142
143             // ... retrieve the headers from the origin server and pass them on
144
Header[] methodHeaders = method.getResponseHeaders();
145             for (int i = 0; i < methodHeaders.length; i++) {
146                 // there is more than one DAV header
147
if (methodHeaders[i].getName().equals("DAV")) {
148                     response.addHeader(methodHeaders[i].getName(), methodHeaders[i].getValue());
149                 } else if (methodHeaders[i].getName().equals("Content-Length")) {
150                     // drop the original Content-Length header. Don't ask me why but there
151
// it's always one byte off
152
} else {
153                     response.setHeader(methodHeaders[i].getName(), methodHeaders[i].getValue());
154                 }
155             }
156
157             // no HTTP keepalives here...
158
response.setHeader("Connection", "close");
159
160             // Parse the XML, if any
161
if (method.getResponseHeader("Content-Type").getValue().startsWith("text/xml")) {
162                 InputStream JavaDoc stream = method.getResponseBodyAsStream();
163                 parser.parse(new InputSource JavaDoc(stream), this.contentHandler, this.lexicalHandler);
164             } else {
165                 // Just send a dummy XML
166
this.contentHandler.startDocument();
167                 this.contentHandler.startElement("", "no-xml-content", "no-xml-content", XMLUtils.EMPTY_ATTRIBUTES);
168                 this.contentHandler.endElement("", "no-xml-content", "no-xml-content");
169                 this.contentHandler.endDocument();
170             }
171
172             // again, no keepalive here.
173
conn.close();
174     }
175
176 }
177
Popular Tags