001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.util.bridges.php;
016    
017    import com.caucho.vfs.Path;
018    import com.caucho.vfs.SchemeMap;
019    import com.caucho.vfs.Vfs;
020    
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.servlet.BufferCacheServletResponse;
024    import com.liferay.portal.kernel.servlet.DynamicServletConfig;
025    import com.liferay.portal.kernel.servlet.PortletServletObjectsFactory;
026    import com.liferay.portal.kernel.servlet.ServletContextUtil;
027    import com.liferay.portal.kernel.servlet.ServletObjectsFactory;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.InstanceFactory;
030    import com.liferay.portal.kernel.util.StringBundler;
031    import com.liferay.util.bridges.common.ScriptPostProcess;
032    
033    import java.io.IOException;
034    import java.io.PrintWriter;
035    
036    import java.net.URI;
037    
038    import java.util.Enumeration;
039    import java.util.HashMap;
040    import java.util.Map;
041    
042    import javax.portlet.ActionRequest;
043    import javax.portlet.ActionResponse;
044    import javax.portlet.GenericPortlet;
045    import javax.portlet.PortletConfig;
046    import javax.portlet.PortletException;
047    import javax.portlet.PortletURL;
048    import javax.portlet.RenderRequest;
049    import javax.portlet.RenderResponse;
050    
051    import javax.servlet.ServletConfig;
052    import javax.servlet.http.HttpServlet;
053    import javax.servlet.http.HttpServletRequest;
054    import javax.servlet.http.HttpServletResponse;
055    
056    /**
057     * @author Jorge Ferrer
058     */
059    public class PHPPortlet extends GenericPortlet {
060    
061            @Override
062            public void destroy() {
063                    if (quercusServlet != null) {
064                            quercusServlet.destroy();
065                    }
066            }
067    
068            @Override
069            public void doDispatch(
070                            RenderRequest renderRequest, RenderResponse renderResponse)
071                    throws IOException, PortletException {
072    
073                    String phpUri = renderRequest.getParameter(_PHP_URI_PARAM);
074    
075                    if (phpUri != null) {
076                            processPHP(phpUri, renderRequest, renderResponse);
077                    }
078                    else {
079                            super.doDispatch(renderRequest, renderResponse);
080                    }
081            }
082    
083            @Override
084            public void doEdit(
085                            RenderRequest renderRequest, RenderResponse renderResponse)
086                    throws IOException, PortletException {
087    
088                    if (renderRequest.getPreferences() == null) {
089                            super.doEdit(renderRequest, renderResponse);
090                    }
091                    else {
092                            processPHP(editUri, renderRequest, renderResponse);
093                    }
094            }
095    
096            @Override
097            public void doHelp(
098                    RenderRequest renderRequest, RenderResponse renderResponse) {
099    
100                    processPHP(helpUri, renderRequest, renderResponse);
101            }
102    
103            @Override
104            public void doView(
105                    RenderRequest renderRequest, RenderResponse renderResponse) {
106    
107                    processPHP(viewUri, renderRequest, renderResponse);
108            }
109    
110            @Override
111            public void init(PortletConfig portletConfig) throws PortletException {
112                    super.init(portletConfig);
113    
114                    editUri = getInitParameter("edit-uri");
115                    helpUri = getInitParameter("help-uri");
116                    viewUri = getInitParameter("view-uri");
117    
118                    addPortletParams = GetterUtil.getBoolean(
119                            portletConfig.getInitParameter("add-portlet-params"), true);
120    
121                    String servletObjectsFactoryName = GetterUtil.getString(
122                            getInitParameter("servlet-objects-factory"),
123                            PortletServletObjectsFactory.class.getName());
124    
125                    try {
126                            Class<?> servletObjectsFactoryClass = Class.forName(
127                                    servletObjectsFactoryName);
128    
129                            servletObjectsFactory =
130                                    (ServletObjectsFactory)servletObjectsFactoryClass.newInstance();
131                    }
132                    catch (Exception e) {
133                            throw new PortletException(
134                                    "Unable to instantiate factory" + servletObjectsFactoryName, e);
135                    }
136            }
137    
138            @Override
139            public void processAction(
140                    ActionRequest actionRequest, ActionResponse actionResponse) {
141    
142                    String phpURI = actionRequest.getParameter(_PHP_URI_PARAM);
143    
144                    if (phpURI != null) {
145                            actionResponse.setRenderParameter(_PHP_URI_PARAM, phpURI);
146                    }
147            }
148    
149            protected synchronized void initQuercus(ServletConfig servletConfig)
150                    throws PortletException {
151    
152                    if (quercusServlet != null) {
153                            return;
154                    }
155    
156                    try {
157                            SchemeMap schemeMap = Vfs.getDefaultScheme();
158    
159                            URI rootURI = ServletContextUtil.getRootURI(
160                                    servletConfig.getServletContext());
161    
162                            schemeMap.put(
163                                    rootURI.getScheme(),
164                                    new ServletContextPath(servletConfig.getServletContext()));
165    
166                            Path.setDefaultSchemeMap(schemeMap);
167    
168                            quercusServlet = (HttpServlet)InstanceFactory.newInstance(
169                                    _QUERCUS_SERVLET);
170    
171                            Map<String, String> params = new HashMap<String, String>();
172    
173                            Enumeration<String> enu = servletConfig.getInitParameterNames();
174    
175                            while (enu.hasMoreElements()) {
176                                    String name = enu.nextElement();
177    
178                                    if (!name.equals("portlet-class")) {
179                                            params.put(name, servletConfig.getInitParameter(name));
180                                    }
181                            }
182    
183                            servletConfig = new DynamicServletConfig(servletConfig, params);
184    
185                            quercusServlet.init(servletConfig);
186                    }
187                    catch (Exception e) {
188                            throw new PortletException(e);
189                    }
190            }
191    
192            protected void processPHP(
193                    String phpURI, RenderRequest renderRequest,
194                    RenderResponse renderResponse) {
195    
196                    try {
197                            ServletConfig servletConfig =
198                                    servletObjectsFactory.getServletConfig(
199                                            getPortletConfig(), renderRequest);
200    
201                            initQuercus(servletConfig);
202    
203                            HttpServletRequest request =
204                                    servletObjectsFactory.getServletRequest(renderRequest);
205                            HttpServletResponse response =
206                                    servletObjectsFactory.getServletResponse(
207                                            renderRequest, renderResponse);
208    
209                            PHPServletRequest phpRequest = new PHPServletRequest(
210                                    request, servletConfig, renderRequest, renderResponse,
211                                    getPortletConfig(), phpURI, addPortletParams);
212    
213                            BufferCacheServletResponse bufferCacheServletResponse =
214                                    new BufferCacheServletResponse(response);
215    
216                            quercusServlet.service(phpRequest, bufferCacheServletResponse);
217    
218                            String result = bufferCacheServletResponse.getString();
219    
220                            String contentType = bufferCacheServletResponse.getContentType();
221    
222                            if (contentType.startsWith("text/")) {
223                                    result = rewriteURLs(result, renderResponse.createRenderURL());
224                            }
225    
226                            renderResponse.setContentType(contentType);
227    
228                            PrintWriter writer = renderResponse.getWriter();
229    
230                            writer.write(result.toCharArray());
231                    }
232                    catch (Exception e) {
233                            _log.error("Error processing PHP", e);
234                    }
235            }
236    
237            protected String rewriteURLs(String page, PortletURL portletURL) {
238                    ScriptPostProcess scriptPostProcess = new ScriptPostProcess();
239    
240                    scriptPostProcess.setInitalPage(new StringBundler(page));
241    
242                    scriptPostProcess.postProcessPage(portletURL, _PHP_URI_PARAM);
243    
244                    return scriptPostProcess.getFinalizedPage();
245            }
246    
247            protected boolean addPortletParams;
248            protected String editUri;
249            protected String helpUri;
250            protected HttpServlet quercusServlet;
251            protected ServletObjectsFactory servletObjectsFactory;
252            protected String viewUri;
253    
254            private static final String _PHP_URI_PARAM = "phpURI";
255    
256            private static final String _QUERCUS_SERVLET =
257                    "com.caucho.quercus.servlet.QuercusServlet";
258    
259            private static Log _log = LogFactoryUtil.getLog(PHPPortlet.class);
260    
261    }