Work around Tomcat/AJP bug.
[jsvc.git] / src / dolda / jsvc / j2ee / J2eeRequest.java
CommitLineData
78f5d120
FT
1package dolda.jsvc.j2ee;
2
3import dolda.jsvc.*;
4import dolda.jsvc.util.*;
5import java.io.*;
6import java.util.*;
7import java.net.*;
8import javax.servlet.*;
9import javax.servlet.http.*;
10
11public class J2eeRequest extends ResponseBuffer {
12 private ServletConfig cfg;
13 private HttpServletRequest req;
14 private HttpServletResponse resp;
15 private String method, path;
4b8346e1 16 private URL url, context;
ca045757 17 private MultiMap<String, String> params = null;
1c868f4e 18 private Map<Object, Object> props = new HashMap<Object, Object>();
78f5d120
FT
19
20 public J2eeRequest(ServletConfig cfg, HttpServletRequest req, HttpServletResponse resp) {
21 this.cfg = cfg;
22 this.req = req;
23 this.resp = resp;
78f5d120 24 {
433ee775
FT
25 /* Ewwww, this is disgusting! */
26 String scheme = req.getScheme();
27 int port = -1;
78f5d120 28 String host = req.getHeader("Host");
433ee775 29 if((host == null) || (host.length() < 1)) {
78f5d120 30 host = req.getLocalAddr();
433ee775
FT
31 port = req.getLocalPort();
32 if((port == 80) && scheme.equals("http"))
33 port = -1;
34 else if((port == 443) && scheme.equals("https"))
35 port = -1;
36 } else {
37 int p;
38 if((host.charAt(0) == '[') && ((p = host.indexOf(']', 1)) > 1)) {
39 String newhost = host.substring(1, p);
40 if((p = host.indexOf(':', p + 1)) >= 0) {
41 try {
42 port = Integer.parseInt(host.substring(p + 1));
43 } catch(NumberFormatException e) {}
44 }
45 host = newhost;
46 } else if((p = host.indexOf(':')) >= 0) {
47 try {
48 port = Integer.parseInt(host.substring(p + 1));
49 host = host.substring(0, p);
50 } catch(NumberFormatException e) {}
51 }
52 }
78f5d120
FT
53 String pi = req.getPathInfo();
54 if(pi == null)
55 pi = "";
56 String q = req.getQueryString();
57 if(q != null)
58 q = "?" + q;
59 else
60 q = "";
61 try {
433ee775 62 url = new URL(scheme, host, port, req.getContextPath() + req.getServletPath() + pi + q);
4b8346e1 63 context = new URL(scheme, host, port, req.getContextPath());
78f5d120
FT
64 } catch(MalformedURLException e) {
65 throw(new Error(e));
66 }
67 }
68 method = req.getMethod().toUpperCase().intern();
69 path = req.getPathInfo();
70 while((path.length() > 0) && (path.charAt(0) == '/'))
71 path = path.substring(1);
72 }
73
1c868f4e 74 public Map<Object, Object> props() {
78f5d120
FT
75 return(props);
76 }
77
b606e86e
FT
78 public SocketAddress remoteaddr() {
79 try {
9f01683a
FT
80 /* Apparently getRemotePort returns -1 when running on Tomcat over AJP. */
81 int port = req.getRemotePort();
82 if(port < 0)
83 port = 0;
84 return(new InetSocketAddress(InetAddress.getByName(req.getRemoteAddr()), port));
b606e86e
FT
85 } catch(UnknownHostException e) {
86 /* req.getRemoteAddr should always be a valid IP address,
87 * so this should never happen. */
88 throw(new Error(e));
89 }
90 }
91
92 public SocketAddress localaddr() {
93 try {
94 return(new InetSocketAddress(InetAddress.getByName(req.getLocalAddr()), req.getLocalPort()));
95 } catch(UnknownHostException e) {
96 /* req.getRemoteAddr should always be a valid IP address,
97 * so this should never happen. */
98 throw(new Error(e));
99 }
100 }
101
78f5d120
FT
102 public URL url() {
103 return(url);
104 }
105
4b8346e1
FT
106 public URL rooturl() {
107 return(context);
108 }
109
110 public ServerContext ctx() {
111 return(ThreadContext.current().server());
112 }
113
78f5d120
FT
114 public String method() {
115 return(method);
116 }
117
118 public String path() {
119 return(path);
120 }
121
122 public InputStream input() {
123 try {
124 return(req.getInputStream());
125 } catch(IOException e) {
126 /* It is not obvious why this would happen, so I'll wait
127 * until I know whatever might happen to try and implement
128 * meaningful behavior. */
129 throw(new RuntimeException(e));
130 }
131 }
132
133 public MultiMap<String, String> inheaders() {
134 MultiMap<String, String> h = new HeaderTreeMap();
135 Enumeration ki = req.getHeaderNames();
136 if(ki != null) {
137 while(ki.hasMoreElements()) {
138 String k = (String)ki.nextElement();
139 Enumeration vi = req.getHeaders(k);
140 if(vi != null) {
141 while(vi.hasMoreElements()) {
142 String v = (String)vi.nextElement();
143 h.add(k, v);
144 }
145 }
146 }
147 }
148 return(h);
149 }
150
151 public MultiMap<String, String> params() {
ca045757
FT
152 if(params == null) {
153 params = Params.urlparams(this);
154 if(method == "POST") {
155 MultiMap<String, String> pp = Params.postparams(this);
156 if(pp != null)
157 params.putAll(pp);
158 }
159 }
160 return(params);
78f5d120
FT
161 }
162
163 protected void backflush() {
c5364ae2 164 resp.setStatus(respcode);
78f5d120
FT
165 for(String key : outheaders().keySet()) {
166 boolean first = true;
167 for(String val : outheaders().values(key)) {
168 if(first) {
169 resp.setHeader(key, val);
170 first = false;
171 } else {
172 resp.addHeader(key, val);
173 }
174 }
175 }
176 }
177
178 protected OutputStream realoutput() {
179 try {
180 return(resp.getOutputStream());
181 } catch(IOException e) {
182 /* It is not obvious why this would happen, so I'll wait
183 * until I know whatever might happen to try and implement
184 * meaningful behavior. */
185 throw(new RuntimeException(e));
186 }
187 }
188}