001    /**
002     * Copyright (c) 2000-2013 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.quercus.servlet.QuercusServlet;
018    
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.servlet.DynamicServletConfig;
022    import com.liferay.portal.kernel.servlet.PortletServletObjectsFactory;
023    import com.liferay.portal.kernel.servlet.ServletObjectsFactory;
024    import com.liferay.portal.kernel.servlet.StringServletResponse;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.InstanceFactory;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.util.bridges.common.ScriptPostProcess;
030    
031    import java.io.IOException;
032    import java.io.PrintWriter;
033    
034    import java.util.Enumeration;
035    import java.util.HashMap;
036    import java.util.Map;
037    
038    import javax.portlet.ActionRequest;
039    import javax.portlet.ActionResponse;
040    import javax.portlet.GenericPortlet;
041    import javax.portlet.PortletConfig;
042    import javax.portlet.PortletException;
043    import javax.portlet.PortletURL;
044    import javax.portlet.RenderRequest;
045    import javax.portlet.RenderResponse;
046    
047    import javax.servlet.ServletConfig;
048    import javax.servlet.http.HttpServletRequest;
049    import javax.servlet.http.HttpServletResponse;
050    
051    /**
052     * @author Jorge Ferrer
053     */
054    public class PHPPortlet extends GenericPortlet {
055    
056            @Override
057            public void destroy() {
058                    if (quercusServlet != null) {
059                            quercusServlet.destroy();
060                    }
061            }
062    
063            @Override
064            public void doDispatch(
065                            RenderRequest renderRequest, RenderResponse renderResponse)
066                    throws IOException, PortletException {
067    
068                    String phpUri = renderRequest.getParameter(_PHP_URI_PARAM);
069    
070                    if (phpUri != null) {
071                            processPHP(phpUri, renderRequest, renderResponse);
072                    }
073                    else {
074                            super.doDispatch(renderRequest, renderResponse);
075                    }
076            }
077    
078            @Override
079            public void doEdit(
080                            RenderRequest renderRequest, RenderResponse renderResponse)
081                    throws IOException, PortletException {
082    
083                    if (renderRequest.getPreferences() == null) {
084                            super.doEdit(renderRequest, renderResponse);
085                    }
086                    else {
087                            processPHP(editUri, renderRequest, renderResponse);
088                    }
089            }
090    
091            @Override
092            public void doHelp(
093                    RenderRequest renderRequest, RenderResponse renderResponse) {
094    
095                    processPHP(helpUri, renderRequest, renderResponse);
096            }
097    
098            @Override
099            public void doView(
100                    RenderRequest renderRequest, RenderResponse renderResponse) {
101    
102                    processPHP(viewUri, renderRequest, renderResponse);
103            }
104    
105            @Override
106            public void init(PortletConfig portletConfig) throws PortletException {
107                    super.init(portletConfig);
108    
109                    editUri = getInitParameter("edit-uri");
110                    helpUri = getInitParameter("help-uri");
111                    viewUri = getInitParameter("view-uri");
112    
113                    addPortletParams = GetterUtil.getBoolean(
114                            portletConfig.getInitParameter("add-portlet-params"), true);
115    
116                    String servletObjectsFactoryName = GetterUtil.getString(
117                            getInitParameter("servlet-objects-factory"),
118                            PortletServletObjectsFactory.class.getName());
119    
120                    try {
121                            Class<?> servletObjectsFactoryClass = Class.forName(
122                                    servletObjectsFactoryName);
123    
124                            servletObjectsFactory =
125                                    (ServletObjectsFactory)servletObjectsFactoryClass.newInstance();
126                    }
127                    catch (Exception e) {
128                            throw new PortletException(
129                                    "Unable to instantiate factory" + servletObjectsFactoryName, e);
130                    }
131            }
132    
133            @Override
134            public void processAction(
135                    ActionRequest actionRequest, ActionResponse actionResponse) {
136    
137                    String phpURI = actionRequest.getParameter(_PHP_URI_PARAM);
138    
139                    if (phpURI != null) {
140                            actionResponse.setRenderParameter(_PHP_URI_PARAM, phpURI);
141                    }
142            }
143    
144            protected synchronized void initQuercus(ServletConfig servletConfig)
145                    throws PortletException {
146    
147                    if (quercusServlet != null) {
148                            return;
149                    }
150    
151                    try {
152                            quercusServlet = (QuercusServlet)InstanceFactory.newInstance(
153                                    _QUERCUS_SERVLET);
154    
155                            Map<String, String> params = new HashMap<String, String>();
156    
157                            Enumeration<String> enu = servletConfig.getInitParameterNames();
158    
159                            while (enu.hasMoreElements()) {
160                                    String name = enu.nextElement();
161    
162                                    if (!name.equals("portlet-class")) {
163                                            params.put(name, servletConfig.getInitParameter(name));
164                                    }
165                            }
166    
167                            servletConfig = new DynamicServletConfig(servletConfig, params);
168    
169                            QuercusServlet.PhpIni phpIni = quercusServlet.createPhpIni();
170    
171                            phpIni.setProperty("unicode.http_input_encoding", StringPool.UTF8);
172                            phpIni.setProperty("unicode.output_encoding", StringPool.UTF8);
173                            phpIni.setProperty("unicode.runtime_encoding", StringPool.UTF8);
174                            phpIni.setProperty("unicode.semantics", Boolean.TRUE.toString());
175    
176                            quercusServlet.init(servletConfig);
177                    }
178                    catch (Exception e) {
179                            throw new PortletException(e);
180                    }
181            }
182    
183            protected void processPHP(
184                    String phpURI, RenderRequest renderRequest,
185                    RenderResponse renderResponse) {
186    
187                    try {
188                            ServletConfig servletConfig =
189                                    servletObjectsFactory.getServletConfig(
190                                            getPortletConfig(), renderRequest);
191    
192                            initQuercus(servletConfig);
193    
194                            HttpServletRequest request =
195                                    servletObjectsFactory.getServletRequest(renderRequest);
196                            HttpServletResponse response =
197                                    servletObjectsFactory.getServletResponse(
198                                            renderRequest, renderResponse);
199    
200                            PHPServletRequest phpRequest = new PHPServletRequest(
201                                    request, servletConfig, renderRequest, renderResponse,
202                                    getPortletConfig(), phpURI, addPortletParams);
203    
204                            StringServletResponse stringResponse = new StringServletResponse(
205                                    response);
206    
207                            quercusServlet.service(phpRequest, stringResponse);
208    
209                            String result = stringResponse.getString();
210    
211                            if (stringResponse.getContentType().startsWith("text/")) {
212                                    result = rewriteURLs(result, renderResponse.createRenderURL());
213                            }
214    
215                            renderResponse.setContentType(stringResponse.getContentType());
216    
217                            PrintWriter writer = renderResponse.getWriter();
218    
219                            writer.write(result.toCharArray());
220                    }
221                    catch (Exception e) {
222                            _log.error("Error processing PHP", e);
223                    }
224            }
225    
226            protected String rewriteURLs(String page, PortletURL portletURL) {
227                    ScriptPostProcess scriptPostProcess = new ScriptPostProcess();
228    
229                    scriptPostProcess.setInitalPage(new StringBundler(page));
230    
231                    scriptPostProcess.postProcessPage(portletURL, _PHP_URI_PARAM);
232    
233                    return scriptPostProcess.getFinalizedPage();
234            }
235    
236            protected boolean addPortletParams;
237            protected String editUri;
238            protected String helpUri;
239            protected QuercusServlet quercusServlet;
240            protected ServletObjectsFactory servletObjectsFactory;
241            protected String viewUri;
242    
243            private static final String _PHP_URI_PARAM = "phpURI";
244    
245            private static final String _QUERCUS_SERVLET =
246                    "com.caucho.quercus.servlet.QuercusServlet";
247    
248            private static Log _log = LogFactoryUtil.getLog(PHPPortlet.class);
249    
250    }