001/* 002 * (C) Copyright 2006-2007 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 */ 015package org.nuxeo.ecm.diff.content.adapter; 016 017import java.util.HashMap; 018import java.util.Map; 019 020import org.apache.commons.lang.StringUtils; 021import org.apache.commons.logging.Log; 022import org.apache.commons.logging.LogFactory; 023import org.nuxeo.ecm.core.api.DocumentModel; 024import org.nuxeo.ecm.core.api.blobholder.BlobHolder; 025import org.nuxeo.ecm.diff.content.ContentDiffAdapter; 026import org.nuxeo.ecm.diff.content.ContentDiffException; 027import org.nuxeo.ecm.diff.content.adapter.factories.BlobHolderContentDiffAdapterFactory; 028import org.nuxeo.ecm.diff.content.adapter.factories.FileBasedContentDiffAdapterFactory; 029import org.nuxeo.runtime.model.ComponentInstance; 030import org.nuxeo.runtime.model.DefaultComponent; 031 032/** 033 * Runtime component that handles the extension points and the service interface for content diff Adapter management. 034 * 035 * @author Antoine Taillefer 036 */ 037public class ContentDiffAdapterManagerComponent extends DefaultComponent implements ContentDiffAdapterManager { 038 039 public static final String ADAPTER_FACTORY_EP = "adapterFactory"; 040 041 public static final String MIME_TYPE_CONTENT_DIFFER_EP = "mimeTypeContentDiffer"; 042 043 private static final Log log = LogFactory.getLog(ContentDiffAdapterManagerComponent.class); 044 045 protected Map<String, ContentDiffAdapterFactory> factoryRegistry = new HashMap<String, ContentDiffAdapterFactory>(); 046 047 protected Map<String, MimeTypeContentDiffer> contentDifferFactory = new HashMap<String, MimeTypeContentDiffer>(); 048 049 protected Map<String, MimeTypeContentDiffer> contentDifferFactoryByName = new HashMap<String, MimeTypeContentDiffer>(); 050 051 // Component and EP management 052 053 @Override 054 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 055 056 if (ADAPTER_FACTORY_EP.equals(extensionPoint)) { 057 ContentDiffAdapterFactoryDescriptor desc = (ContentDiffAdapterFactoryDescriptor) contribution; 058 if (desc.isEnabled()) { 059 ContentDiffAdapterFactory factory = desc.getNewInstance(); 060 if (factory != null) { 061 factoryRegistry.put(desc.getTypeName(), factory); 062 } 063 } else { 064 factoryRegistry.remove(desc.getTypeName()); 065 } 066 } else if (MIME_TYPE_CONTENT_DIFFER_EP.equals(extensionPoint)) { 067 MimeTypeContentDifferDescriptor desc = (MimeTypeContentDifferDescriptor) contribution; 068 try { 069 MimeTypeContentDiffer contentDiffer = desc.getKlass().newInstance(); 070 contentDifferFactory.put(desc.getPattern(), contentDiffer); 071 072 // Also (since 7.4) add a name in the contribution 073 String name = desc.getName(); 074 if (StringUtils.isNotBlank(name)) { 075 contentDifferFactoryByName.put(name, contentDiffer); 076 } 077 } catch (ReflectiveOperationException e) { 078 throw new RuntimeException(e); 079 } 080 } 081 } 082 083 @Override 084 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 085 } 086 087 // Service interface impl 088 089 @Override 090 public boolean hasAdapter(DocumentModel doc) { 091 if (doc == null) { 092 return false; 093 } 094 095 String docType = doc.getType(); 096 if (factoryRegistry.containsKey(docType)) { 097 return true; 098 } 099 100 return doc.hasSchema("file") || doc.hasSchema("files"); 101 } 102 103 @Override 104 public ContentDiffAdapter getAdapter(DocumentModel doc) { 105 if (doc == null) { 106 return null; 107 } 108 109 String docType = doc.getType(); 110 111 log.debug("Looking for ContentDiffAdapter for type " + docType); 112 113 if (factoryRegistry.containsKey(docType)) { 114 log.debug("Dedicated ContentDiffAdapter factory found"); 115 return factoryRegistry.get(docType).getAdapter(doc); 116 } 117 118 if (doc.isFolder()) { 119 return null; 120 } 121 122 BlobHolder bh = doc.getAdapter(BlobHolder.class); 123 if (bh != null) { 124 log.debug("Using Blob Holder based ContentDiffAdapter factory"); 125 ContentDiffAdapterFactory factory = new BlobHolderContentDiffAdapterFactory(); 126 return factory.getAdapter(doc); 127 128 } 129 130 if (doc.hasSchema("file") || doc.hasSchema("files")) { 131 log.debug("Using default file based ContentDiffAdapter factory"); 132 ContentDiffAdapterFactory factory = new FileBasedContentDiffAdapterFactory(); 133 return factory.getAdapter(doc); 134 } else { 135 return null; 136 } 137 } 138 139 @Override 140 public MimeTypeContentDiffer getContentDiffer(String mimeType) { 141 for (Map.Entry<String, MimeTypeContentDiffer> entry : contentDifferFactory.entrySet()) { 142 if (mimeType.matches(entry.getKey())) { 143 return entry.getValue(); 144 } 145 } 146 return null; 147 } 148 149 @Override 150 public MimeTypeContentDiffer getContentDifferForName(String name) { 151 for (Map.Entry<String, MimeTypeContentDiffer> entry : contentDifferFactoryByName.entrySet()) { 152 if (name.equals(entry.getKey())) { 153 return entry.getValue(); 154 } 155 } 156 return null; 157 } 158 159 @Override 160 public HtmlContentDiffer getHtmlContentDiffer() throws ContentDiffException { 161 MimeTypeContentDiffer htmlContentDiffer = contentDifferFactory.get("text/html"); 162 if (htmlContentDiffer == null || !(htmlContentDiffer instanceof HtmlContentDiffer)) { 163 throw new ContentDiffException( 164 "No content differ of type HtmlContentDiffer found for the 'text/html' mime-type. Please check the 'mimeTypeContentDiffer' contributions."); 165 } 166 return (HtmlContentDiffer) htmlContentDiffer; 167 } 168 169}