/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.jsp.util;
import org.opencms.file.CmsObject;
import org.opencms.file.CmsResource;
import org.opencms.flex.CmsFlexController;
import org.opencms.i18n.CmsEncoder;
import org.opencms.i18n.CmsLocaleManager;
import org.opencms.i18n.CmsMessages;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;
import org.opencms.util.CmsHtml2TextConverter;
import org.opencms.util.CmsRequestUtil;
import org.opencms.util.CmsStringUtil;
import org.opencms.util.CmsUUID;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.jsp.PageContext;
import org.apache.commons.beanutils.PropertyUtils;
/**
* Provides utility methods to be used as functions from a JSP with the EL.<p>
*
* @since 7.0.2
*
* @see CmsJspContentAccessBean
*/
public final class CmsJspElFunctions {
/**
* Hide the public constructor.<p>
*/
private CmsJspElFunctions() {
// NOOP
}
/**
* Returns an OpenCms user context created from an Object.<p>
*
* <ul>
* <li>If the input is already a {@link CmsObject}, it is casted and returned unchanged.
* <li>If the input is a {@link ServletRequest}, the OpenCms user context is read from the request context.
* <li>If the input is a {@link PageContext}, the OpenCms user context is read from the request of the page context.
* <li>Otherwise the input is converted to a String which should be a user name, and creation of a OpenCms
* user context with this name is attempted. Please note that this will only work if the user name is
* either the "Guest" user or the "Export" user.
* <li>If no valid OpenCms user context could be created with all of the above, then a new user context for
* the "Guest" user is created.
* </ul>
*
* @param input the input to create an OpenCms user context from
*
* @return an OpenCms user context created from an Object
*/
public static CmsObject convertCmsObject(Object input) {
CmsObject result;
if (input instanceof CmsObject) {
result = (CmsObject)input;
} else if (input instanceof ServletRequest) {
result = CmsFlexController.getCmsObject((ServletRequest)input);
} else if (input instanceof PageContext) {
result = CmsFlexController.getCmsObject(((PageContext)input).getRequest());
} else {
try {
// try to use the given name as user name
result = OpenCms.initCmsObject(String.valueOf(input));
// try to set the right site root
ServletRequest req = convertRequest(input);
if (req instanceof HttpServletRequest) {
result.getRequestContext().setSiteRoot(
OpenCms.getSiteManager().matchRequest((HttpServletRequest)req).getSiteRoot());
}
} catch (CmsException e) {
result = null;
}
}
if (result == null) {
try {
result = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest());
// try to set the right site root
ServletRequest req = convertRequest(input);
if (req instanceof HttpServletRequest) {
result.getRequestContext().setSiteRoot(
OpenCms.getSiteManager().matchRequest((HttpServletRequest)req).getSiteRoot());
}
} catch (CmsException e1) {
// this should never fail since we can always create a "Guest" user
}
}
return result;
}
/**
* Returns a Date created from an Object.<p>
*
* <ul>
* <li>The Object is first checked if it is a {@link Date} already, if so it is casted and returned unchanged.
* <li>If not, the input is checked if it is a {@link Long}, and if so the Date is created from the Long value.
* <li>If it's not a Date and not a Long, the Object is transformed to a String and then it's tried
* to parse a Long out of the String.
* <li>If this fails, it is tried to parse as a Date using the
* default date formatting.
* <li>If this also fails, a new Date is returned that has been initialized with 0.<p>
* </ul>
*
* @param input the Object to create a Date from
*
* @return a Date created from the given Object
*/
public static Date convertDate(Object input) {
Date result;
if (input instanceof Date) {
result = (Date)input;
} else if (input instanceof Long) {
result = new Date(((Long)input).longValue());
} else {
String str = String.valueOf(input);
try {
// treat the input as a String
long l = Long.parseLong(str);
result = new Date(l);
} catch (NumberFormatException e) {
try {
// try to parse String as a Date
result = DateFormat.getDateInstance().parse(str);
} catch (ParseException e1) {
result = null;
}
if (result == null) {
// use default date if parsing fails
result = new Date(0);
}
}
}
return result;
}
/**
* Returns a list of attribute values specified by the attribute name of the items of the given list.<p>
*
* @param input the list of objects to obtain the attribute values from
* @param attributeName the name of the attribute to obtain
* @return a list of attributes specified by the attribute name of the items of the given list
*/
public static List<Object> convertList(List<Object> input, String attributeName) {
List<Object> result = new ArrayList<Object>(input.size());
for (Object item : input) {
try {
result.add(PropertyUtils.getProperty(item, attributeName));
} catch (Exception e) {
// specified attribute is not implemented, return empty list
return Collections.emptyList();
}
}
return result;
}
/**
* Returns a Locale created from an Object.<p>
*
* <ul>
* <li>The Object is first checked if it is a {@link Locale} already, if so it is casted and returned.
* <li>If not, the input is transformed to a String and then a Locale lookup with this String is done.
* <li>If the locale lookup fails, the OpenCms default locale is returned.
* </ul>
*
* @param input the Object to create a Locale from
*
* @return a Locale created from the given Object
*/
public static Locale convertLocale(Object input) {
Locale locale;
if (input instanceof Locale) {
locale = (Locale)input;
} else {
locale = CmsLocaleManager.getLocale(String.valueOf(input));
}
return locale;
}
/**
* Tries to convert the given input object into a request.<p>
*
* This is only possible if the input object is already a request
* or if it is a page context.<p>
*
* If everything else, this method returns <code>null</code>.<p>
*
* @param input the input object to convert to a request
*
* @return a request object, or <code>null</code>
*/
public static ServletRequest convertRequest(Object input) {
ServletRequest req = null;
if (input instanceof ServletRequest) {
req = (ServletRequest)input;
} else if (input instanceof PageContext) {
req = ((PageContext)input).getRequest();
}
return req;
}
/**
* Returns a resource created from an Object.<p>
*
* <ul>
* <li>If the input is already a {@link CmsResource}, it is casted to the resource and returned unchanged.
* <li>If the input is a String, the given OpenCms context is used to read a resource with this name from the VFS.
* <li>If the input is a {@link CmsUUID}, the given OpenCms context is used to read a resource with
* this UUID from the VFS.
* <li>Otherwise the input is converted to a String, and then the given OpenCms context is used to read
* a resource with this name from the VFS.
* </ul>
*
* @param cms the current OpenCms user context
* @param input the input to create a resource from
*
* @return a resource created from the given Object
*
* @throws CmsException in case of errors accessing the OpenCms VFS for reading the resource
*/
public static CmsResource convertResource(CmsObject cms, Object input) throws CmsException {
CmsResource result;
if (input instanceof String) {
// input is a String
result = cms.readResource((String)input);
} else if (input instanceof CmsResource) {
// input is already a resource
result = (CmsResource)input;
} else if (input instanceof CmsUUID) {
// input is a UUID
result = cms.readResource((CmsUUID)input);
} else {
// input seems not really to make sense, try to use it like a String
result = cms.readResource(String.valueOf(input));
}
return result;
}
/**
* Returns a CmsUUID created from an Object.<p>
*
* <ul>
* <li>The Object is first checked if it is a {@link CmsUUID} already, if so it is casted and returned.
* <li>If not, the input is transformed to a byte[] and a new {@link CmsUUID} is created with this byte[].
* <li>Otherwise the input is casted to a String and a new {@link CmsUUID} is created with this String.
* </ul>
*
* @param input the Object to create a CmsUUID from
*
* @return a CmsUUID created from the given Object
*/
public static CmsUUID convertUUID(Object input) {
CmsUUID uuid;
if (input instanceof CmsUUID) {
uuid = (CmsUUID)input;
} else if (input instanceof byte[]) {
uuid = new CmsUUID((byte[])input);
} else {
uuid = new CmsUUID(String.valueOf(input));
}
return uuid;
}
/**
* Encodes a String in a way that is compatible with the JavaScript escape function.
*
* @param source The text to be encoded
* @param encoding the encoding type
*
* @return The JavaScript escaped string
*/
public static String escape(String source, String encoding) {
return CmsEncoder.escape(source, encoding);
}
/**
* Returns the current OpenCms user context from the given page context.<p>
*
* @param input the input to create a CmsObject from
*
* @return the current OpenCms user context from the given page context
*/
public static CmsObject getCmsObject(Object input) {
return convertCmsObject(input);
}
/**
* Returns the size of the given list.<p>
*
* @param input the list of objects to obtain the size from
* @return the size of the given list
*/
public static Integer getListSize(List<Object> input) {
if (input != null) {
return Integer.valueOf(input.size());
}
// input was null
return Integer.valueOf(0);
}
/**
* Returns the current navigation URI.<p>
*
* Which can be the request URI or the VFS resource URI.<p>
*
* In case a sitemap is used, the navigation URI will be the
* request URI, if not the VFS resource URI is returned.<p>
*
* @param input the request convertible object to get the navigation URI from
*
* @return the current navigation URI
*/
public static String getNavigationUri(Object input) {
ServletRequest req = convertRequest(input);
if (req == null) {
return null;
}
return getCmsObject(input).getRequestContext().getUri();
}
/**
* Returns the link without parameters from a String that is formatted for a GET request.<p>
*
* @param url the URL to remove the parameters from
* @return the link without parameters
*/
public static String getRequestLink(String url) {
return CmsRequestUtil.getRequestLink(url);
}
/**
* Returns the value of a parameter from a String that is formatted for a GET request.<p>
*
* @param url the URL to get the parameter value from
* @param paramName the request parameter name
* @return the value of the parameter
*/
public static String getRequestParam(String url, String paramName) {
Map<String, String[]> params = Collections.emptyMap();
if (CmsStringUtil.isNotEmpty(url)) {
int pos = url.indexOf(CmsRequestUtil.URL_DELIMITER);
if (pos >= 0) {
params = CmsRequestUtil.createParameterMap(url.substring(pos + 1));
}
}
String[] result = params.get(paramName);
if (result != null) {
return result[0];
}
return null;
}
/**
* Returns a JSP / EL VFS access bean.<p>
*
* @param input the Object to create a CmsObject from
*
* @return a JSP / EL VFS access bean
*/
public static CmsJspVfsAccessBean getVfsAccessBean(Object input) {
return CmsJspVfsAccessBean.create(CmsJspElFunctions.convertCmsObject(input));
}
/**
* Strips all HTML markup from the given input.<p>
*
* <ul>
* <li>In case the input is an instance of {@link CmsJspContentAccessValueWrapper}, an optimized
* method is used for the HTML stripping.
* <li>Otherwise the input is converted to a String and this String is stripped.
* </ul>
*
* @param input the input to Strip from HTML
*
* @return the given input with all HTML stripped.
*/
public static String stripHtml(Object input) {
if (input instanceof CmsJspContentAccessValueWrapper) {
CmsJspContentAccessValueWrapper wrapper = (CmsJspContentAccessValueWrapper)input;
if (wrapper.getExists()) {
return wrapper.obtainContentValue().getPlainText(wrapper.obtainCmsObject());
} else {
return "";
}
}
try {
return CmsHtml2TextConverter.html2text(String.valueOf(input), OpenCms.getSystemInfo().getDefaultEncoding());
} catch (Exception e) {
return CmsMessages.formatUnknownKey(e.getMessage());
}
}
/**
* Returns a substring of the source, which is at most length characters long.<p>
*
* If a char is cut, <code>" ..."</code> is appended to the result.<p>
*
* @param input the string to trim
* @param length the maximum length of the string to be returned
*
* @return a substring of the source, which is at most length characters long
*
* @see CmsStringUtil#trimToSize(String, int, String)
*/
public static String trimToSize(String input, int length) {
return CmsStringUtil.trimToSize(input, length, " ...");
}
/**
* Decodes a String in a way that is compatible with the JavaScript
* unescape function.<p>
*
* @param source The String to be decoded
* @param encoding the encoding type
*
* @return The JavaScript unescaped String
*/
public static String unescape(String source, String encoding) {
return CmsEncoder.unescape(source, encoding);
}
}