/* * (C) Copyright 2007 Nuxeo SAS (http://nuxeo.com/) and contributors. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser General Public License * (LGPL) version 2.1 which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl.html * * 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. * * Contributors: * Nuxeo - initial API and implementation * * $Id: DocumentModelFunctions.java 30568 2008-02-25 18:52:49Z ogrisel $ */ package org.nuxeo.ecm.platform.ui.web.tag.fn; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.core.Manager; import org.nuxeo.ecm.core.NXCore; import org.nuxeo.ecm.core.api.Blob; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.DocumentLocation; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl; import org.nuxeo.ecm.core.api.model.DocumentPart; import org.nuxeo.ecm.core.api.model.Property; import org.nuxeo.ecm.core.lifecycle.LifeCycle; import org.nuxeo.ecm.core.lifecycle.LifeCycleException; import org.nuxeo.ecm.core.lifecycle.LifeCycleService; import org.nuxeo.ecm.core.schema.FacetNames; import org.nuxeo.ecm.core.schema.SchemaManager; import org.nuxeo.ecm.core.schema.types.ComplexType; import org.nuxeo.ecm.core.schema.types.Field; import org.nuxeo.ecm.core.schema.types.ListType; import org.nuxeo.ecm.core.schema.types.Schema; import org.nuxeo.ecm.core.schema.types.Type; import org.nuxeo.ecm.core.utils.DocumentModelUtils; import org.nuxeo.ecm.directory.DirectoryException; import org.nuxeo.ecm.directory.Session; import org.nuxeo.ecm.directory.api.DirectoryService; import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeEntry; import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry; import org.nuxeo.ecm.platform.types.TypeManager; import org.nuxeo.ecm.platform.types.adapter.TypeInfo; import org.nuxeo.ecm.platform.ui.web.directory.DirectoryFunctions; import org.nuxeo.ecm.platform.ui.web.directory.DirectoryHelper; import org.nuxeo.ecm.platform.ui.web.rest.RestHelper; import org.nuxeo.ecm.platform.ui.web.rest.api.URLPolicyService; import org.nuxeo.ecm.platform.ui.web.util.BaseURL; import org.nuxeo.ecm.platform.ui.web.util.ComponentUtils; import org.nuxeo.ecm.platform.url.DocumentViewImpl; import org.nuxeo.ecm.platform.url.api.DocumentView; import org.nuxeo.ecm.platform.url.codec.DocumentFileCodec; import org.nuxeo.runtime.api.Framework; /** * Document model functions. * * @author <a href="mailto:at@nuxeo.com">Anahide Tchertchian</a> * @author <a href="mailto:og@nuxeo.com">Olivier Grisel</a> */ public final class DocumentModelFunctions implements LiveEditConstants { private static final Log log = LogFactory.getLog(DocumentModelFunctions.class); private static final String JSESSIONID = "JSESSIONID"; private static final String i18n_prefix = "%i18n"; private static final String NXEDIT_URL_VIEW_ID = "nxliveedit.faces"; private static final String NXEDIT_URL_SCHEME = "nxedit"; private static MimetypeRegistry mimetypeService; private static TypeManager typeManagerService; private static DirectoryService dirService; private static LifeCycleService lifeCycleService; // static cache of default viewId per document type shared all among // threads private static final Map<String, String> defaultViewCache = Collections.synchronizedMap(new HashMap<String, String>()); // Utility class. private DocumentModelFunctions() { } private static DirectoryService getDirectoryService() { if (dirService == null) { dirService = DirectoryHelper.getDirectoryService(); } return dirService; } private static MimetypeRegistry getMimetypeService() { if (mimetypeService == null) { try { mimetypeService = Framework.getService(MimetypeRegistry.class); } catch (Exception e) { log.error("Unable to get mimetype service : " + e.getMessage()); } } return mimetypeService; } private static TypeManager getTypeManager() { if (typeManagerService == null) { try { typeManagerService = Framework.getService(TypeManager.class); } catch (Exception e) { log.error("Unable to get typeManager service : " + e.getMessage()); } } return typeManagerService; } private static String getDefaultView(DocumentModel doc) { String docType = doc.getType(); if (defaultViewCache.containsKey(docType)) { return defaultViewCache.get(docType); } else { org.nuxeo.ecm.platform.types.Type type = getTypeManager().getType( docType); if (type == null) { return null; } String defaultView = type.getDefaultView(); defaultViewCache.put(docType, defaultView); return defaultView; } } private static LifeCycleService geLifeCycleService() { if (lifeCycleService == null) { lifeCycleService = NXCore.getLifeCycleService(); if (lifeCycleService == null) { log.error("No Life Cycle service registered"); } } return lifeCycleService; } public static TypeInfo typeInfo(DocumentModel document) { if (document != null) { return document.getAdapter(TypeInfo.class); } else { return null; } } public static String typeLabel(DocumentModel document) { String label = ""; if (document != null) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { label = typeInfo.getLabel(); } } return label; } public static String typeView(DocumentModel document, String viewId) { String viewValue = ""; if (document != null) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { viewValue = typeInfo.getView(viewId); } } return viewValue; } public static String iconPath(DocumentModel document) { String iconPath = ""; if (document != null) { try { iconPath = (String) document.getProperty("common", "icon"); } catch (ClientException e) { iconPath = null; } if (iconPath == null || iconPath.length() == 0 || document.getType().equals("Workspace")) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { iconPath = typeInfo.getIcon(); } } } return iconPath; } public static String iconExpandedPath(DocumentModel document) { String iconPath = ""; if (document != null) { try { iconPath = (String) document.getProperty("common", "icon-expanded"); } catch (ClientException e) { iconPath = null; } if (iconPath == null || iconPath.length() == 0) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { iconPath = typeInfo.getIconExpanded(); // Set to default icon if expanded is not set if (iconPath == null || iconPath.equals("")) { iconPath = iconPath(document); } } } } return iconPath; } public static String bigIconPath(DocumentModel document) { String iconPath = ""; if (document != null) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { iconPath = typeInfo.getBigIcon(); } } return iconPath; } public static String bigIconExpandedPath(DocumentModel document) { String iconPath = ""; if (document != null) { TypeInfo typeInfo = document.getAdapter(TypeInfo.class); if (typeInfo != null) { iconPath = typeInfo.getIconExpanded(); // Set to default icon if expanded is not set if (iconPath == null || iconPath.equals("")) { iconPath = bigIconPath(document); } } } return iconPath; } public static String fileIconPath(Blob blob) { String iconPath = ""; if (blob != null) { try { MimetypeEntry mimeEntry = getMimetypeService().getMimetypeEntryByMimeType( blob.getMimeType()); if (mimeEntry != null) { if (mimeEntry.getIconPath() != null) { // FIXME: above Context should find it iconPath = "/icons/" + mimeEntry.getIconPath(); } } } catch (Exception err) { } } return iconPath; } public static String titleOrId(DocumentModel document) { String title = null; if (document != null) { try { title = (String) document.getProperty("dublincore", "title"); } catch (ClientException e) { title = null; } if (title == null || title.length() == 0) { // handle root document title if ("/".equals(document.getPathAsString())) { title = "/"; } else { title = document.getId(); } } } if (title == null) { title = "<Unknown>"; } if (title.startsWith(i18n_prefix)) { String i18nTitle = title.substring(i18n_prefix.length()); FacesContext context = FacesContext.getCurrentInstance(); title = ComponentUtils.translate(context, i18nTitle); } return title; } /** * @since 6.0 */ public static String titleFromId(final String documentId) throws ClientException { final CoreSession coreSession = (CoreSession) Component.getInstance("documentManager"); if (StringUtils.isNotBlank(documentId)) { try { return coreSession.getDocument(new IdRef(documentId)).getTitle(); } catch (ClientException e) { log.info(String.format("Could not find document with id %s", documentId)); return documentId; } } return null; } public static boolean isDocumentModel(Object value) { return value instanceof DocumentModel; } public static boolean isDirty(DocumentModel doc) throws ClientException { if (doc == null) { return false; } for (DocumentPart part : doc.getParts()) { if (part.isDirty()) { // check if dirty properties are not empty Iterator<Property> props = part.getDirtyChildren(); if (props != null) { while (props.hasNext()) { Property prop = props.next(); Serializable value = prop.getValue(); if (value != null) { if (isPropertyValueDirty(value)) { return true; } } } } } } return false; } @SuppressWarnings("rawtypes") protected static boolean isPropertyValueDirty(Object value) { if (value instanceof String) { if (!StringUtils.isBlank((String) value)) { return true; } } else if (value instanceof List) { List<?> list = (List) value; if (!list.isEmpty()) { return true; } } else if (value instanceof Collection) { Collection<?> col = (Collection) value; if (!col.isEmpty()) { return true; } } else if (value instanceof Object[]) { Object[] col = (Object[]) value; if (col.length > 0) { return true; } } else if (value instanceof Map) { Map<?, ?> map = (Map) value; if (map.isEmpty()) { return true; } for (Object mapItem : map.values()) { if (isPropertyValueDirty(mapItem)) { return true; } } } else if (value != null) { // in any other case, test if object is null (int, calendar, // etc...) return true; } return false; } public static boolean hasPermission(DocumentModel document, String permission) throws ClientException { if (document == null) { return false; } CoreSession session = document.getCoreSession(); if (session == null) { session = (CoreSession) Component.getInstance("documentManager", ScopeType.CONVERSATION); } if (session == null) { log.error("Cannot retrieve CoreSession for " + document); return false; } boolean granted = session.hasPermission(document.getRef(), permission); return granted; } /** * Returns true if document can be modified. * <p> * A document can be modified if current user has 'Write' permission on it * and document is mutable (no archived version). * * @param document * @return true if document can be modified. * @throws ClientException */ public static boolean canModify(DocumentModel document) throws ClientException { if (document == null) { return false; } return hasPermission(document, "Write") && !document.hasFacet(FacetNames.IMMUTABLE); } /** * Returns the default value for given schema field. * * @param schemaName the schema name * @param fieldName the field name * @return the default value. * @deprecated use defaultValue(propertyName) instead */ @Deprecated public static Object defaultValue(String schemaName, String fieldName) throws Exception { Object value = null; SchemaManager tm = Framework.getService(SchemaManager.class); Schema schema = tm.getSchema(schemaName); Field field = schema.getField(fieldName); Type type = field.getType(); if (type.isListType()) { Type itemType = ((ListType) type).getFieldType(); value = itemType.newInstance(); } return value; } protected static Field getField(Field parent, String subFieldName) { if (parent != null) { Type type = parent.getType(); if (type.isListType()) { Type itemType = ((ListType) type).getFieldType(); if (itemType.isComplexType()) { ComplexType complexType = (ComplexType) itemType; Field subField = complexType.getField(subFieldName); return subField; } } else if (type.isComplexType()) { return ((ComplexType) type).getField(subFieldName); } } return null; } /** * Returns the default value for given property name. * * @param propertyName as xpath * @return the default value. * @throws Exception */ public static Object defaultValue(String propertyName) throws Exception { SchemaManager tm = Framework.getService(SchemaManager.class); Field field = null; if (propertyName != null && propertyName.contains("/")) { // need to resolve subfields String[] properties = propertyName.split("/"); Field resolvedField = tm.getField(properties[0]); for (int x = 1; x < properties.length; x++) { if (resolvedField == null) { break; } resolvedField = getField(resolvedField, properties[x]); } if (resolvedField != null) { field = resolvedField; } } else { field = tm.getField(propertyName); } Object value = null; if (field != null) { Type type = field.getType(); if (type.isListType()) { Type itemType = ((ListType) type).getFieldType(); value = itemType.newInstance(); } } return value; } /** * @since 6.0 */ public static String fileUrl(String baseURL, String patternName, DocumentModel doc, String blobPropertyName, String filename) { if (doc == null) { return null; } try { DocumentLocation docLoc = new DocumentLocationImpl(doc); Map<String, String> params = new HashMap<String, String>(); params.put(DocumentFileCodec.FILE_PROPERTY_PATH_KEY, blobPropertyName); params.put(DocumentFileCodec.FILENAME_KEY, filename); DocumentView docView = new DocumentViewImpl(docLoc, null, params); // generate url URLPolicyService service = Framework.getService(URLPolicyService.class); if (patternName == null) { patternName = service.getDefaultPatternName(); } return service.getUrlFromDocumentView(patternName, docView, baseURL); } catch (Exception e) { log.error("Could not generate url for document file", e); } return null; } public static String fileUrl(String patternName, DocumentModel doc, String blobPropertyName, String filename) { return fileUrl(BaseURL.getBaseURL(), patternName, doc, blobPropertyName, filename); } public static String bigFileUrl(DocumentModel doc, String blobPropertyName, String filename) { if (doc == null) { return null; } String bigDownloadURL = BaseURL.getBaseURL(); bigDownloadURL += "nxbigfile" + "/"; bigDownloadURL += doc.getRepositoryName() + "/"; bigDownloadURL += doc.getRef().toString() + "/"; bigDownloadURL += blobPropertyName + "/"; bigDownloadURL += filename; return bigDownloadURL; } public static String fileDescription(DocumentModel document, String blobPropertyName, String filePropertyName, String filename) { String fileInfo = ""; if (document != null) { Long blobLength = null; try { Blob blob = (Blob) document.getPropertyValue(blobPropertyName); if (blob != null) { blobLength = blob.getLength(); } } catch (ClientException e) { // no prop by that name with that type } if (filename != null && filePropertyName != null) { try { filename = (String) document.getPropertyValue(filePropertyName); } catch (ClientException e) { // no prop by that name with that type } } if (blobLength != null && filename != null) { fileInfo = String.format("%s [%s]", filename, Functions.printFileSize(String.valueOf(blobLength))); } else if (blobLength != null) { fileInfo = String.format("[%s]", Functions.printFileSize(String.valueOf(blobLength))); } else if (filename != null) { fileInfo = filename; } } return fileInfo; } /** * Convenient method to get the REST URL of a blob inside the * <code>Files</code> schema. * * @param patternName * @param doc The document model. * @param index index of the element containing the blob. * <code>index</code> starts at 0. * @param filename The filename of the blob. * @return the REST URL for the blob, or <code>null</code> if an error * occurred. */ public static String complexFileUrl(String patternName, DocumentModel doc, int index, String filename) { return complexFileUrl(patternName, doc, "files:files", index, DEFAULT_SUB_BLOB_FIELD, filename); } /** * Get the REST URL for a blob inside a list of complex type. For instance, * <code>http://localhost/nuxeo/nxfile/server/docId/files:files%5B0%5D/file/image.png</code> * for the blob property 'file' of the first element inside the * 'files:files' list. * * @param patternName * @param doc The document model. * @param listElement Element containing a list of complex type. * @param index Index of the element containing the blob inside the list. * <code>index</code> starts at 0. * @param blobPropertyName The property containing the blob. * @param filename Filename of the blob. * @return the REST URL for the blob, or <code>null</code> if an error * occurred. */ public static String complexFileUrl(String patternName, DocumentModel doc, String listElement, int index, String blobPropertyName, String filename) { try { DocumentLocation docLoc = new DocumentLocationImpl(doc); Map<String, String> params = new HashMap<String, String>(); String fileProperty = getPropertyPath(listElement, index, blobPropertyName); params.put(DocumentFileCodec.FILE_PROPERTY_PATH_KEY, fileProperty); params.put(DocumentFileCodec.FILENAME_KEY, filename); DocumentView docView = new DocumentViewImpl(docLoc, null, params); // generate url URLPolicyService service = Framework.getService(URLPolicyService.class); if (patternName == null) { patternName = service.getDefaultPatternName(); } return service.getUrlFromDocumentView(patternName, docView, BaseURL.getBaseURL()); } catch (Exception e) { log.error("Could not generate url for document file", e); } return null; } // TODO: add method accepting filename property name (used for edit online) public static String documentUrl(DocumentModel doc, HttpServletRequest req) { return documentUrl(null, doc, null, null, false); } public static String documentUrl(DocumentModel doc) { return documentUrl(null, doc, null, null, false); } public static String documentUrl(String patternName, DocumentModel doc, String viewId, Map<String, String> parameters, boolean newConversation) { return documentUrl(patternName, doc, viewId, parameters, newConversation, null); } public static String documentUrl(String patternName, DocumentModel doc, String viewId, Map<String, String> parameters, boolean newConversation, HttpServletRequest req) { DocumentLocation docLoc = new DocumentLocationImpl(doc); if (viewId == null || viewId.length() == 0) { viewId = getDefaultView(doc); } parameters = parameters == null ? new HashMap<String, String>() : parameters; if (doc.isVersion()) { parameters.put("version", "true"); } return documentUrl(patternName, docLoc, viewId, parameters, newConversation, req); } /** * @since 5.7 */ public static String documentUrl(String patternName, DocumentLocation docLoc, String viewId, Map<String, String> parameters, boolean newConversation, HttpServletRequest req) { try { DocumentView docView = new DocumentViewImpl(docLoc, viewId, parameters); // generate url URLPolicyService service = Framework.getService(URLPolicyService.class); if (patternName == null || patternName.length() == 0) { patternName = service.getDefaultPatternName(); } String baseURL = null; if (req == null) { baseURL = BaseURL.getBaseURL(); } else { baseURL = BaseURL.getBaseURL(req); } String url = service.getUrlFromDocumentView(patternName, docView, baseURL); // pass conversation info if needed if (!newConversation && url != null) { url = RestHelper.addCurrentConversationParameters(url); } return url; } catch (Exception e) { log.error("Could not generate url for document", e); } return null; } /** * Computes an URL for a {@code repositoryName} only. * * @since 5.7 */ public static String repositoryUrl(String patternName, String repositoryName, String viewId, Map<String, String> parameters, boolean newConversation) { return repositoryUrl(patternName, repositoryName, viewId, parameters, newConversation, null); } /** * Computes an URL for a {@code repositoryName} only. * * @since 5.7 */ public static String repositoryUrl(String patternName, String repositoryName, String viewId, Map<String, String> parameters, boolean newConversation, HttpServletRequest req) { DocumentLocation docLoc = new DocumentLocationImpl(repositoryName, null); parameters = parameters == null ? new HashMap<String, String>() : parameters; return documentUrl(patternName, docLoc, viewId, parameters, newConversation, req); } protected static void addQueryParameter(StringBuilder sb, String name, String value, boolean isFirst) throws ClientException { if (isFirst) { sb.append("?"); } else { sb.append("&"); } if (value == null) { return; } sb.append(name); sb.append("="); try { sb.append(URLEncoder.encode(value, URL_ENCODE_CHARSET)); } catch (UnsupportedEncodingException e) { throw new ClientException(String.format( "could not encode URL parameter: %s=%s", name, value), e); } } /** * Build the nxedit URL for the "edit existing document" use case for a * document using the file:content field as Blob holder * * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveEditUrl(DocumentModel doc) throws ClientException { return liveEditUrl(doc, DEFAULT_SCHEMA, DEFAULT_BLOB_FIELD, DEFAULT_FILENAME_FIELD); } /** * Build the nxedit URL for the "edit existing document" use case * * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveEditUrl(DocumentModel doc, String schemaName, String blobFieldName, String filenameFieldName) throws ClientException { if (doc == null) { return ""; // JSF DebugUtil.printTree may call this } StringBuilder queryParamBuilder = new StringBuilder(); addQueryParameter(queryParamBuilder, ACTION, ACTION_EDIT_DOCUMENT, true); addQueryParameter(queryParamBuilder, REPO_ID, doc.getRepositoryName(), false); addQueryParameter(queryParamBuilder, DOC_REF, doc.getRef().toString(), false); if (schemaName == null || "".equals(schemaName)) { // try to extract it from blob field name schemaName = DocumentModelUtils.getSchemaName(blobFieldName); blobFieldName = DocumentModelUtils.getFieldName(blobFieldName); filenameFieldName = DocumentModelUtils.getFieldName(filenameFieldName); } addQueryParameter(queryParamBuilder, SCHEMA, schemaName, false); addQueryParameter(queryParamBuilder, BLOB_FIELD, blobFieldName, false); addQueryParameter(queryParamBuilder, FILENAME_FIELD, filenameFieldName, false); return buildNxEditUrl(queryParamBuilder.toString()); } /** * Build the nxedit URL for the "edit existing document" use case * * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String complexLiveEditUrl(DocumentModel doc, String listPropertyName, int index, String blobPropertyName, String filenamePropertyName) throws ClientException { StringBuilder queryParamBuilder = new StringBuilder(); addQueryParameter(queryParamBuilder, ACTION, ACTION_EDIT_DOCUMENT, true); addQueryParameter(queryParamBuilder, REPO_ID, doc.getRepositoryName(), false); addQueryParameter(queryParamBuilder, DOC_REF, doc.getRef().toString(), false); addQueryParameter(queryParamBuilder, BLOB_PROPERTY_NAME, getPropertyPath(listPropertyName, index, blobPropertyName), false); addQueryParameter(queryParamBuilder, FILENAME_PROPERTY_NAME, getPropertyPath(listPropertyName, index, filenamePropertyName), false); return buildNxEditUrl(queryParamBuilder.toString()); } /** * Build the nxedit URL for the "create new document" use case with a * document using the file:content field as Blob holder * * @param mimetype the mime type of the newly created document * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveCreateUrl(String mimetype) throws ClientException { return liveCreateUrl(mimetype, DEFAULT_DOCTYPE, DEFAULT_SCHEMA, DEFAULT_BLOB_FIELD, DEFAULT_FILENAME_FIELD); } /** * Build the nxedit URL for the "create new document" use case * * @param mimetype the mime type of the newly created document * @param docType the document type of the document to create * @param schemaName the schema of the blob to hold the new attachment * @param blobFieldName the field name of the blob to hold the new * attachment * @param filenameFieldName the field name of the filename of the new * attachment * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveCreateUrl(String mimetype, String docType, String schemaName, String blobFieldName, String filenameFieldName) throws ClientException { StringBuilder queryParamBuilder = new StringBuilder(); addQueryParameter(queryParamBuilder, ACTION, ACTION_CREATE_DOCUMENT, true); addQueryParameter(queryParamBuilder, MIMETYPE, mimetype, false); addQueryParameter(queryParamBuilder, SCHEMA, schemaName, false); addQueryParameter(queryParamBuilder, BLOB_FIELD, blobFieldName, false); addQueryParameter(queryParamBuilder, FILENAME_FIELD, filenameFieldName, false); addQueryParameter(queryParamBuilder, DOC_TYPE, docType, false); return buildNxEditUrl(queryParamBuilder.toString()); } /** * Build the nxedit URL for the "create new document from template" use * case with "File" doc type and "file" schema * * @param template the document holding the blob to be used as template * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveCreateFromTemplateUrl(DocumentModel template) throws ClientException { return liveCreateFromTemplateUrl(template, DEFAULT_SCHEMA, DEFAULT_BLOB_FIELD, DEFAULT_DOCTYPE, DEFAULT_SCHEMA, DEFAULT_BLOB_FIELD, DEFAULT_FILENAME_FIELD); } /** * Build the nxedit URL for the "create new document from template" use * case * * @param template the document holding the blob to be used as template * @param templateSchemaName the schema of the blob holding the template * @param templateBlobFieldName the field name of the blob holding the * template * @param docType the document type of the new document to create * @param schemaName the schema of the new blob to be saved as attachment * @param blobFieldName the field name of the new blob to be saved as * attachment * @param filenameFieldName the field name of the filename of the * attachment * @return the encoded URL string * @throws ClientException if the URL encoding fails */ public static String liveCreateFromTemplateUrl(DocumentModel template, String templateSchemaName, String templateBlobFieldName, String docType, String schemaName, String blobFieldName, String filenameFieldName) throws ClientException { StringBuilder queryParamBuilder = new StringBuilder(); addQueryParameter(queryParamBuilder, ACTION, ACTION_CREATE_DOCUMENT_FROM_TEMPLATE, true); addQueryParameter(queryParamBuilder, TEMPLATE_REPO_ID, template.getRepositoryName(), false); addQueryParameter(queryParamBuilder, TEMPLATE_DOC_REF, template.getRef().toString(), false); addQueryParameter(queryParamBuilder, TEMPLATE_SCHEMA, templateSchemaName, false); addQueryParameter(queryParamBuilder, TEMPLATE_BLOB_FIELD, templateBlobFieldName, false); addQueryParameter(queryParamBuilder, SCHEMA, schemaName, false); addQueryParameter(queryParamBuilder, BLOB_FIELD, blobFieldName, false); addQueryParameter(queryParamBuilder, FILENAME_FIELD, filenameFieldName, false); addQueryParameter(queryParamBuilder, DOC_TYPE, docType, false); return buildNxEditUrl(queryParamBuilder.toString()); } private static String buildNxEditUrl(String queryParameters) throws ClientException { FacesContext context = FacesContext.getCurrentInstance(); HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest(); // build the URL prefix by concatenating nxedit: scheme with the // http:// or https:// base URL from the current request context and // the LiveEditBoostrapHelper JSF view StringBuilder nxeditUrlBuilder = new StringBuilder(NXEDIT_URL_SCHEME); nxeditUrlBuilder.append(":"); nxeditUrlBuilder.append(BaseURL.getBaseURL(request)); nxeditUrlBuilder.append(NXEDIT_URL_VIEW_ID); // add the query parameters them selves nxeditUrlBuilder.append(queryParameters); // add seam conversation and JSESSION ids addQueryParameter(nxeditUrlBuilder, Manager.instance().getConversationIdParameter(), Manager.instance().getCurrentConversationId(), false); addQueryParameter(nxeditUrlBuilder, JSESSIONID, extractJSessionId(request), false); return nxeditUrlBuilder.toString(); } /** * Extract the current JSESSIONID value from the request context * * @param request the current HttpServletRequest request * @return the current JSESSIONID string */ public static String extractJSessionId(HttpServletRequest request) { if (request.getSession() != null) { return request.getSession().getId(); } if (request.getCookies() != null) { for (Cookie cookie : request.getCookies()) { if (cookie.getName().equalsIgnoreCase("jsessionid")) { return cookie.getValue(); } } } return null; } /** * Returns the label for given directory and id. * * @param directoryName the directory name * @param id the label id * @return the label. * @throws DirectoryException * @deprecated use * {@link DirectoryFunctions#getDirectoryEntry(String, String)} */ @Deprecated public static String getLabelFromId(String directoryName, String id) throws DirectoryException { if (id == null) { return ""; } Session directory = null; try { directory = getDirectoryService().open(directoryName); // XXX hack, directory entries have only one datamodel DocumentModel documentModel = directory.getEntry(id); String schemaName = documentModel.getSchemas()[0]; return (String) documentModel.getProperty(schemaName, "label"); } catch (Exception e) { return ""; } finally { if (directory != null) { directory.close(); } } } public static String getPropertyPath(String listPropertyName, int index, String subPropertyName) { return String.format("%s/%s/%s", listPropertyName, index, subPropertyName); } /** * Returns all the available transitions given the current state. * * @param lifeCycleName the Life Cycle name * @param currentState the state from which the transitions should start * @since 5.4.2 */ public static Collection<String> getAvailableLifeCycleTransitions( String lifeCycleName, String currentState) throws LifeCycleException { LifeCycle lf = geLifeCycleService().getLifeCycleByName(lifeCycleName); return lf.getAllowedStateTransitionsFrom(currentState); } /** * Reset default view cache. * * @since 5.8 */ public static void resetDefaultViewCache() { defaultViewCache.clear(); } }