001/* 002 * (C) Copyright 2006-2009 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * troger 018 */ 019package org.nuxeo.ecm.platform.annotations.preview; 020 021import java.io.IOException; 022import java.io.InputStreamReader; 023import java.io.Reader; 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026 027import org.apache.commons.logging.Log; 028import org.apache.commons.logging.LogFactory; 029import org.jboss.seam.international.LocaleSelector; 030import org.nuxeo.ecm.core.api.Blob; 031import org.nuxeo.ecm.core.api.Blobs; 032import org.nuxeo.ecm.platform.preview.adapter.BlobPostProcessor; 033import org.nuxeo.ecm.platform.web.common.vh.VirtualHostHelper; 034 035/** 036 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a> 037 */ 038public class AnnotationBlobPostProcessor implements BlobPostProcessor { 039 040 private static final Log log = LogFactory.getLog(AnnotationBlobPostProcessor.class); 041 042 protected static final int BUFFER_SIZE = 4096 * 16; 043 044 protected static final String GWT_LOCALE = "<meta name=\"gwt:property\" content=\"locale=%s\" />"; 045 046 protected static final String ANNOTATION_MODULE_JS = "<script type=\"text/javascript\" src='" 047 + VirtualHostHelper.getContextPathProperty() 048 + "/org.nuxeo.ecm.platform.annotations.gwt.AnnotationFrameModule/org.nuxeo.ecm.platform.annotations.gwt.AnnotationFrameModule.nocache.js'></script>"; 049 050 protected static final String INTERNET_EXPLORER_RANGE_JS = "<script type=\"text/javascript\" src='" 051 + VirtualHostHelper.getContextPathProperty() + "/scripts/InternetExplorerRange.js'></script>"; 052 053 protected Pattern headPattern = Pattern.compile("(.*)(<head>)(.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 054 055 protected Pattern htmlPattern = Pattern.compile("(.*)(<html>)(.*)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL); 056 057 protected Pattern charsetPattern = Pattern.compile("(.*) charset=(.*?)\"(.*)", Pattern.CASE_INSENSITIVE 058 | Pattern.DOTALL); 059 060 public Blob process(Blob blob) { 061 String mimetype = blob.getMimeType(); 062 if (mimetype == null || !mimetype.startsWith("text/")) { 063 // blob does not carry HTML payload hence there is no need to try to 064 // inject HTML metadata 065 return blob; 066 } 067 try { 068 String encoding = null; 069 if (blob.getEncoding() == null) { 070 Matcher m = charsetPattern.matcher(blob.getString()); 071 if (m.matches()) { 072 encoding = m.group(2); 073 } 074 } else { 075 encoding = blob.getEncoding(); 076 } 077 078 String blobAsString = getBlobAsString(blob, encoding); 079 String processedBlob = addAnnotationModule(blobAsString); 080 081 blob = Blobs.createBlob(processedBlob, blob.getMimeType(), encoding); 082 } catch (IOException e) { 083 log.debug("Unable to process Blob", e); 084 } 085 return blob; 086 } 087 088 protected String getBlobAsString(Blob blob, String encoding) throws IOException { 089 if (encoding == null) { 090 return blob.getString(); 091 } 092 Reader reader = new InputStreamReader(blob.getStream(), encoding); 093 return readString(reader); 094 } 095 096 protected String addAnnotationModule(String blob) { 097 LocaleSelector localeSelector = LocaleSelector.instance(); 098 StringBuilder sb = new StringBuilder(); 099 Matcher m = headPattern.matcher(blob); 100 if (m.matches()) { 101 sb.append(m.group(1)); 102 sb.append(m.group(2)); 103 if (localeSelector != null) { 104 sb.append(String.format(GWT_LOCALE, localeSelector.getLocaleString())); 105 } 106 sb.append(INTERNET_EXPLORER_RANGE_JS); 107 sb.append(ANNOTATION_MODULE_JS); 108 sb.append(m.group(3)); 109 } else { 110 m = htmlPattern.matcher(blob); 111 if (m.matches()) { 112 sb.append(m.group(1)); 113 sb.append(m.group(2)); 114 sb.append("<head>"); 115 if (localeSelector != null) { 116 sb.append(String.format(GWT_LOCALE, localeSelector.getLocaleString())); 117 } 118 sb.append(INTERNET_EXPLORER_RANGE_JS); 119 sb.append(ANNOTATION_MODULE_JS); 120 sb.append("</head>"); 121 sb.append(m.group(3)); 122 } else { 123 log.debug("Unable to inject Annotation module javascript"); 124 sb.append(blob); 125 } 126 } 127 return sb.toString(); 128 } 129 130 public static String readString(Reader reader) throws IOException { 131 StringBuilder sb = new StringBuilder(BUFFER_SIZE); 132 try { 133 char[] buffer = new char[BUFFER_SIZE]; 134 int read; 135 while ((read = reader.read(buffer, 0, BUFFER_SIZE)) != -1) { 136 sb.append(buffer, 0, read); 137 } 138 } finally { 139 if (reader != null) { 140 reader.close(); 141 } 142 } 143 return sb.toString(); 144 } 145 146}