001/* 002 * (C) Copyright 2006-2009 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * troger 016 */ 017package org.nuxeo.ecm.platform.annotations.preview; 018 019import java.io.IOException; 020import java.io.InputStreamReader; 021import java.io.Reader; 022import java.util.regex.Matcher; 023import java.util.regex.Pattern; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027import org.jboss.seam.international.LocaleSelector; 028import org.nuxeo.ecm.core.api.Blob; 029import org.nuxeo.ecm.core.api.Blobs; 030import org.nuxeo.ecm.platform.preview.adapter.BlobPostProcessor; 031import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper; 032 033/** 034 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 035 */ 036public class AnnotationBlobPostProcessor implements BlobPostProcessor { 037 038 private static final Log log = LogFactory.getLog(AnnotationBlobPostProcessor.class); 039 040 protected static final int BUFFER_SIZE = 4096 * 16; 041 042 protected static final String GWT_LOCALE = "<meta name=\"gwt:property\" content=\"locale=%s\" />"; 043 044 protected static final String ANNOTATION_MODULE_JS = "<script type=\"text/javascript\" src='" 045 + VirtualHostHelper.getContextPathProperty() 046 + "/org.nuxeo.ecm.platform.annotations.gwt.AnnotationFrameModule/org.nuxeo.ecm.platform.annotations.gwt.AnnotationFrameModule.nocache.js'></script>"; 047 048 protected static final String INTERNET_EXPLORER_RANGE_JS = "<script type=\"text/javascript\" src='" 049 + VirtualHostHelper.getContextPathProperty() + "/scripts/InternetExplorerRange.js'></script>"; 050 051 protected Pattern headPattern = Pattern.compile("(.*)(<head>)(.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 052 053 protected Pattern htmlPattern = Pattern.compile("(.*)(<html>)(.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 054 055 protected Pattern charsetPattern = Pattern.compile("(.*) charset=(.*?)\"(.*)", Pattern.CASE_INSENSITIVE 056 | Pattern.DOTALL); 057 058 public Blob process(Blob blob) { 059 String mimetype = blob.getMimeType(); 060 if (mimetype == null || !mimetype.startsWith("text/")) { 061 // blob does not carry HTML payload hence there is no need to try to 062 // inject HTML metadata 063 return blob; 064 } 065 try { 066 String encoding = null; 067 if (blob.getEncoding() == null) { 068 Matcher m = charsetPattern.matcher(blob.getString()); 069 if (m.matches()) { 070 encoding = m.group(2); 071 } 072 } else { 073 encoding = blob.getEncoding(); 074 } 075 076 String blobAsString = getBlobAsString(blob, encoding); 077 String processedBlob = addAnnotationModule(blobAsString); 078 079 blob = Blobs.createBlob(processedBlob, blob.getMimeType(), encoding); 080 } catch (IOException e) { 081 log.debug("Unable to process Blob", e); 082 } 083 return blob; 084 } 085 086 protected String getBlobAsString(Blob blob, String encoding) throws IOException { 087 if (encoding == null) { 088 return blob.getString(); 089 } 090 Reader reader = new InputStreamReader(blob.getStream(), encoding); 091 return readString(reader); 092 } 093 094 protected String addAnnotationModule(String blob) { 095 LocaleSelector localeSelector = LocaleSelector.instance(); 096 StringBuilder sb = new StringBuilder(); 097 Matcher m = headPattern.matcher(blob); 098 if (m.matches()) { 099 sb.append(m.group(1)); 100 sb.append(m.group(2)); 101 if (localeSelector != null) { 102 sb.append(String.format(GWT_LOCALE, localeSelector.getLocaleString())); 103 } 104 sb.append(INTERNET_EXPLORER_RANGE_JS); 105 sb.append(ANNOTATION_MODULE_JS); 106 sb.append(m.group(3)); 107 } else { 108 m = htmlPattern.matcher(blob); 109 if (m.matches()) { 110 sb.append(m.group(1)); 111 sb.append(m.group(2)); 112 sb.append("<head>"); 113 if (localeSelector != null) { 114 sb.append(String.format(GWT_LOCALE, localeSelector.getLocaleString())); 115 } 116 sb.append(INTERNET_EXPLORER_RANGE_JS); 117 sb.append(ANNOTATION_MODULE_JS); 118 sb.append("</head>"); 119 sb.append(m.group(3)); 120 } else { 121 log.debug("Unable to inject Annotation module javascript"); 122 sb.append(blob); 123 } 124 } 125 return sb.toString(); 126 } 127 128 public static String readString(Reader reader) throws IOException { 129 StringBuilder sb = new StringBuilder(BUFFER_SIZE); 130 try { 131 char[] buffer = new char[BUFFER_SIZE]; 132 int read; 133 while ((read = reader.read(buffer, 0, BUFFER_SIZE)) != -1) { 134 sb.append(buffer, 0, read); 135 } 136 } finally { 137 if (reader != null) { 138 reader.close(); 139 } 140 } 141 return sb.toString(); 142 } 143 144}