/* * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * 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. * * Contributors: * rux, tdelprat * */ package org.nuxeo.ecm.webapp.liveedit; import static org.jboss.seam.ScopeType.SESSION; import static org.jboss.seam.annotations.Install.FRAMEWORK; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.nuxeo.runtime.api.Framework; /** * This Seam component is used to represent the client configuration for LiveEdit. * <p> * On the client side, the LiveEdit plugin advertise its feature via the Accept Header of the browser. This information * may be used to decide if LiveEdit links must be displayed or not. * <p> * The behavior can be configured via the property: org.nuxeo.ecm.platform.liveedit.config * <p> * There are 3 possible values : * <ul> * <li>client : let the client choose what is live editable => use the mime-types send by the client to define what must * be live editable * <li>server : let the server decide => use the mime-type registry define what types are liveEditable * <li>both : use client and server intersection => in order to be liveEditable a type must be advertised by the client * and set to liveEditable in the mimetypeRegistry * </ul> * Client advertising is done in the Accept header: Accept : application/x-nuxeo-liveedit:mimetype1;mimetype2 Starting * the 5.2, the addon can send the standardized accept header, as Accept : * application/x-nuxeo-liveedit;ext0="mimetype1";ext1="mimetype2".. Also, the addon can still send the old way, so the * both forms are accepted. See NXP-3257 * * @author Thierry Delprat * @author rux */ @Scope(SESSION) @Name("liveEditClientConfig") @Install(precedence = FRAMEWORK) public class LiveEditClientConfig implements Serializable { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(LiveEditClientConfig.class); protected Boolean clientHasLiveEditInstalled; protected List<String> advertizedLiveEditableMimeTypes; protected static String liveEditConfigPolicy; public static final String LE_MIME_TYPE = "application/x-nuxeo-liveedit"; public static final String LE_CONFIG_PROPERTY = "org.nuxeo.ecm.platform.liveedit.config"; public static final String LE_CONFIG_CLIENTSIDE = "client"; public static final String LE_CONFIG_SERVERSIDE = "server"; public static final String LE_CONFIG_BOTHSIDES = "both"; protected void detectLiveEditClientConfig() { clientHasLiveEditInstalled = false; advertizedLiveEditableMimeTypes = new ArrayList<String>(); if (getLiveEditConfigurationPolicy().equals(LE_CONFIG_SERVERSIDE)) { // in case if Server side config, consider liveEdit is installed clientHasLiveEditInstalled = true; return; } FacesContext fContext = FacesContext.getCurrentInstance(); if (fContext == null) { log.error("unable to fetch facesContext, can not detect liveEdit client config"); } else { Map<String, String> headers = fContext.getExternalContext().getRequestHeaderMap(); String accept = headers.get("Accept"); if (accept == null) { return; } String[] accepted = accept.split(","); for (String acceptHeader : accepted) { if (acceptHeader != null) { acceptHeader = acceptHeader.trim(); } else { continue; } if (acceptHeader.startsWith(LE_MIME_TYPE)) { clientHasLiveEditInstalled = true; String[] subTypes = acceptHeader.split(";"); for (String subType : subTypes) { // accept both forms: // application/x-nuxeo-liveedit:mimetype1;mimetype2 // application/x-nuxeo-liveedit;ext0="mimetype1";ext1="mimetype2" int equalQuoteIndex = subType.indexOf("=\""); String valueSubType = subType; if (equalQuoteIndex >= 0 && subType.length() > equalQuoteIndex + 3) { valueSubType = subType.substring(equalQuoteIndex + 2, subType.length() - 1); } advertizedLiveEditableMimeTypes.add(valueSubType.replace("!", "/")); } } } } } public boolean isLiveEditInstalled() { if (clientHasLiveEditInstalled == null) { detectLiveEditClientConfig(); } return clientHasLiveEditInstalled; } public String getLiveEditConfigurationPolicy() { if (liveEditConfigPolicy == null) { liveEditConfigPolicy = Framework.getProperty(LE_CONFIG_PROPERTY, LE_CONFIG_CLIENTSIDE); } return liveEditConfigPolicy; } public boolean isMimeTypeLiveEditable(String mimetype) { if (advertizedLiveEditableMimeTypes == null) { detectLiveEditClientConfig(); } return advertizedLiveEditableMimeTypes.contains(mimetype); } }