blob: c65c39cc8cfaef2ec62a990b925805ef8749b22b [file] [log] [blame]
Richard S. Hallfe8e5602006-04-19 15:23:22 +00001/*
2 * Copyright 2006 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 */
17package org.apache.felix.http.jetty;
18
19import java.io.IOException;
20import java.io.InputStream;
21import java.io.OutputStream;
22import java.net.URL;
23import java.security.*;
24
25import org.mortbay.http.HttpException;
26import org.mortbay.http.HttpRequest;
27import org.mortbay.http.HttpResponse;
28import org.mortbay.http.handler.AbstractHttpHandler;
29import org.mortbay.jetty.servlet.*;
30
31/**
32 *
33 */
34public class OsgiResourceHandler extends AbstractHttpHandler
35{
36 protected org.osgi.service.http.HttpContext m_osgiHttpContext;
37 protected String m_name;
38 protected OsgiServletHandler m_dummyHandler;
39 protected AccessControlContext m_acc;
40
41
42 public OsgiResourceHandler(
43 org.osgi.service.http.HttpContext osgiHttpContext, String name,
44 AccessControlContext acc)
45 {
46 m_osgiHttpContext = osgiHttpContext;
47 m_name = name;
48 // needed for OSGi security handling
49 m_dummyHandler = new OsgiServletHandler(osgiHttpContext);
50 m_acc = acc;
51 }
52
53
54 public void initialize(org.mortbay.http.HttpContext context)
55 {
56 super.initialize(context);
57 m_dummyHandler.initialize(context);
58 }
59
60
61 public void handle(String pathInContext,
62 String pathParams,
63 HttpRequest request,
64 HttpResponse response)
65 throws HttpException, IOException
66 {
67 Activator.debug("handle for name:" + m_name
68 + "(path=" + pathInContext + ")");
69
70 ServletHttpRequest servletRequest = new DummyServletHttpRequest(
71 m_dummyHandler, pathInContext, request);
72 ServletHttpResponse servletResponse = new DummyServletHttpResponse(
73 servletRequest, response);
74
75 if (!m_osgiHttpContext.handleSecurity(servletRequest, servletResponse))
76 {
77 // spec doesn't state specific processing here apart from
78 // "send the response back to the client". We take this to mean
79 // any response generated in the context, and so all we do here
80 // is set handled to "true" to ensure any output is sent back
81 request.setHandled(true);
82 return;
83 }
84
85 // Create resource based name and see if we can resolve it
86 String resName = m_name + pathInContext;
87 Activator.debug("** looking for: " + resName);
88 URL url = m_osgiHttpContext.getResource(resName);
89
90 if (url == null)
91 {
92 return;
93 }
94
95 Activator.debug("serving up:" + resName);
96
97 // It doesn't state so in the OSGi spec, but can't see how anything
98 // other than GET and variants would be supported
99 String method=request.getMethod();
100 if (method.equals(HttpRequest.__GET) ||
101 method.equals(HttpRequest.__POST) ||
102 method.equals(HttpRequest.__HEAD))
103 {
104 handleGet(request, response, url, resName);
105 }
106 else
107 {
108 try
109 {
110 response.sendError(HttpResponse.__501_Not_Implemented);
111 }
112 catch(Exception e) {/*TODO: include error logging*/}
113 }
114 }
115
116
117 public void handleGet(HttpRequest request, final HttpResponse response,
118 final URL url, String resName)
119 throws IOException
120 {
121 String encoding = m_osgiHttpContext.getMimeType(resName);
122
123 if (encoding == null)
124 {
125 encoding = getHttpContext().getMimeByExtension(resName);
126 }
127
128 if (encoding == null)
129 {
130 encoding = getHttpContext().getMimeByExtension(".default");
131 }
132
133 //TODO: not sure why this is needed, but sometimes get "IllegalState"
134 // errors if not included
135 response.setAcceptTrailer(true);
136 response.setContentType(encoding);
137
138 //TODO: check other http fields e.g. ranges, timestamps etc.
139
140 // make sure we access the resource inside the bundle's access control
141 // context if supplied
142 if (System.getSecurityManager() != null)
143 {
144 try
145 {
146 AccessController.doPrivileged(new PrivilegedExceptionAction()
147 {
148 public Object run()
149 throws Exception
150 {
151 copyResourceBytes(url, response);
152 return null;
153 }
154 }, m_acc);
155 }
156 catch (PrivilegedActionException ex)
157 {
158 IOException ioe = (IOException) ex.getException();
159 throw ioe;
160 }
161 }
162 else
163 {
164 copyResourceBytes(url, response);
165 }
166
167 request.setHandled(true);
168 //TODO: set other http fields e.g. __LastModified, __ContentLength
169 }
170
171
172 private void copyResourceBytes(URL url, HttpResponse response)
173 throws
174 IOException
175 {
176 OutputStream os = response.getOutputStream();
177 InputStream is = url.openStream();
178 int len = 0;
179 byte[] buf = new byte[1024];
180 int n = 0;
181
182 while ((n = is.read(buf, 0, buf.length)) >= 0)
183 {
184 os.write(buf, 0, n);
185 len += n;
186 }
187
188 try
189 {
190 response.setContentLength(len);
191 }
192 catch (IllegalStateException ex)
193 {
194 System.err.println("OsgiResourceHandler: " + ex);
195 }
196 }
197}