/* * Copyright (C) 2003-2007 eXo Platform SAS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see<http://www.gnu.org/licenses/>. */ package org.exoplatform.ecm.webui.utils; import java.io.InputStream; import java.net.URLEncoder; import java.text.DecimalFormat; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.ZipInputStream; import javax.imageio.ImageIO; import javax.jcr.*; import javax.jcr.nodetype.NodeDefinition; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.NodeTypeManager; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringUtils; import org.exoplatform.commons.utils.HTMLSanitizer; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.ExoContainerContext; import org.exoplatform.container.definition.PortalContainerConfig; import org.exoplatform.container.xml.PortalContainerInfo; import org.exoplatform.download.DownloadService; import org.exoplatform.download.InputStreamDownloadResource; import org.exoplatform.ecm.webui.form.UIOpenDocumentForm; import org.exoplatform.portal.webui.util.Util; import org.exoplatform.services.cms.documents.TrashService; import org.exoplatform.services.cms.drives.DriveData; import org.exoplatform.services.cms.link.LinkManager; import org.exoplatform.services.cms.templates.TemplateService; import org.exoplatform.services.cms.thumbnail.ThumbnailService; import org.exoplatform.services.jcr.RepositoryService; import org.exoplatform.services.jcr.core.ManageableRepository; import org.exoplatform.services.jcr.ext.app.SessionProviderService; import org.exoplatform.services.jcr.ext.common.SessionProvider; import org.exoplatform.services.jcr.impl.Constants; import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeImpl; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.exoplatform.services.resources.ResourceBundleService; import org.exoplatform.services.security.ConversationState; import org.exoplatform.services.security.Identity; import org.exoplatform.services.wcm.publication.WCMComposer; import org.exoplatform.services.wcm.utils.WCMCoreUtils; import org.exoplatform.wcm.webui.reader.ContentReader; import org.exoplatform.web.application.RequestContext; import org.exoplatform.webui.application.WebuiRequestContext; import org.exoplatform.webui.application.portlet.PortletRequestContext; import org.exoplatform.webui.core.UIComponent; import org.exoplatform.webui.core.UIContainer; import org.exoplatform.webui.core.UIPopupContainer; import org.exoplatform.webui.event.Event; import org.exoplatform.webui.ext.UIExtension; import org.exoplatform.webui.ext.UIExtensionManager; /** * Created by The eXo Platform SARL Author : Dang Van Minh * minh.dang@exoplatform.com May 8, 2008 3:13:32 PM */ public class Utils { final public static String WORKSPACE_NAME = "workspace"; final public static String JCR_PATH = "path"; final public static String DRIVE_FOLDER = "allowCreateFolder"; final public static String MIN_WIDTH = "minwidth"; final public static String CB_DOCUMENT_NAME = "documentName"; final public static String CB_SCRIPT_NAME = "scriptName"; final public static String CB_REF_DOCUMENT = "reference"; final public static String CB_CHILD_DOCUMENT = "child"; final public static String CB_NB_PER_PAGE = "nbPerPage"; final public static String CB_QUERY_STATEMENT = "queryStatement"; final public static String CB_QUERY_ISNEW = "isAddNew"; final public static String CB_QUERY_TYPE = "queryType"; final public static String CB_QUERY_STORE = "queryStore"; final public static String CB_QUERY_LANGUAGE = "queryLanguage"; final public static String CB_VIEW_TOOLBAR = "viewToolbar"; final public static String CB_VIEW_TAGMAP = "viewTagMap"; final public static String CB_VIEW_COMMENT = "viewComment"; final public static String CB_VIEW_VOTE = "viewVote"; final public static String CB_SEARCH_LOCATION = "searchLocation"; final public static String CB_ENABLE_SEARCH_LOCATION = "enableSearch"; final public static String CB_FILTER_CATEGORY = "filterCategory"; final static public String EXO_AUDITABLE = "exo:auditable"; final public static String CB_BOX_TEMPLATE = "boxTemplate"; final public static String CB_TEMPLATE = "template"; final public static String CB_USECASE = "usecase"; final public static String CB_ALLOW_PUBLISH = "isAllowPublish"; final public static String FROM_PATH = "From Path"; final public static String USE_DOCUMENT = "Document"; final public static String USE_JCR_QUERY = "Using a JCR query"; final public static String USE_SCRIPT = "Using a script"; final public static String CB_USE_FROM_PATH = "path"; final public static String CB_USE_DOCUMENT = "detail-document"; final public static String CB_USE_JCR_QUERY = "query"; final public static String CB_USE_SCRIPT = "script"; final public static String SEMI_COLON = ";"; final public static String COLON = ":"; final public static String SLASH = "/"; final public static String BACKSLASH = "\\"; final public static String EXO_CREATED_DATE = "exo:dateCreated"; final public static String EXO_DATETIME = "exo:datetime"; final public static String EXO_MODIFIED_DATE = "exo:dateModified"; final public static String EXO_OWNER = "exo:owner"; final public static String SPECIALCHARACTER[] = { SEMI_COLON, SLASH, BACKSLASH, "|", ">", "<", "\"", "?", "!", "#", "$", "&", "*", "(", ")", "{", "}", "[", "]", ":", ".", "'" }; final public static String REPOSITORY = "repository"; final public static String VIEWS = "views"; final public static String DRIVE = "drive"; final static public String TRASH_HOME_NODE_PATH = "trashHomeNodePath"; final static public String TRASH_REPOSITORY = "trashRepository"; final static public String TRASH_WORKSPACE = "trashWorkspace"; final public static String JCR_INFO = "jcrInfo"; final static public String NT_UNSTRUCTURED = "nt:unstructured"; final static public String NT_FILE = "nt:file"; final static public String NT_FOLDER = "nt:folder"; final static public String NT_FROZEN = "nt:frozenNode"; final static public String EXO_TITLE = "exo:title"; final static public String EXO_SUMMARY = "exo:summary"; final static public String EXO_RELATION = "exo:relation"; final static public String EXO_TAXONOMY = "exo:taxonomy"; final static public String EXO_IMAGE = "exo:image"; final static public String EXO_LANGUAGE = "exo:language"; final static public String LANGUAGES = "languages"; final static public String EXO_METADATA = "exo:metadata"; final static public String MIX_REFERENCEABLE = "mix:referenceable"; final static public String MIX_VERSIONABLE = "mix:versionable"; final static public String NT_RESOURCE = "nt:resource"; final static public String NT_BASE = "nt:base"; final static public String DEFAULT = "default"; final static public String JCR_CONTENT = "jcr:content"; final static public String JCR_CONTENT_DESCRIPTION = "jcr:content/dc:description"; final static public String JCR_MIMETYPE = "jcr:mimeType"; final static public String JCR_FROZEN = "jcr:frozenNode"; final public static String JCR_LASTMODIFIED = "jcr:lastModified"; final public static String JCR_PRIMARYTYPE = "jcr:primaryType"; final static public String JCR_DATA = "jcr:data"; final static public String JCR_SCORE = "jcr:score"; final static public String EXO_ROLES = "exo:roles"; final static public String EXO_TEMPLATEFILE = "exo:templateFile"; final static public String EXO_TEMPLATE = "exo:template"; final static public String EXO_ACTION = "exo:action"; final static public String EXO_ACTIONS = "exo:actions"; final static public String MIX_LOCKABLE = "mix:lockable"; final static public String EXO_CATEGORIZED = "exo:categorized"; final static public String EXO_CATEGORY = "exo:category"; final static public String EXO_HIDDENABLE = "exo:hiddenable"; final static public String EXO_ACCESSPERMISSION = "exo:accessPermissions"; final static public String EXO_PERMISSIONS = "exo:permissions"; final static public String EXO_FAVOURITE = "exo:favourite"; final static public String EXO_FAVOURITE_FOLDER = "exo:favoriteFolder"; final static public String EXO_FAVOURITER = "exo:favouriter"; final static public String EXO_RESTOREPATH = "exo:restorePath"; final static public String EXO_RESTORELOCATION = "exo:restoreLocation"; final static public String EXO_RESTORE_WORKSPACE = "exo:restoreWorkspace"; final static public String EXO_LASTMODIFIER = "exo:lastModifier"; final static public String EXO_TRASH_FOLDER = "exo:trashFolder"; final static public String EXO_TOTAL = "exo:total"; final static public String EXO_WEBCONTENT = "exo:webContent"; final static public String EXO_RSS_ENABLE = "exo:rss-enable"; final static public String EXO_COMMENTS = "exo:comments"; final static public String EXO_MUSICFOLDER = "exo:musicFolder"; final static public String EXO_VIDEOFOLDER = "exo:videoFolder"; final static public String EXO_PICTUREFOLDER = "exo:pictureFolder"; final static public String EXO_DOCUMENTFOLDER = "exo:documentFolder"; final static public String EXO_SEARCHFOLDER = "exo:searchFolder"; final static public String MIX_COMMENTABLE = "mix:commentable"; final static public String MIX_VOTABLE = "mix:votable"; final static public String EXO_SYMLINK = "exo:symlink"; final static public String EXO_PRIMARYTYPE = "exo:primaryType"; final static public String INLINE_DRAFT = "Draft"; final static public String INLINE_PUBLISHED = "Published"; final static public String EXO_SORTABLE = "exo:sortable"; final static public String EXO_RISIZEABLE = "exo:documentSize"; final static public String FLASH_MIMETYPE = "flash"; final static public String[] SPECIFIC_FOLDERS = { EXO_MUSICFOLDER, EXO_VIDEOFOLDER, EXO_PICTUREFOLDER, EXO_DOCUMENTFOLDER, EXO_SEARCHFOLDER }; final static public String[] FOLDERS = { NT_UNSTRUCTURED, NT_FOLDER }; final static public String[] NON_EDITABLE_NODETYPES = { NT_UNSTRUCTURED, NT_FOLDER, NT_RESOURCE }; final public static String[] CATEGORY_NODE_TYPES = { NT_FOLDER, NT_UNSTRUCTURED, EXO_TAXONOMY }; final static public String CATEGORY_MANDATORY = "categoryMandatoryWhenFileUpload"; final static public String UPLOAD_SIZE_LIMIT_MB = "uploadFileSizeLimitMB"; final static public String FILE_VIEWER_EXTENSION_TYPE = "org.exoplatform.ecm.dms.FileViewer"; final static public String MIME_TYPE = "mimeType"; final static public String LOCALE_WEBUI_DMS = "locale.portlet.i18n.WebUIDms"; final static public String REQUESTCONTEXT = "requestcontext"; final static public String WORKSPACE_PARAM = "workspaceName"; final static public String EMPTY = ""; final static public String PUBLIC = "Public"; final static public String GROUP = "Group"; final static public String SITE = "Site"; final static public String PRIVATE = "Private"; final static public String URL_BACKTO = "backto"; public static final String INPUT_TEXT_AREA = "TEXTAREA"; public static final String INPUT_WYSIWYG = "WYSIWYG"; public static final String INPUT_TEXT = "TEXT"; public static final String DEFAULT_CSS_NAME = "InlineText"; public static final String LEFT2RIGHT = "left-to-right"; public static final String RIGHT2LEFT = "right-to-left"; protected static final String SEPARATOR = "="; protected static final String TOOLBAR = "toolbar"; protected static final String CSS = "CSSData"; protected static final String HEIGHT = "height"; protected static final String BUTTON_DIR = "button_direction"; protected static final String PREV_HTML = "prev_html"; protected static final String POST_HTML = "post_html"; protected static final String FAST_PUBLISH_LINK = "fast_publish"; private static final Log LOG = ExoLogger.getLogger(Utils.class.getName()); public Map<String, Object> maps_ = new HashMap<String, Object>(); public static String encodeHTML(String text) { return text.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">"); } public static String formatNodeName(String text) { return text.replaceAll("'", "\\\\'"); } public static boolean isVersionable(Node node) throws RepositoryException { return node.isNodeType(MIX_VERSIONABLE); } public static boolean isTrashHomeNode(Node node) throws RepositoryException { return node.isNodeType(EXO_TRASH_FOLDER); } public static boolean isInTrash(Node node) throws RepositoryException { TrashService trashService = WCMCoreUtils.getService(TrashService.class); return trashService.isInTrash(node); } /** check a symlink node and its target are in Trash or not */ public static boolean targetNodeAndLinkInTrash(Node currentNode) throws Exception { if (Utils.isInTrash(currentNode) && Utils.isSymLink(currentNode)) { Node targetNode = Utils.getNodeSymLink(currentNode); if (Utils.isInTrash(targetNode)) { return true; } } return false; } /** check if we can restore a node */ public static boolean isAbleToRestore(Node currentNode) throws Exception { String restorePath; String restoreWorkspace; Node restoreLocationNode; if (!Utils.isInTrash(currentNode)) { return false; } // return false if the node is exo:actions if (Utils.EXO_ACTIONS.equals(currentNode.getName()) && Utils.isInTrash(currentNode)) { return false; } // return false if the target has been already in Trash. if (Utils.targetNodeAndLinkInTrash(currentNode)) { return false; } if (ConversationState.getCurrent().getIdentity().getUserId().equalsIgnoreCase(WCMCoreUtils.getSuperUser())) { return true; } if (currentNode.isNodeType(TrashService.EXO_RESTORE_LOCATION)) { restorePath = currentNode.getProperty(TrashService.RESTORE_PATH).getString(); restoreWorkspace = currentNode.getProperty(TrashService.RESTORE_WORKSPACE).getString(); restorePath = restorePath.substring(0, restorePath.lastIndexOf("/")); } else { // Is not a deleted node, may be groovy action, hidden node,... return false; } Session session = WCMCoreUtils.getUserSessionProvider().getSession(restoreWorkspace, WCMCoreUtils.getRepository()); try { if (restorePath == null || restorePath.length() == 0) { restoreLocationNode = session.getRootNode(); } else { restoreLocationNode = (Node) session.getItem(restorePath); } } catch (Exception e) { return false; } return PermissionUtil.canAddNode(restoreLocationNode); } public static boolean isReferenceable(Node node) throws RepositoryException { return node.isNodeType(MIX_REFERENCEABLE); } public static boolean isNameValid(String name, String[] regexpression) { for (String c : regexpression) { if (name == null || name.contains(c)) return false; } return true; } public static boolean isNameEmpty(String name) { return (name == null || name.trim().length() == 0); } public static boolean isAuditable(Node node) throws RepositoryException { return node.isNodeType(EXO_AUDITABLE); } public static String getIndexName(Node node) throws RepositoryException { StringBuilder buffer = new StringBuilder(128); buffer.append(node.getName()); int index = node.getIndex(); if (index > 1) { buffer.append('['); buffer.append(index); buffer.append(']'); } return buffer.toString(); } public static List<String> getListAllowedFileType(Node currentNode, TemplateService templateService) throws Exception { List<String> nodeTypes = new ArrayList<String>(); NodeTypeManager ntManager = currentNode.getSession().getWorkspace().getNodeTypeManager(); NodeType currentNodeType = currentNode.getPrimaryNodeType(); NodeDefinition[] childDefs = currentNodeType.getChildNodeDefinitions(); List<String> templates = templateService.getDocumentTemplates(); try { for (int i = 0; i < templates.size(); i++) { String nodeTypeName = templates.get(i).toString(); NodeType nodeType = ntManager.getNodeType(nodeTypeName); NodeType[] superTypes = nodeType.getSupertypes(); boolean isCanCreateDocument = false; for (NodeDefinition childDef : childDefs) { NodeType[] requiredChilds = childDef.getRequiredPrimaryTypes(); for (NodeType requiredChild : requiredChilds) { if (nodeTypeName.equals(requiredChild.getName())) { isCanCreateDocument = true; break; } } if (nodeTypeName.equals(childDef.getName()) || isCanCreateDocument) { if (!nodeTypes.contains(nodeTypeName)) nodeTypes.add(nodeTypeName); isCanCreateDocument = true; } } if (!isCanCreateDocument) { for (NodeType superType : superTypes) { for (NodeDefinition childDef : childDefs) { for (NodeType requiredType : childDef.getRequiredPrimaryTypes()) { if (superType.getName().equals(requiredType.getName())) { if (!nodeTypes.contains(nodeTypeName)) nodeTypes.add(nodeTypeName); isCanCreateDocument = true; break; } } if (isCanCreateDocument) break; } if (isCanCreateDocument) break; } } } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("Unexpected error", e); } } return nodeTypes; } public static String getNodeTypeIcon(Node node, String appended, String mode) throws RepositoryException { return org.exoplatform.services.cms.impl.Utils.getNodeTypeIcon(node, appended, mode); } public static String getNodeTypeIcon(Node node, String appended) throws RepositoryException { return org.exoplatform.services.cms.impl.Utils.getNodeTypeIcon(node, appended); } public static NodeIterator getAuthorizedChildNodes(Node node) throws Exception { NodeIterator iter = node.getNodes(); while (iter.hasNext()) { if (!PermissionUtil.canRead(iter.nextNode())) iter.remove(); } return iter; } public static List<Node> getAuthorizedChildList(Node node) throws Exception { List<Node> children = new ArrayList<Node>(); NodeIterator iter = node.getNodes(); while (iter.hasNext()) { Node child = iter.nextNode(); if (PermissionUtil.canRead(child)) children.add(child); } return children; } public static boolean isLockTokenHolder(Node node) throws Exception { if (node.getLock().getLockToken() != null) { return true; } return false; } public static List<String> getMemberships() throws Exception { return org.exoplatform.services.cms.impl.Utils.getMemberships(); } public static List<String> getGroups() throws Exception { ConversationState conversationState = ConversationState.getCurrent(); Identity identity = conversationState.getIdentity(); Set<String> groups = identity.getGroups(); return new ArrayList<String>(groups); } public static String getNodeOwner(Node node) throws Exception { try { if (node.hasProperty(EXO_OWNER)) { return node.getProperty(EXO_OWNER).getString(); } } catch (Exception e) { return null; } return null; } public static Node findNodeByUUID(String uuid) throws Exception { RepositoryService repositoryService = Util.getUIPortal().getApplicationComponent(RepositoryService.class); SessionProviderService sessionProviderService = Util.getUIPortal().getApplicationComponent(SessionProviderService.class); SessionProvider sessionProvider = sessionProviderService.getSessionProvider(null); ManageableRepository manageableRepository = repositoryService.getCurrentRepository(); Node node = null; for (String wsName : manageableRepository.getWorkspaceNames()) { try { node = sessionProvider.getSession(wsName, manageableRepository).getNodeByUUID(uuid); } catch (ItemNotFoundException e) { continue; } } return node; } public static boolean isSymLink(Node node) throws RepositoryException { LinkManager linkManager = Util.getUIPortal().getApplicationComponent(LinkManager.class); return linkManager.isLink(node); } public static Node getNodeSymLink(Node node) throws Exception { LinkManager linkManager = Util.getUIPortal().getApplicationComponent(LinkManager.class); Node realNode = null; if (linkManager.isLink(node)) { if (linkManager.isTargetReachable(node)) { realNode = linkManager.getTarget(node); } } else { realNode = node; } return realNode; } public static InputStream extractFirstEntryFromZipFile(ZipInputStream zipStream) throws Exception { return zipStream.getNextEntry() == null ? null : zipStream; } public static String getThumbnailImage(InputStream input, String downloadName) throws Exception { DownloadService dservice = WCMCoreUtils.getService(DownloadService.class); InputStreamDownloadResource dresource = new InputStreamDownloadResource(input, "image"); dresource.setDownloadName(downloadName); return dservice.getDownloadLink(dservice.addDownloadResource(dresource)); } public static String getThumbnailImage(Node node, String propertyName) throws Exception { ThumbnailService thumbnailService = Util.getUIPortal().getApplicationComponent(ThumbnailService.class); if (node.isNodeType(NT_FILE)) { String mimeType = node.getNode(JCR_CONTENT).getProperty(JCR_MIMETYPE).getString(); if (mimeType.startsWith("image")) { Node thumbnailNode = thumbnailService.addThumbnailNode(node); InputStream inputStream = node.getNode(JCR_CONTENT).getProperty(JCR_DATA).getStream(); thumbnailService.createSpecifiedThumbnail(thumbnailNode, ImageIO.read(inputStream), propertyName); } } Node thumbnailNode = thumbnailService.getThumbnailNode(node); if (thumbnailNode != null && thumbnailNode.hasProperty(propertyName)) { DownloadService dservice = Util.getUIPortal().getApplicationComponent(DownloadService.class); InputStream input = thumbnailNode.getProperty(propertyName).getStream(); InputStreamDownloadResource dresource = new InputStreamDownloadResource(input, "image"); dresource.setDownloadName(node.getName()); return dservice.getDownloadLink(dservice.addDownloadResource(dresource)); } return null; } public static String calculateFileSize(double fileLengthLong) { int fileLengthDigitCount = Double.toString(fileLengthLong).length(); double fileSizeKB = 0.0; String howBig = ""; if (fileLengthDigitCount < 5) { fileSizeKB = Math.abs(fileLengthLong); howBig = "Byte(s)"; } else if (fileLengthDigitCount >= 5 && fileLengthDigitCount <= 6) { fileSizeKB = Math.abs((fileLengthLong / 1024)); howBig = "KB"; } else if (fileLengthDigitCount >= 7 && fileLengthDigitCount <= 9) { fileSizeKB = Math.abs(fileLengthLong / (1024 * 1024)); howBig = "MB"; } else if (fileLengthDigitCount > 9) { fileSizeKB = Math.abs((fileLengthLong / (1024 * 1024 * 1024))); howBig = "GB"; } String finalResult = roundTwoDecimals(fileSizeKB); return finalResult + " " + howBig; } private static String roundTwoDecimals(double d) { DecimalFormat twoDForm = new DecimalFormat("#.##"); return twoDForm.format(d); } /** * Get resource bundle from PortalApplication resource bundle * * @param key * @return * @throws MissingResourceException */ public static String getResourceBundle(String key) throws MissingResourceException { RequestContext context = Util.getPortalRequestContext(); ResourceBundle res = context.getApplicationResourceBundle(); return res.getString(key); } /** * Get resource bundle from given resource file * * @param name : resource file name * @param key : key * @param cl : ClassLoader to load resource file * @return */ public static String getResourceBundle(String name, String key, ClassLoader cl) { Locale locale = WebuiRequestContext.getCurrentInstance().getLocale(); ResourceBundleService resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class); ResourceBundle resourceBundle = resourceBundleService.getResourceBundle(name, locale, cl); try { return resourceBundle.getString(key); } catch (MissingResourceException ex) { return key; } } public static String getRestContextName(String portalContainerName) { ExoContainer container = ExoContainerContext.getCurrentContainer(); PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class); return portalContainerConfig.getRestContextName(portalContainerName); } public static String getInlineEditingField(Node orgNode, String propertyName) throws Exception { String defaultValue = ""; String idGenerator = ""; Pattern p = Pattern.compile("[^a-zA-Z0-9]"); Matcher m = p.matcher(propertyName); if (orgNode.hasProperty(propertyName)) { defaultValue = orgNode.getProperty(propertyName).getString(); } idGenerator = m.replaceAll("_"); return getInlineEditingField(orgNode, propertyName, defaultValue, INPUT_TEXT, idGenerator, DEFAULT_CSS_NAME, true); } /** * @param orgNode Processed node * @param propertyName which property used for editing * @param inputType input type for editing: TEXT, TEXTAREA, WYSIWYG * @param cssClass class name for CSS, should implement: cssClass, * [cssClass]Title Edit[cssClass] as relative css Should create the * function: InlineEditor.presentationRequestChange[cssClass] to * request the rest-service * @param isGenericProperty set as true to use generic javascript function, * other wise, must create the correctspond function * InlineEditor.presentationRequestChange[cssClass] * @param arguments Extra parameter for Input component (toolbar, width, * height,.. for CKEditor/TextArea) * @return String that can be put on groovy template * @throws Exception * @author vinh_nguyen */ public static String getInlineEditingField(Node orgNode, String propertyName, String defaultValue, String inputType, String idGenerator, String cssClass, boolean isGenericProperty, String... arguments) throws Exception { HashMap<String, String> parsedArguments = parseArguments(arguments); String height = parsedArguments.get(HEIGHT); String bDirection = parsedArguments.get(BUTTON_DIR); String publishLink = parsedArguments.get(FAST_PUBLISH_LINK); Locale locale = WebuiRequestContext.getCurrentInstance().getLocale(); String language = locale.toString(); ResourceBundleService resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class); ResourceBundle resourceBundle; resourceBundle = resourceBundleService.getResourceBundle(LOCALE_WEBUI_DMS, locale); String draft = INLINE_DRAFT; String published = INLINE_PUBLISHED; try { draft = StringEscapeUtils.escapeHtml(resourceBundle.getString("PublicationStates.draft")); published = StringEscapeUtils.escapeHtml(resourceBundle.getString("PublicationStates.published")); } catch (MissingResourceException ex) { if (LOG.isWarnEnabled()) { LOG.warn("Missing resource exception of draft/published status.", ex); } } String portletRealID; if(WebuiRequestContext.getCurrentInstance() instanceof PortletRequestContext) { portletRealID = org.exoplatform.wcm.webui.Utils.getRealPortletId((PortletRequestContext) WebuiRequestContext.getCurrentInstance()); } else { portletRealID = ""; } StringBuffer sb = new StringBuffer(); StringBuffer actionsb = new StringBuffer(); String repo = ((ManageableRepository) orgNode.getSession().getRepository()).getConfiguration().getName(); String workspace = orgNode.getSession().getWorkspace().getName(); String uuid = orgNode.getUUID(); String strSuggestion = ""; String acceptButton = ""; String cancelButton = ""; portletRealID = portletRealID.replace('-', '_'); String showBlockId = "Current" + idGenerator + "_" + portletRealID; String editBlockEditorID = "Edit" + idGenerator + "_" + portletRealID; String editFormID = "Edit" + idGenerator + "Form_" + portletRealID; String newValueInputId = "new" + idGenerator + "_" + portletRealID; String currentValueID = "old" + idGenerator + "_" + portletRealID; String siteName = org.exoplatform.portal.webui.util.Util.getPortalRequestContext().getPortalOwner(); String currentValue = StringUtils.replace(defaultValue, "{portalName}", siteName); try { strSuggestion = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.label.EditingSuggestion")); acceptButton = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.title.AcceptButton")); cancelButton = StringEscapeUtils.escapeHtml(resourceBundle.getString("UIPresentation.title.CancelButton")); } catch (MissingResourceException e) { if (LOG.isWarnEnabled()) { LOG.warn("MissingResourceException of EditingSuggestion/Accept/Cancel buttons.", e); } } actionsb.append(" return InlineEditor.presentationRequestChange"); if (isGenericProperty) { actionsb.append("Property").append("('").append("/property?', '").append(propertyName).append("', '"); } else { actionsb.append(cssClass).append("('"); } actionsb.append(currentValueID) .append("', '") .append(newValueInputId) .append("', '") .append(repo) .append("', '") .append(workspace) .append("', '") .append(uuid) .append("', '") .append(editBlockEditorID) .append("', '") .append(showBlockId) .append("', '") .append(siteName) .append("', '") .append(language); if (inputType.equals(INPUT_WYSIWYG)) { actionsb.append("', 1);"); } else { actionsb.append("');"); } String strAction = actionsb.toString(); if (orgNode.hasProperty(propertyName)) { try { if (propertyName.equals(EXO_TITLE)) return ContentReader.getXSSCompatibilityContent(orgNode.getProperty(propertyName).getString()); String propertyValue; if (propertyName.equals(JCR_CONTENT_DESCRIPTION)) { propertyValue = orgNode.getProperty(propertyName).getValues()[0].getString(); return HTMLSanitizer.sanitize(propertyValue); } if (orgNode.getProperty(propertyName).getDefinition().isMultiple()) { // The requested property is multiple-valued, inline editing enable // users to edit the first value of property propertyValue = orgNode.getProperty(propertyName).getValues()[0].getString(); propertyValue = ContentReader.simpleEscapeHtml(propertyValue); } else { propertyValue = orgNode.getProperty(propertyName).getString(); } if (org.exoplatform.wcm.webui.Utils.getCurrentMode().equals(WCMComposer.MODE_LIVE)) return StringUtils.replace(propertyValue, "{portalName}", siteName); else return "<div class=\"WCMInlineEditable\" contenteditable=\"true\" propertyName=\"" + propertyName + "\" repo=\"" + repo + "\" workspace=\"" + workspace + "\"" + " uuid=\"" + uuid + "\" siteName=\"" + siteName + "\" publishedMsg=\"" + published + "\" draftMsg=\"" + draft + "\" fastpublishlink=\"" + publishLink + "\" language=\"" + language + "\" >" + propertyValue + "</div>"; } catch (Exception e) { if (org.exoplatform.wcm.webui.Utils.getCurrentMode().equals(WCMComposer.MODE_LIVE)) return currentValue; else return "<div class=\"WCMInlineEditable\" contenteditable=\"true\" propertyName=\"" + propertyName + "\" repo=\"" + repo + "\" workspace=\"" + workspace + "\" " + "uuid=\"" + uuid + "\" siteName=\"" + siteName + "\" publishedMsg=\"" + published + "\" draftMsg=\"" + draft + "\" fastpublishlink=\"" + publishLink + "\" language=\"" + language + "\" >" + defaultValue + "</div>"; } } sb.append("<div class=\"InlineEditing\" >\n"); sb.append("\n<div rel=\"tooltip\" data-placement=\"bottom\" id=\"") .append(showBlockId) .append("\" Class=\"") .append(cssClass) .append("\""); sb.append("title=\"").append(strSuggestion).append("\""); sb.append(" onClick=\"InlineEditor.presentationSwitchBlock('") .append(showBlockId) .append("', '") .append(editBlockEditorID) .append("');\""); sb.append("onmouseout=\"this.className='") .append(cssClass) .append("';\" onblur=\"this.className='") .append(cssClass) .append("';\" onfocus=\"this.className='") .append(cssClass) .append("Hover") .append("';\" onmouseover=\"this.className='") .append(cssClass) .append("Hover';\">") .append(currentValue) .append("</div>\n"); sb.append("\t<div id=\"").append(editBlockEditorID).append("\" class=\"Edit").append(cssClass).append("\">\n"); sb.append("\t\t<form name=\"") .append(editFormID) .append("\" id=\"") .append(editFormID) .append("\" onSubmit=\"") .append(strAction) .append("\">\n"); sb.append("<DIV style=\"display:none; visible:hidden\" id=\"") .append(currentValueID) .append("\" name=\"") .append(currentValueID) .append("\">") .append(currentValue) .append("</DIV>"); if (bDirection != null && bDirection.equals(LEFT2RIGHT)) { sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\"") .append(" class =\"AcceptButton\" style=\"float:left\" onclick=\"") .append(strAction) .append("\" title=\"" + acceptButton + "\"> </a>\n"); sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"CancelButton\" style=\"float:left\" ") .append("onClick=\"InlineEditor.presentationSwitchBlock('"); sb.append(editBlockEditorID).append("', '").append(showBlockId).append("');\" title=\"" + cancelButton + "\"> </a>\n"); } else { sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"CancelButton\" ") .append("onClick=\"InlineEditor.presentationSwitchBlock('"); sb.append(editBlockEditorID).append("', '").append(showBlockId).append("');\" title=\"" + cancelButton + "\"> </a>\n"); sb.append("\t\t<a href=\"#\" rel=\"tooltip\" data-placement=\"bottom\" class =\"AcceptButton\" onclick=\"") .append(strAction) .append("\" title=\"" + acceptButton + "\"> </a>\n"); } sb.append("\t\t<div class=\"Edit").append(cssClass).append("Input\">\n "); sb.append("\n\t\t</div>\n\t</form>\n</div>\n\n</div>"); return sb.toString(); } private static HashMap<String, String> parseArguments(String... arguments) { HashMap<String, String> map = new HashMap<String, String>(); int sIndex = -1; for (String argument : arguments) { String value = null; sIndex = argument.indexOf(SEPARATOR); if (sIndex > 0) { value = argument.substring(sIndex + 1); } else { continue; } if (argument.startsWith(JCR_PATH)) { map.put(JCR_PATH, value); continue; } else if (argument.startsWith(TOOLBAR)) { map.put(TOOLBAR, value); continue; } else if (argument.startsWith(CSS)) { map.put(CSS, value); continue; } else if (argument.startsWith(HEIGHT)) { map.put(HEIGHT, value); continue; } else if (argument.startsWith(BUTTON_DIR)) { map.put(BUTTON_DIR, value); continue; } else if (argument.startsWith(PREV_HTML)) { map.put(PREV_HTML, value); continue; } else if (argument.startsWith(POST_HTML)) { map.put(POST_HTML, value); continue; } else if (argument.startsWith(FAST_PUBLISH_LINK)) { map.put(FAST_PUBLISH_LINK, value); continue; } } return map; } /** * Gets the title. * * @param node the node * @return the title * @throws Exception the exception */ public static String getTitle(Node node) throws Exception { String title = null; try { title = node.getProperty("exo:title").getValue().getString(); } catch (PathNotFoundException pnf1) { try { Value[] values = node.getNode("jcr:content").getProperty("dc:title").getValues(); if (values.length != 0) { title = values[0].getString(); } } catch (PathNotFoundException pnf2) { title = null; } } catch (ValueFormatException e) { title = null; } catch (IllegalStateException e) { title = null; } catch (RepositoryException e) { title = null; } if (StringUtils.isBlank(title)) { title = node.getName(); } return ContentReader.getXSSCompatibilityContent(title); } /** * @param node * @return * @throws Exception */ public static String getTitleWithSymlink(Node node) throws Exception { String title = null; Node nProcessNode = node; if (title == null) { nProcessNode = node; if (nProcessNode.hasProperty("exo:title")) { title = nProcessNode.getProperty("exo:title").getValue().getString(); } if (nProcessNode.hasNode("jcr:content")) { Node content = nProcessNode.getNode("jcr:content"); if (content.hasProperty("dc:title")) { try { title = content.getProperty("dc:title").getValues()[0].getString(); } catch (Exception e) { title = null; } } } if (title != null) title = title.trim(); } if (title != null && title.length() > 0) return ContentReader.getXSSCompatibilityContent(title); if (isSymLink(node)) { nProcessNode = getNodeSymLink(nProcessNode); if (nProcessNode == null) { nProcessNode = node; } if (nProcessNode.hasProperty("exo:title")) { title = nProcessNode.getProperty("exo:title").getValue().getString(); } if (nProcessNode.hasNode("jcr:content")) { Node content = nProcessNode.getNode("jcr:content"); if (content.hasProperty("dc:title")) { try { title = content.getProperty("dc:title").getValues()[0].getString(); } catch (Exception e) { title = null; } } } if (title != null) { title = title.trim(); if (title.length() == 0) title = null; } } if (title == null) title = nProcessNode.getName(); return ContentReader.getXSSCompatibilityContent(title); } /** * Get UIComponent to process render a node which has specified mimeType * * @param mimeType * @param container * @return * @throws Exception */ public static UIComponent getUIComponent(String mimeType, UIContainer container) throws Exception { UIExtensionManager manager = WCMCoreUtils.getService(UIExtensionManager.class); List<UIExtension> extensions = manager.getUIExtensions(FILE_VIEWER_EXTENSION_TYPE); Map<String, Object> context = new HashMap<String, Object>(); context.put(MIME_TYPE, mimeType.toLowerCase()); for (UIExtension extension : extensions) { UIComponent uiComponent = manager.addUIExtension(extension, context, container); if (uiComponent != null) return uiComponent; } return null; } /* * Check the current node is eligible to add mix:versionable or not * @param node the current node * @param nodetypes The list of node types have child nodes which are not add * mix:versionaboe while enrolling. * @throws Exception the exception */ public static boolean isMakeVersionable(Node node, String[] nodetypes) throws Exception { boolean isMakeVersionable = true; int deep = node.getDepth(); for (int i = 0; i < deep; i++) { Node parent = node.getParent(); for (String nodetype : nodetypes) { if (nodetype != null && nodetype.length() > 0 && parent.isNodeType(nodetype)) return false; } node = parent; } return isMakeVersionable; } /** * Get a cookie value with given name * * @param cookieName cookies * @return a cookies value */ public static String getCookieByCookieName(String cookieName) { HttpServletRequest request = Util.getPortalRequestContext().getRequest(); Cookie[] cookies = request.getCookies(); if (cookies == null) { return null; } for (int loopIndex = 0; loopIndex < cookies.length; loopIndex++) { Cookie cookie1 = cookies[loopIndex]; if (cookie1.getName().equals(cookieName)) return cookie1.getValue(); } return null; } /** * @param node nt:file node with have the data stream * @return Link to download the jcr:data of the given node * @throws Exception */ public static String getDownloadRestServiceLink(Node node) throws Exception { ExoContainer container = ExoContainerContext.getCurrentContainer(); PortalContainerInfo containerInfo = (PortalContainerInfo) container.getComponentInstanceOfType(PortalContainerInfo.class); String portalName = containerInfo.getContainerName(); PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class); String restContextName = portalContainerConfig.getRestContextName(portalName); StringBuilder sb = new StringBuilder(); Node currentNode = org.exoplatform.wcm.webui.Utils.getRealNode(node); String ndPath = currentNode.getPath(); if (ndPath.startsWith("/")) { ndPath = ndPath.substring(1); } String encodedPath = URLEncoder.encode(ndPath, "utf-8"); encodedPath = encodedPath.replaceAll("%2F", "/"); // we won't encode the // slash characters in the // path sb.append("/").append(restContextName).append("/contents/download/"); sb.append(currentNode.getSession().getWorkspace().getName()).append("/").append(encodedPath); if (node.isNodeType("nt:frozenNode")) { sb.append("?version=" + node.getParent().getName()); } return sb.toString(); } public static String getPDFViewerLink(Node node) throws Exception { ExoContainer container = ExoContainerContext.getCurrentContainer(); PortalContainerInfo containerInfo = (PortalContainerInfo) container.getComponentInstanceOfType(PortalContainerInfo.class); String portalName = containerInfo.getContainerName(); PortalContainerConfig portalContainerConfig = (PortalContainerConfig) container.getComponentInstance(PortalContainerConfig.class); String restContextName = portalContainerConfig.getRestContextName(portalName); StringBuilder sb = new StringBuilder(); String repository = ((ManageableRepository) node.getSession().getRepository()).getConfiguration().getName(); sb.append("/").append(restContextName).append("/pdfviewer/"); sb.append(repository).append("/"); sb.append(node.getSession().getWorkspace().getName()).append("/").append(node.getUUID()); return sb.toString(); } /** * Get allowed folder types in current path. * * @param currentNode * @param currentDrive * @return list of node types * @throws Exception */ public static List<String> getAllowedFolderTypesInCurrentPath(Node currentNode, DriveData currentDrive) throws Exception { List<String> allowedTypes = new ArrayList<String>(); NodeTypeImpl currentNodeType = (NodeTypeImpl) currentNode.getPrimaryNodeType(); String[] arrFoldertypes = currentDrive.getAllowCreateFolders().split(","); NodeTypeManager ntManager = currentNode.getSession().getWorkspace().getNodeTypeManager(); for (String strFolderType : arrFoldertypes) { if (strFolderType.isEmpty()) continue; NodeType folderType = ntManager.getNodeType(strFolderType); if ((currentNodeType).isChildNodePrimaryTypeAllowed(Constants.JCR_ANY_NAME, ((NodeTypeImpl) folderType).getQName())) { allowedTypes.add(strFolderType); } } return allowedTypes; } /** * removes child nodes in path list if ancestor of the node exists in list * * @param srcPath the list of nodes * @return the node list with out child nodes */ public static String[] removeChildNodes(String srcPath) { if (StringUtils.isEmpty(srcPath)) { return new String[] {}; } if (!srcPath.contains(";")) { return new String[] { srcPath }; } String[] paths = srcPath.split(";"); List<String> ret = new ArrayList<String>(); for (int i = 0; i < paths.length; i++) { boolean ok = true; for (int j = 0; j < paths.length; j++) { // check if [i] is child of [j] if ((i != j) && paths[i].startsWith(paths[j]) && (paths[i].length() > paths[j].length()) && (paths[i].charAt(paths[j].length()) == '/')) { ok = false; break; } } if (ok) { ret.add(paths[i]); } } return ret.toArray(new String[] {}); } public static void openDocumentInDesktop(Node currentNode, UIPopupContainer popupContainer, Event<? extends UIComponent> event) throws Exception { HttpServletRequest httpServletRequest = Util.getPortalRequestContext().getRequest(); String nodePath = currentNode.getPath(); String ws = currentNode.getSession().getWorkspace().getName(); String repo = WCMCoreUtils.getRepository().getConfiguration().getName(); String filePath = httpServletRequest.getScheme() + "://" + httpServletRequest.getServerName() + ":" + httpServletRequest.getServerPort() + "/" + WCMCoreUtils.getRestContextName() + "/private/jcr/" + repo + "/" + ws + nodePath; String mountPath = httpServletRequest.getScheme()+ "://" + httpServletRequest.getServerName() + ":" + httpServletRequest.getServerPort() + "/" + WCMCoreUtils.getRestContextName()+ "/private/jcr/" + repo + "/" + ws; if (currentNode.isLocked()) { String[] userLock = { currentNode.getLock().getLockOwner() }; UIOpenDocumentForm uiOpenDocumentForm = popupContainer.activate(UIOpenDocumentForm.class, 600); uiOpenDocumentForm.setId("UIReadOnlyFileConfirmMessage"); uiOpenDocumentForm.setMessageKey("UIPopupMenu.msg.lock-node-read-only"); uiOpenDocumentForm.setArguments(userLock); uiOpenDocumentForm.setFilePath(nodePath); uiOpenDocumentForm.setMountPath(mountPath); uiOpenDocumentForm.setAbsolutePath(filePath); event.getRequestContext() .getJavascriptManager() .require("SHARED/openDocumentInOffice") .addScripts("eXo.ecm.OpenDocumentInOffice.showConfirmBox();"); } else { event.getRequestContext() .getJavascriptManager() .require("SHARED/openDocumentInOffice") .addScripts("eXo.ecm.OpenDocumentInOffice.openDocument('" + filePath + "', '" + mountPath + "');"); } event.getRequestContext().addUIComponentToUpdateByAjax(popupContainer.getParent()); } public static void logUnavaiblePreview(String path) { LOG.warn("Can not preview the document having path : " + path); } static public class NodeTypeNameComparator implements Comparator<NodeType> { public int compare(NodeType n1, NodeType n2) throws ClassCastException { String name1 = n1.getName(); String name2 = n2.getName(); return name1.compareToIgnoreCase(name2); } } }