View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.portals.bridges.php;
18  
19  import java.io.IOException;
20  import java.security.Principal;
21  import java.util.Enumeration;
22  
23  import javax.portlet.ActionRequest;
24  import javax.portlet.ActionResponse;
25  import javax.portlet.GenericPortlet;
26  import javax.portlet.PortletConfig;
27  import javax.portlet.PortletContext;
28  import javax.portlet.PortletException;
29  import javax.portlet.PortletSession;
30  import javax.portlet.PortletURL;
31  import javax.portlet.RenderRequest;
32  import javax.portlet.RenderResponse;
33  import javax.servlet.ServletException;
34  import javax.servlet.http.HttpServletRequest;
35  import javax.servlet.http.HttpServletResponse;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.portals.bridges.common.ScriptPostProcess;
39  import org.apache.portals.bridges.common.ServletContextProvider;
40  import org.apache.portals.bridges.php.PHPParameters;
41  
42  /***
43   * This portlet is executes a PHP application in a portlet.
44   *
45   * @author <a href="mailto:rogerrut@apache.org">Roger Ruttimann</a>
46   * @version $Id: PHPApplicationPortlet.java 545680 2007-06-09 01:48:26Z ate $
47   */
48  
49  public class PHPApplicationPortlet extends GenericPortlet {
50  
51  	/***
52  	 * INIT parameters required by the PHP Portlet:application and ServletContextProvider
53  	 *
54       * Name of class implementing {@link PHPServletContextProvider}
55       */
56      public static final String PARAM_SERVLET_CONTEXT_PROVIDER = "ServletContextProvider";
57      
58      	
59  	/***
60  	 * Start page for this portlet it must be the path to the script (e.g hosts/index.php)
61  	 */
62  	public static final String START_PAGE	=	"StartPage";
63  
64  		   
65      // Local variables
66      
67  	private ServletContextProvider servletContextProvider;
68      private static final Log log = LogFactory.getLog(PHPApplicationPortlet.class);
69      
70      // Servlet INFO needed for portlet    
71      
72      ServletConfigImpl servletConfig = null;
73      
74      // PHP engine 
75      com.itgroundwork.portlet.php.servlet phpServletImpl = null;
76      
77       // INIT Parameters
78      private String startPage = null;
79      
80      // caching status    
81      private boolean bUseCachedParameters = false;
82      private String lastContextPath = null;
83      private String lastQuery = null;
84      private String lastURI = null;
85      
86      //ID to identify portlet
87      private String portletID = null;
88   
89      public void init(PortletConfig config) throws PortletException
90      {    
91          super.init(config);
92          
93          //Get the INIT PARAMETERS for this portlet. If the values are missing
94          // throw an exception
95          startPage											=	config.getInitParameter(START_PAGE);
96          String contextProviderClassName	=	config.getInitParameter(PARAM_SERVLET_CONTEXT_PROVIDER);
97          
98          if (startPage == null)
99              throw new PortletException("Portlet " + config.getPortletName()
100                     + " is incorrectly configured. Init parameter "
101                     + START_PAGE + " not specified");
102           
103         if (contextProviderClassName == null)
104             throw new PortletException("Portlet " + config.getPortletName()
105                     + " is incorrectly configured. Init parameter "
106                     + PARAM_SERVLET_CONTEXT_PROVIDER + " not specified");
107         
108        
109         if (contextProviderClassName != null)
110         {
111             try
112             {
113                 Class clazz = Class.forName(contextProviderClassName);
114                 if (clazz != null)
115                 {
116                     Object obj = clazz.newInstance();
117                     if (ServletContextProvider.class.isInstance(obj))
118                         servletContextProvider = (ServletContextProvider) obj;
119                     else
120                         throw new PortletException("class not found");
121                 }
122             } catch (Exception e)
123             {
124                 if (e instanceof PortletException)
125                     throw (PortletException) e;
126                 e.printStackTrace();
127                 throw new PortletException("Cannot load", e);
128             }
129         }
130         // Initialize config
131         servletConfig = new ServletConfigImpl(config, servletContextProvider.getServletContext(this));
132      }	
133     
134     /***
135      * processAction()
136      * Checks action initiated by the php portlet (invoking other php scripts)
137      * @param actionRequest
138      * @param actionResponse
139      * @throws PortletException
140      * @throws IOException
141      */
142     public void processAction(ActionRequest actionRequest, ActionResponse actionResponse) throws PortletException, IOException
143 	{
144     	String phpParameter = actionRequest.getParameter(PHPParameters.ACTION_PARAMETER_PHP);
145      	/*
146     	 * If the phpParameter is not empty create a PHPParameters object and attach it to the session
147     	 */
148     	if ( phpParameter != null && phpParameter.length() > 0)
149     	{
150     		// Perl Parameter Object
151     		PHPParameters phpScript = new PHPParameters();
152     		
153     		// Separate the values before and after the Query Mark ?
154     		int ixQuery = phpParameter.indexOf('?');
155     		if ( ixQuery != -1)
156     		{
157     			phpScript.setScriptName(phpParameter.substring(0,ixQuery));
158     			
159     			String queryArguments = phpParameter.substring(ixQuery+1);
160     			System.out.println("ProcessRequest -- Script " + phpParameter.substring(0,ixQuery) + " Query string " + queryArguments);
161     			
162     			int ixQuerySeparator = queryArguments.indexOf('&');
163     			while ( ixQuerySeparator != -1)
164     			{
165     				phpScript.addQueryArgument(queryArguments.substring(0, ixQuerySeparator));
166     				queryArguments = queryArguments.substring(ixQuerySeparator+1);
167     				ixQuerySeparator = queryArguments.indexOf('&');
168     			}
169     			
170     			phpScript.addQueryArgument(queryArguments);
171     			
172     			// Add the PerlParameters to the session
173     			actionRequest.getPortletSession().setAttribute(PHPParameters.PHP_PARAMETER, phpScript, PortletSession.APPLICATION_SCOPE);
174     		}
175     		else
176     		{
177     			// No query string just the script name
178     			phpScript.setScriptName(phpParameter);
179     			
180     			// Get all the parameters from the request and add them as query arguments
181     			Enumeration names = actionRequest.getParameterNames();
182     			String name, value;
183     			while (names.hasMoreElements())
184     			{
185     				name = (String)names.nextElement();
186     				// ACTION_PARAMETER_PHP already processed just ignore it
187     				if (name.compareToIgnoreCase(PHPParameters.ACTION_PARAMETER_PHP) != 0)
188     				{
189     					value = actionRequest.getParameter(name);
190     					
191        					phpScript.addQueryArgument(name + "=" + value);
192     				}
193     			}
194     			// Add the PerlParameters to the session
195     			actionRequest.getPortletSession().setAttribute(PHPParameters.PHP_PARAMETER, phpScript, PortletSession.APPLICATION_SCOPE);
196      		}
197     	}
198 	}
199     
200     /***
201      * doView
202      * Renders a PHP file in the portlet. 
203      * The script parameters are in a PHPParameters object that is passed in the session
204      */
205     
206     public void doView(RenderRequest request, RenderResponse response)
207     throws PortletException, IOException
208 	{
209     	/*
210     	 *  Extract the PHPParameter object from the session. If this is not provided use the values for startPage and application from the INIT Parameters
211     	 */
212     	String	reqQuery;
213     	String	phpScript;
214     	
215     	PHPParameters phpParam = null;
216     	try
217 		{
218     		phpParam = (PHPParameters)request.getPortletSession().getAttribute(PHPParameters.PHP_PARAMETER, PortletSession.APPLICATION_SCOPE);
219 		}
220     	catch (Exception e )
221 		{
222     		phpParam = null;
223 		}
224     	
225     	if (phpParam != null)
226     	{
227     		// We got real parameters
228     		bUseCachedParameters = false;
229     		reqQuery = phpParam.getQueryString();
230     		phpScript = phpParam.getScriptName();
231     	}
232     	else
233     	{
234     		/*
235     		 * No parameters were send to this page. Either it is the initial invocation (use init param) or 
236     		 * iit was a refresh (use cached arguments)
237     		 * 
238     		 * Setting the bUseCacheParameters means that nothing was provided from outside
239     		 */
240     		bUseCachedParameters = true;
241     		reqQuery = "";
242     		phpScript = this.startPage;
243     	}
244     	
245       	//ServletContext		servletContext	= servletContextProvider.getServletContext(this);
246     	HttpServletRequest	httpRequest		= servletContextProvider.getHttpServletRequest(this, request);
247     	HttpServletResponse httpResponse	= servletContextProvider.getHttpServletResponse(this, response);
248     	
249     	//initialize PHP engine
250     	if ( phpServletImpl == null)
251     	{
252     		try
253 			{
254     		phpServletImpl = new com.itgroundwork.portlet.php.servlet();
255     		if (phpServletImpl != null )
256     			phpServletImpl.init(servletConfig);
257 			}
258     		catch(ServletException se)
259 			{
260     			httpResponse.getWriter().println("<p><b>Initializationof PHP servlet failed!</b> Error: " + se.getMessage() + "</p>");
261 			}
262     	}
263     	
264       	
265     	// Make sure we have an user
266       	String userName = "anon";	//default not logged in
267     	Principal userPrincipal = request.getUserPrincipal();
268     	if (userPrincipal != null )
269     		userName = userPrincipal.getName();
270         
271         boolean bShowInfoPage = false;
272         String	cookieValue = null;
273         
274          // Build the context path
275         String contextPath =		request.getContextPath();
276         PortletContext portletApplication = getPortletContext(); 
277         String path = portletApplication.getRealPath("/WEB-INF");
278         String rootContextPath = path + "/";
279         
280         /*
281          * At this point we have all the information to run the PHP servlet:
282          * 		rootContextPath	contains the file path to the PortletApplication root (e.g /home/user/tomcat/webapps/MyApplication/ )
283          * 		phpScript				php script to execute. Includes the full path to the application (e.g hosts/index.php)
284          * 		reqQuery				Query arguments passed to the scripts
285          */
286         
287         // Run parameters
288         String runURI, runQuery, runContext;
289         
290         // First time call or invoked from another portlet
291         if ( bUseCachedParameters == true)
292         {
293         	//If it is the first call create an URI
294         	if ( lastURI == null || lastURI.length() == 0)
295         	{
296         		// Build the URI with the start page and the context
297         		lastURI = contextPath + "/" + phpScript;
298         		lastContextPath = rootContextPath + phpScript;
299         	}
300         	
301         	// Assign run values
302         	runURI = lastURI;
303         	runQuery = lastQuery;
304         	runContext = lastContextPath;
305         }
306         else
307         {      
308 			// New request for this portlet render it for the new content
309 			String adjURI = contextPath + "/" + phpScript;
310 			
311 			String phpContext = rootContextPath + phpScript;			
312 			
313 			// Assign run values
314         	runURI = adjURI;
315         	runQuery = reqQuery;
316         	runContext = phpContext;
317         }
318 
319 		// Invoke the PHP servlet and run it
320 		try
321 		{		
322 			if (phpServletImpl != null )
323 			{	
324 				    if (runQuery == null )
325 				    	runQuery = "";
326 				    
327 				    //  Call into the php library. 		
328 				    // Cache the page in the servlet and don't write the output to the response since some post processing
329 				    // is needed before the page can be send back to the client
330 				    phpServletImpl.setUseInternalPage();
331 				    
332 				    // Set the servlet parameters
333 					phpServletImpl.setAdjustedURI(runURI);
334 					phpServletImpl.setAuthenticatedUser(userName);
335 					phpServletImpl.setAdjustedQuery(runQuery);
336 					
337 					// execute the PHP script
338 					phpServletImpl.service(httpRequest, httpResponse, runContext);
339 					
340 					//Save last executed request info so that we remember when it was last called
341 					lastQuery = runQuery;
342 					lastContextPath = runContext;
343 					lastURI = runURI;
344 					
345 					//PostProcess:
346 					//	replace all relative links with actions
347 					
348 					//Any HREFs and Form actions should be extended with the ActionURL
349 					PortletURL actionURL = response.createActionURL();
350 					
351 					// Get the buffered page from the PHP servlet
352 					StringBuffer page = phpServletImpl.getSourcePage();
353 					
354 					// Call into the PostProcess object which is the same for PERL and other script engine
355 					// supported in the future.
356 					ScriptPostProcess processor = new ScriptPostProcess();
357 					processor.setInitalPage(page);
358 					processor.postProcessPage(actionURL, PHPParameters.ACTION_PARAMETER_PHP);
359 					String finalPage = processor.getFinalizedPage();
360 					
361 			        //Write the page to the HttpResponse
362 					httpResponse.getWriter().println(finalPage);				
363 			}
364 			else
365 			{
366 				httpResponse.getWriter().println("<br/><b>Error in PHP servlet. Couldn't create instance of com.itgroundwork.portlet.php.servlet. Make sure the jar is included in the same app as the portas-bridges-php jar file</b>" );
367 			}
368 		}
369 		catch( ServletException se)
370 		{
371 			httpResponse.getWriter().println("<P><B>Error in PHP servlet.Servlet Exception: " + se.getMessage() + "</B>RunQuery=" + runQuery+ " RunContext=" + runContext + " RunURI=" + runURI + " </P><BR>");
372 			throw new PortletException(se);
373 		}
374 		catch (IOException e)
375 		{
376 			httpResponse.getWriter().println("<P><B>Error in PHP servlet. IO Exception " + e.getMessage() + "</B>RunQuery=" + runQuery+ " RunContext=" + runContext + "Run URI=" + runURI + "</P><BR>");
377 		}
378 	}
379 }