package org.apache.jetspeed.util;
/*
* Copyright 2000-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//jetspeed support
import org.apache.jetspeed.portal.Portlet;
import org.apache.jetspeed.portal.PortletControl;
import org.apache.jetspeed.om.registry.PortletEntry;
import org.apache.jetspeed.services.Registry;
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
import org.apache.jetspeed.services.logging.JetspeedLogger;
import org.apache.jetspeed.services.resources.JetspeedResources;
import org.apache.jetspeed.services.rundata.JetspeedRunData;
//turbine
import org.apache.turbine.util.ParameterParser;
import org.apache.turbine.util.RunData;
import org.apache.turbine.util.template.TemplateLink;
/**
* <p>
* URI lookup related functions.
* </p>
*
* <p>
* Functions to get an URI based on a type like info, edit, save
* and to identify the type of an URI.
* </p>
*
* <p>
* To overwrite the default behaviour, specify one
* of the following parameters in the JR.p file. URILookup
* will then return the uri specified in the properties file.
* </p>
* <p>
* all possible property parameters:
* </p>
*
* <UL>
* <LI>URILookup.home.uri</LI>
* <LI>URILookup.home.acceptlogin.uri</LI>
* <LI>URILookup.home.restore.uri</LI>
* <LI>URILookup.home.logout.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.info.uri</LI>
* <LI>URILookup.info.mark.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.login.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.editaccount.uri</LI>
* <LI>URILookup.editaccount.mark.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.back.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.enrollment.uri</LI>
* </UL>
* <UL>
* <LI>URILookup.customizer.uri</LI>
* <LI>URILookup.customizer.save.uri</LI>
* </UL>
*
* @author <A HREF="shesmer@raleigh.ibm.com">Stephan Hesmer</A>
* @author <A HREF="sgala@apache.org">Santiago Gala</A>
* @version $Id: URILookup.java,v 1.24 2004/02/23 03:23:42 jford Exp $
*/
public class URILookup
{
/**
* Static initialization of the logger for this class
*/
private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(URILookup.class.getName());
/**
* <P>show Jetspeed Home page<BR>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* <LI>SUBTYPE_RESTORE</LI>
* <LI>SUBTYPE_MAXIMIZE</LI>
* <LI>SUBTYPE_LOGOUT</LI>
* <LI>SUBTYPE_ACCEPT_LOGIN</LI>
* </UL>
*/
public static final int TYPE_HOME = 0;
/**
* <P>show some additional information about the portlet</P>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* <LI>SUBTYPE_MARK</LI>
* </UL>
*/
public static final int TYPE_INFO = 1;
/**
* <P>show the edit page of the account</P>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* <LI>SUBTYPE_MARK</LI>
* </UL>
*/
public static final int TYPE_EDIT_ACCOUNT = 3;
/**
* <P>show portlet customization</P>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* <LI>SUBTYPE_SAVE</LI>
* </UL>
*/
public static final int TYPE_CUSTOMIZE = 4;
/**
* <P>show login screen</P>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* </UL>
*/
public static final int TYPE_LOGIN = 5;
/**
* <P>show the marked page<BR>
* only used in function getURI, not in getURIType</P>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* </UL>
*/
public static final int TYPE_BACK = 6;
/**
* <P>creates new account<BR>
* allowed Subtypes:<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* </UL>
*/
public static final int TYPE_ENROLLMENT = 7;
/**
* apply no subtype to the url
*/
public static final int SUBTYPE_NONE = 0;
/**
* restore portlet to default size
*/
public static final int SUBTYPE_RESTORE = 1;
/**
* show the current portlet maximized<BR>
* additionally, the current page is marked for restoring
*/
public static final int SUBTYPE_MAXIMIZE = 2;
/**
* mark the current page before processing portlet
*/
public static final int SUBTYPE_MARK = 3;
/**
* logs out the user
*/
public static final int SUBTYPE_LOGOUT = 4;
/**
* trues to login, after entering username and password
*/
public static final int SUBTYPE_ACCEPT_LOGIN = 5;
/**
* save user settings before processing portlet
*/
public static final int SUBTYPE_SAVE = 6;
/**
* Gets the URI for the specified type
*
* @param aType type of the URI
* @param aSubType subtype of the URI
* @param rundata the RunData object
* @return the URI
* @exception JetspeedException
*/
public static String getURI(int aType,
int aSubType,
RunData rundata)
throws JetspeedException
{
return getURI(aType,
aSubType,
null,
(String)null,
rundata);
}
/**
* Gets the URI of the specified portlet with the specified type
*
* @param aType type of the URI
* @param aSubType subtype of the URI
* @param aPortlet Portlet the URI points to
* @param rundata the RunData object
* @return the URI
*/
public static String getURI(int aType,
int aSubType,
Portlet aPortlet,
RunData rundata)
throws JetspeedException
{
return getURI(aType,
aSubType,
null,
aPortlet,
rundata);
}
/**
* Gets the URI of the specified portlet with the specified type
*
* @param aType type of the URI
* @param aSubType subtype of the URI
* @param aPortletName Portlet the URI points to
* @param rundata the RunData object
* @return the URI
*/
public static String getURI(int aType,
int aSubType,
String aPortletName,
RunData rundata)
throws JetspeedException
{
return getURI(aType,
aSubType,
null,
aPortletName,
rundata);
}
/**
* Gets the URI of the specified portlet with the specified type and adds
* given user data.
*
* @param aType type of the URI
* @param aSubType subtype of the URI
* @param userData string which should be added to the URL
* @param aPortlet Portlet the URI points to
* @param rundata the RunData object
* @return the URI
*/
public static String getURI(int aType,
int aSubType,
String userData,
Portlet aPortlet,
RunData rundata)
throws JetspeedException
{
if (aPortlet!=null) {
aPortlet = getRealPortlet(aPortlet);
return getURI(aType,
aSubType,
userData,
aPortlet.getName(),
rundata);
}
else {
return getURI(aType,
aSubType,
userData,
(String)null,
rundata);
}
}
/**
* Gets the URI of the specified portlet with the specified type and adds
* given user data.
*
* @param aType type of the URI
* @param aSubType subtype of the URI
* @param userData string which should be added to the URL
* @param aPortletName Portlet the URI points to
* @param rundata the RunData object
* @return the URI
*/
public static String getURI(int aType,
int aSubType,
String userData,
String aPortletName,
RunData rundata)
throws JetspeedException
{
String newURI = null;
String propertiesParameter = "URILookup.";
TemplateLink uri = new TemplateLink( rundata );
if (aType==TYPE_HOME)
{
propertiesParameter += "home.";
if (aSubType==SUBTYPE_RESTORE)
{
propertiesParameter += "restore.";
newURI = getMarkedPage( rundata );
}
else if (aSubType==SUBTYPE_MAXIMIZE)
{
propertiesParameter += "maximize.";
if (aPortletName==null)
{
throw new JetspeedException( "A portlet is required to return an URI." );
}
uri.setAction( ACTION_MARKPAGE );
uri.addPathInfo( "portlet", aPortletName );
}
else if (aSubType==SUBTYPE_LOGOUT)
{
propertiesParameter += "logout.";
uri.setAction( ACTION_LOGOUT );
}
else if (aSubType==SUBTYPE_ACCEPT_LOGIN)
{
propertiesParameter += "acceptlogin.";
uri.setAction( ACTION_ACCEPT_LOGIN );
}
else if (aSubType!=SUBTYPE_NONE)
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_INFO)
{
propertiesParameter += "info.";
if (aPortletName==null)
{
throw new JetspeedException( "A portlet is required to return an URI." );
}
uri.setPage( SCREEN_INFO );
uri.addPathInfo( "portlet", aPortletName );
if (aSubType==SUBTYPE_MARK)
{
propertiesParameter += "mark.";
uri.setAction( ACTION_MARKPAGE );
}
else if (aSubType!=SUBTYPE_NONE)
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_EDIT_ACCOUNT)
{
propertiesParameter += "editaccount.";
uri.setPage( SCREEN_EDIT_ACCOUNT );
if (aSubType==SUBTYPE_NONE)
{
uri.setAction( ACTION_PREPARE_SCREEN_EDIT_ACCOUNT );
}
else if (aSubType==SUBTYPE_MARK)
{
propertiesParameter += "mark.";
if (aPortletName==null)
{
throw new JetspeedException( "A portlet is required to return an URI." );
}
// FIX ME: how can we add a prepare action and a mark action at the same time?
// But I think this branch is never used anyway. (?)
uri.setAction( ACTION_MARKPAGE );
uri.addPathInfo( "portlet", aPortletName );
}
else
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_CUSTOMIZE)
{
propertiesParameter += "customize.";
uri.setPage( SCREEN_CUSTOMIZE );
if( aPortletName != null )
{
uri.addPathInfo( "portlet", aPortletName );
}
if (aSubType==SUBTYPE_NONE)
{
if (ACTION_CUSTOMIZER!=null) uri.setAction( ACTION_CUSTOMIZER );
}
else if (aSubType==SUBTYPE_SAVE)
{
propertiesParameter += "save.";
uri.setAction( ACTION_CUSTOMIZER_SAVE );
}
else
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_LOGIN)
{
propertiesParameter += "login.";
if (aSubType==SUBTYPE_NONE)
{
uri.setPage( SCREEN_LOGIN );
}
else
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_BACK)
{
propertiesParameter += "back.";
if (aSubType==SUBTYPE_NONE)
{
newURI = getMarkedPage( rundata );
}
else
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
}
else if (aType==TYPE_ENROLLMENT)
{
propertiesParameter += "enrollment.";
uri.setPage( SCREEN_NEWACCOUNT );
}
else
{
throw new JetspeedException( "Incorrect Type / Subtype combination." );
}
if (newURI==null)
{
newURI = uri.toString();
}
propertiesParameter += "uri";
String propertiesParameterValue = JetspeedResources.getString( propertiesParameter, null );
if (propertiesParameterValue!=null)
{
// found the parameter value, so replace the newURI with this one
if ( logger.isInfoEnabled() )
{
logger.info("URILookup: replaced uri "+newURI+" with "+propertiesParameterValue);
}
newURI = propertiesParameterValue;
}
if (userData!=null)
{
newURI = addURIParameter(newURI, userData);
}
// remove sessionid, if exists
if (newURI.indexOf(";jsessionid")!=-1)
{
newURI = newURI.substring(0,newURI.indexOf(";jsessionid"));
}
// adds sessionid if necessary
newURI = rundata.getResponse().encodeURL( newURI );
// remove starting slash, so that the URI is relative, and the Base-Tag is used
// Note: if there is no starting slash, the function encodeURL inserts one slash in front of the URI
if (newURI.startsWith("/"))
{
newURI = newURI.substring(1);
}
return newURI;
}
/**
* Gets the type of the URI (e.g. TYPE_INFO, TYPE_EDIT).
*
* @param rundata the RunData object
* @return the type
*/
public static int getURIType(RunData rundata)
{
return getURIType( null, rundata );
}
/**
* Gets the type of the URI (e.g. TYPE_INFO, TYPE_EDIT).
* The default return value is TYPE_HOME
* <P>Hint:<BR>
* Portlets should check for TYPE_EDIT_PORTLET and in any other case render the content</P>
*
* @param aPortlet the associated portlet
* @param rundata the RunData object
* @return the type
*/
public static int getURIType(Portlet aPortlet, RunData rundata)
{
if (aPortlet!=null)
{
aPortlet = getRealPortlet(aPortlet);
if (aPortlet.getName().equals(((JetspeedRunData)rundata).getPortlet()))
{
if (rundata.getScreen()!=null)
{
if (rundata.getScreen().equals(SCREEN_INFO)) return TYPE_INFO;
}
}
}
if (rundata.getScreen()!=null)
{
if (rundata.getScreen().equals(SCREEN_CUSTOMIZE)) return TYPE_CUSTOMIZE;
else if (rundata.getScreen().equals(SCREEN_NEWACCOUNT)) return TYPE_ENROLLMENT;
else if (rundata.getScreen().equals(SCREEN_EDIT_ACCOUNT)) return TYPE_EDIT_ACCOUNT;
else if (rundata.getScreen().equals(SCREEN_LOGIN)) return TYPE_LOGIN;
}
return TYPE_HOME;
}
/**
* <P>Gets the subtype of the URI (e.g. SUBTYPE_SAVE).</P>
* returns only the values<BR>
* <UL>
* <LI>SUBTYPE_NONE</LI>
* <LI>SUBTYPE_MAXIMIZE</LI>
* <LI>SUBTYPE_SAVE</LI>
* </UL>
*
* @param aPortlet the related portlet
* @param rundata the RunData object
* @return the type
* @exception JetspeedException
*/
public static int getURISubType(Portlet aPortlet, RunData rundata)
throws JetspeedException
{
if (rundata.getAction()!=null)
{
if (rundata.getAction().equals(ACTION_ACCEPT_LOGIN)) return SUBTYPE_ACCEPT_LOGIN;
else if (rundata.getAction().equals(ACTION_LOGOUT)) return SUBTYPE_LOGOUT;
}
String value = (String)rundata.getRequest().getParameter("type");
if (value!=null)
{
if (value.equalsIgnoreCase("save")) return SUBTYPE_SAVE;
}
if (aPortlet==null) throw new JetspeedException( "A portlet is required." );
aPortlet = getRealPortlet(aPortlet);
if (aPortlet.getName().equals(((JetspeedRunData)rundata).getPortlet()))
{
if ((rundata.getScreen()==null) || // no screen
( SCREEN_HOME.equals(rundata.getScreen())) ) // or Home-screen
{
return SUBTYPE_MAXIMIZE;
}
}
return SUBTYPE_NONE;
}
/**
* Gets the user specific data stored in the URI.
*
* @param rundata the RunData object
* @return the previous added user data
* @see #getURI
*/
public static String getURIUserData(RunData rundata)
{
return rundata.getParameters().getString("info");
}
/**
* returns the WebApplication base directory.
*
* @param rundata the rundata object
* @return the URI
*/
public static String getWebAppBaseDirURI(RunData rundata)
{
String ctxtPath = JetspeedResources.getString( JetspeedResources.CONTENT_ROOT_URL_KEY, "");
// Add port only if it is not default port for protocol
String port = "";
if( "http".equals( rundata.getServerScheme() ) &&
rundata.getServerPort() != 80 ) {
port += ":" + rundata.getServerPort();
}
if( "https".equals( rundata.getServerScheme() ) &&
rundata.getServerPort() != 443 ) {
port += ":" + rundata.getServerPort();
}
try {
ctxtPath = rundata.getRequest().getContextPath()+ctxtPath;
} catch (Exception e) {
// not servlet 2.2
logger.error( "Servlet container probably not 2.2", e );
}
return rundata.getServerScheme()+"://"+
rundata.getServerName()+
port + ctxtPath;
}
/**
* Marks the current URI and stores it internally for later usage.
*
* @param rundata the RunData object
*/
public static void markCurrentPage(RunData rundata)
{
javax.servlet.http.HttpSession session = rundata.getSession();
if (session != null) {
// delete action, if exists
String uri = replaceTurbineURIParameter(rundata.getRequest().getRequestURI(), "action", null );
session.setAttribute("URILookup_MarkedPage",uri);
// for servlet api 2.0
// session.putValue("URILookup_MarkedPage",uri);
}
}
/**
* Marks the URI and stores it internally for later usage.
*
* @param aURI the URI to store
* @param rundata the RunData object
*/
public static void markPage(String aURI, RunData rundata)
{
javax.servlet.http.HttpSession session = rundata.getSession();
if (session != null) {
// delete action, if exists
aURI = replaceTurbineURIParameter(aURI, "action", null );
session.setAttribute("URILookup_MarkedPage",aURI);
// for servlet api 2.0
// session.putValue("URILookup_MarkedPage",aURI);
}
}
/**
* Gets the previous marked page as relative url.<br>
* If no page was marked, the Jetspeed Home page is returned.
*
* @return the marked page URI
*/
public static String getMarkedPage(RunData rundata)
{
return getMarkedPage( rundata, true );
}
/**
* Gets the previous marked page.<br>
* If no page was marked, the Jetspeed Home page is returned.
*
* @param relative specifies whether the returing URI should be relative
* @return the marked page URI
*/
public static String getMarkedPage(RunData rundata, boolean relative)
{
javax.servlet.http.HttpSession session = rundata.getSession();
if (session != null) {
String markedPage = (String)session.getAttribute("URILookup_MarkedPage");
// for servlet api 2.0
// String markedPage = (String)session.getValue("URILookup_MarkedPage");
if ((markedPage!=null) && (relative)) {
// check if the URL is absolute. If so, than make it relative
int idx = markedPage.indexOf("://");
if (idx!=-1) { // found it
idx = markedPage.indexOf("/",idx+3); // search the next slash
if (idx!=-1) { // this is the slash after host and port
idx = markedPage.indexOf("/",idx+1); // search the next slash
if (idx!=-1) { // this is the slash after context
markedPage = markedPage.substring(idx);
}
}
}
}
return markedPage;
}
return null;
}
/**
<p>
Given a ParameterParser, get a PortletEntry. This is used so that when you have a
URI created from PortletURIManager you can get back the PortletEntry that created
it originally.
</p>
<p>
Return null if we aren't able to figure out the PortletEntry
</p>
*/
public static final PortletEntry getEntry( ParameterParser params ) throws Exception
{
String name = params.getString("portlet");
return (PortletEntry)Registry.getEntry(Registry.PORTLET, name );
}
/**
* <p>
* Checks that a Portlet is not a PortletControl. If it's a Control returns
* the non-controlled Portlet entry.
* </p>
*
* @return the portlet
*/
private static Portlet getRealPortlet( Portlet portlet )
{
while (portlet instanceof PortletControl) {
portlet = ((PortletControl)portlet).getPortlet();
}
return portlet;
}
/**
* Replaces a turbine-based parameter in the URI.<BR>
* /paramater/value/paramater/value/...
*
* @param uri the URI to modify
* @param parameter the parameter to be replaced
* @param value the value
* @return the new URI
*/
private static String replaceTurbineURIParameter( String uri, String parameter, String value)
{
int idx = uri.indexOf("/" + parameter + "/");
if (idx!=-1) {
int idx2 = uri.indexOf("/",idx+parameter.length()+2);
if (idx2==-1) // end of string
idx2 = uri.length();
uri = uri.substring(0,idx) + uri.substring(idx2);
}
if (value!=null) {
if (!uri.endsWith("/")) uri += "/";
uri += parameter + "/" + value;
}
return uri;
}
/**
* removes all parameters of the URI (after the questionmark)<BR>
* (i.e. http://localhost/jetspeed?type=save to http://localhost/jetspeed)
*
* @param uri the URI t be modified
* @return the URI
*/
private static String resetURIParameter( String uri )
{
if (uri.indexOf("?")!=-1) {
uri = uri.substring(0,uri.indexOf("?"));
}
return uri;
}
/**
* appends the parameter/value pair to the URI
*
* @param uri the URI to be modified
* @param parameter the parameter to be added
* @param value the parameter value
* @return the modified URI
*/
private static String addURIParameter( String uri, String parameter, String value)
{
parameter = URIEncoder.encode( parameter );
value = URIEncoder.encode( value );
if (uri.indexOf("?")!=-1) {
int idx = uri.indexOf( parameter + "=", uri.indexOf("?"));
if (idx!=-1) { // parameter already in URI. remove it
int idx2 = uri.indexOf("&", idx);
if (idx2==-1) // end of string
idx2 = uri.length();
uri = uri.substring(0,idx) + uri.substring(idx2);
}
}
return addURIParameter( uri, parameter + "=" + value );
}
/**
* appends the parameter/value pair to the URI
*
* @param uri the URI to be modified
* @param data the data to be added (has to be the correct format - paramater=value)
* @return the modified URI
*/
private static String addURIParameter( String uri,
String data)
{
if (uri.indexOf("?")!=-1) uri += "&";
else uri += "?";
uri += data;
return uri;
}
private static final String SCREEN_INFO = "Info";
private static final String SCREEN_HOME = JetspeedResources.getString( "template.homepage" );
// private static final String SCREEN_CUSTOMIZE = "Customize";
private static final String SCREEN_CUSTOMIZE = JetspeedResources.getString( "customizer.screen" );
private static final String SCREEN_LOGIN = JetspeedResources.getString( "template.login" );
private static final String SCREEN_NEWACCOUNT = "NewAccount";
private static final String SCREEN_EDIT_ACCOUNT = "EditAccount";
private static final String ACTION_CUSTOMIZER = JetspeedResources.getString( "customizer.action" );
private static final String ACTION_MARKPAGE = "MarkRefPage";
private static final String ACTION_LOGOUT = JetspeedResources.getString( "action.logout" );
private static final String ACTION_ACCEPT_LOGIN = JetspeedResources.getString( "action.login" );
private static final String ACTION_CUSTOMIZER_SAVE = "SavePageConfig";
private static final String ACTION_PREPARE_SCREEN_EDIT_ACCOUNT = "PrepareScreenEditAccount";
}