001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.osgi;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.JavaConstants;
020    import com.liferay.portal.kernel.util.StringPool;
021    import com.liferay.portal.kernel.util.Validator;
022    import com.liferay.portal.osgi.service.OSGiServiceUtil;
023    import com.liferay.portal.util.PortalUtil;
024    
025    import java.io.IOException;
026    
027    import java.util.Hashtable;
028    
029    import javax.servlet.ServletConfig;
030    import javax.servlet.ServletException;
031    import javax.servlet.http.HttpServlet;
032    import javax.servlet.http.HttpServletRequest;
033    import javax.servlet.http.HttpServletRequestWrapper;
034    import javax.servlet.http.HttpServletResponse;
035    
036    import org.osgi.framework.BundleContext;
037    import org.osgi.framework.ServiceReference;
038    import org.osgi.framework.launch.Framework;
039    
040    /**
041     * @author Raymond Augé
042     */
043    public class OSGiServlet extends HttpServlet {
044    
045            @Override
046            public void init(ServletConfig servletConfig) throws ServletException {
047                    super.init(servletConfig);
048    
049                    BundleContext bundleContext = getBundleContext();
050    
051                    if (bundleContext == null) {
052                            if (_log.isWarnEnabled()) {
053                                    _log.warn("No framework available");
054                            }
055    
056                            return;
057                    }
058    
059                    registerServletConfig(servletConfig);
060    
061                    _serviceReference = bundleContext.getServiceReference(
062                            _HTTP_SERVICE_SERVLET_WRAPPER);
063    
064                    if (_serviceReference == null) {
065                            _log.warn("No HTTP service available");
066    
067                            return;
068                    }
069    
070                    HttpServlet httpServlet = (HttpServlet)bundleContext.getService(
071                            _serviceReference);
072    
073                    httpServlet.init(servletConfig);
074            }
075    
076            @Override
077            public void service(
078                            HttpServletRequest request, HttpServletResponse response)
079                    throws IOException, ServletException {
080    
081                    BundleContext bundleContext = getBundleContext();
082    
083                    if (bundleContext == null) {
084                            PortalUtil.sendError(
085                                    HttpServletResponse.SC_SERVICE_UNAVAILABLE,
086                                    new IllegalStateException("No framework available"),
087                                    request, response);
088    
089                            return;
090                    }
091    
092                    String pathInfo = request.getPathInfo();
093    
094                    if (Validator.isNull(pathInfo) || pathInfo.equals(StringPool.SLASH)) {
095                            PortalUtil.sendError(
096                                    HttpServletResponse.SC_NOT_FOUND,
097                                    new IllegalArgumentException("No path was available"), request,
098                                    response);
099    
100                            return;
101                    }
102    
103                    if (isExtensionMapping(pathInfo)) {
104                            request = new ExtensionMappingRequest(request);
105                    }
106    
107                    if (request.getAttribute(
108                                    JavaConstants.JAVAX_SERVLET_INCLUDE_REQUEST_URI) != null) {
109    
110                            String includePathInfo = (String)request.getAttribute(
111                                    JavaConstants.JAVAX_SERVLET_INCLUDE_PATH_INFO);
112    
113                            if (Validator.isNull(includePathInfo)) {
114                                    String includeServletPath = (String)request.getAttribute(
115                                            JavaConstants.JAVAX_SERVLET_INCLUDE_SERVLET_PATH);
116    
117                                    String servletPath = request.getServletPath();
118    
119                                    if (includeServletPath.contains(servletPath)) {
120                                            includeServletPath = includeServletPath.substring(
121                                                    servletPath.length());
122                                    }
123    
124                                    if (isExtensionMapping(includeServletPath)) {
125                                            request = new IncludedExtensionMappingRequest(
126                                                    request, servletPath);
127                                    }
128                            }
129                    }
130    
131                    _serviceReference = bundleContext.getServiceReference(
132                            _HTTP_SERVICE_SERVLET_WRAPPER);
133    
134                    if (_serviceReference == null) {
135                            PortalUtil.sendError(
136                                    HttpServletResponse.SC_SERVICE_UNAVAILABLE,
137                                    new IllegalStateException("No HTTP service available"),
138                                    request, response);
139    
140                            return;
141                    }
142    
143                    HttpServlet httpServlet = (HttpServlet)bundleContext.getService(
144                            _serviceReference);
145    
146                    httpServlet.init(getServletConfig());
147    
148                    httpServlet.service(request, response);
149            }
150    
151            protected BundleContext getBundleContext() {
152                    if (_bundleContext != null) {
153                            return _bundleContext;
154                    }
155    
156                    Framework framework = OSGiServiceUtil.getFramework();
157    
158                    if (framework != null) {
159                            _bundleContext = framework.getBundleContext();
160                    }
161    
162                    return _bundleContext;
163            }
164    
165            protected boolean isExtensionMapping(String servletPath) {
166                    int pos = servletPath.lastIndexOf(StringPool.SLASH);
167    
168                    if (pos != -1) {
169                            servletPath = servletPath.substring(pos + 1);
170                    }
171    
172                    return servletPath.indexOf(StringPool.PERIOD) != -1;
173            }
174    
175            protected void registerServletConfig(ServletConfig servletConfig) {
176                    Hashtable<String, Object> properties = new Hashtable<String, Object>();
177    
178                    properties.put(OSGiConstants.BEAN_ID, ServletConfig.class.getName());
179                    properties.put(OSGiConstants.ORIGINAL_BEAN, Boolean.TRUE);
180    
181                    _bundleContext.registerService(
182                            new String[] {ServletConfig.class.getName()}, servletConfig,
183                            properties);
184            }
185    
186            private static final String _HTTP_SERVICE_SERVLET_WRAPPER =
187                    "com.liferay.osgi.http.HttpServiceServletWrapper";
188    
189            private static Log _log = LogFactoryUtil.getLog(OSGiServlet.class);
190    
191            private BundleContext _bundleContext;
192            private ServiceReference<?> _serviceReference;
193    
194            private class ExtensionMappingRequest extends HttpServletRequestWrapper {
195    
196                    public ExtensionMappingRequest(HttpServletRequest request) {
197                            super(request);
198                    }
199    
200                    @Override
201                    public String getServletPath() {
202                            return StringPool.BLANK;
203                    }
204    
205            }
206    
207            private class IncludedExtensionMappingRequest
208                    extends ExtensionMappingRequest {
209    
210                    private String _servletPath;
211    
212                    public IncludedExtensionMappingRequest(
213                            HttpServletRequest request, String servletPath) {
214    
215                            super(request);
216    
217                            _servletPath = servletPath;
218                    }
219    
220                    @Override
221                    public Object getAttribute(String attributeName) {
222                            if (attributeName.equals(
223                                            JavaConstants.JAVAX_SERVLET_INCLUDE_SERVLET_PATH)) {
224    
225                                    return StringPool.BLANK;
226                            }
227                            else if (attributeName.equals(
228                                                    JavaConstants.JAVAX_SERVLET_INCLUDE_PATH_INFO)) {
229    
230                                    String includeServletPath = (String)super.getAttribute(
231                                            JavaConstants.JAVAX_SERVLET_INCLUDE_SERVLET_PATH);
232    
233                                    if (includeServletPath.contains(_servletPath)) {
234                                            includeServletPath = includeServletPath.substring(
235                                                    _servletPath.length());
236                                    }
237    
238                                    return includeServletPath;
239                            }
240    
241                            return super.getAttribute(attributeName);
242                    }
243    
244            }
245    
246    }