001/* 002 * (C) Copyright 2008 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 * Nuxeo - initial API and implementation 016 * 017 * $Id: IndexingAdapterService.java 31426 2008-04-09 17:00:34Z ogrisel $ 018 */ 019 020package org.nuxeo.ecm.platform.indexing.gateway.adapter; 021 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.HashMap; 025import java.util.LinkedList; 026import java.util.List; 027import java.util.Map; 028 029import org.nuxeo.ecm.core.api.CoreSession; 030import org.nuxeo.ecm.platform.api.ws.DocumentBlob; 031import org.nuxeo.ecm.platform.api.ws.DocumentDescriptor; 032import org.nuxeo.ecm.platform.api.ws.DocumentProperty; 033import org.nuxeo.ecm.platform.api.ws.WsACE; 034import org.nuxeo.runtime.RuntimeServiceException; 035import org.nuxeo.runtime.model.ComponentInstance; 036import org.nuxeo.runtime.model.DefaultComponent; 037 038/** 039 * Service to allow client code to register converters for the datastructures served to the Sinequa Intuition to be 040 * indexed. This is especially useful to be able to index Access Control Policy after some post-processing since the ACL 041 * model of Intuition is not as expressive as the Nuxeo Core security model. 042 * 043 * @author Olivier Grisel <ogrisel@nuxeo.com> 044 */ 045public class IndexingAdapterService extends DefaultComponent implements IndexingAdapter { 046 047 public static final String INTUITION_ADAPTER_XP = "adapters"; 048 049 public static final String BLOB_FORMAT_XP = "blobFormat"; 050 051 protected final List<IndexingAdapterDescriptor> registeredAdapters = new LinkedList<IndexingAdapterDescriptor>(); 052 053 protected final List<IndexingAdapter> mergedAdapters = new LinkedList<IndexingAdapter>(); 054 055 protected boolean useDownloadUrl = true; 056 057 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 058 if (INTUITION_ADAPTER_XP.equals(extensionPoint)) { 059 mergedAdapters.clear(); // invalidate merged contributions 060 IndexingAdapterDescriptor descriptor = (IndexingAdapterDescriptor) contribution; 061 if (descriptor.isEnabled()) { 062 // do not try to instantiate classes to be disabled by the 063 // contribution 064 IndexingAdapter adapterInstance; 065 try { 066 adapterInstance = (IndexingAdapter) contributor.getContext().loadClass(descriptor.getClassName()).newInstance(); 067 } catch (ReflectiveOperationException e) { 068 throw new RuntimeException(e); 069 } 070 descriptor.setAdapterInstance(adapterInstance); 071 } 072 registeredAdapters.add(descriptor); 073 } else if (BLOB_FORMAT_XP.equals(extensionPoint)) { 074 BlobFormatDescriptor desc = (BlobFormatDescriptor) contribution; 075 useDownloadUrl = desc.isUseDownloadUrl(); 076 } else { 077 throw new RuntimeServiceException("unsupported extension point: " + extensionPoint); 078 } 079 } 080 081 public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 082 if (INTUITION_ADAPTER_XP.equals(extensionPoint)) { 083 mergedAdapters.clear(); // invalidate merged contributions 084 IndexingAdapterDescriptor descriptor = (IndexingAdapterDescriptor) contribution; 085 registeredAdapters.remove(registeredAdapters.lastIndexOf(descriptor)); 086 087 } else { 088 throw new RuntimeServiceException("unsupported extension point: " + extensionPoint); 089 } 090 } 091 092 public DocumentDescriptor adaptDocumentDescriptor(CoreSession session, String uuid, DocumentDescriptor dd) 093 { 094 for (IndexingAdapter adapter : getMergedAdapters()) { 095 dd = adapter.adaptDocumentDescriptor(session, uuid, dd); 096 } 097 return dd; 098 } 099 100 public WsACE[] adaptDocumentACL(CoreSession session, String uuid, WsACE[] aces) { 101 for (IndexingAdapter adapter : getMergedAdapters()) { 102 aces = adapter.adaptDocumentACL(session, uuid, aces); 103 } 104 return aces; 105 } 106 107 public WsACE[] adaptDocumentLocalACL(CoreSession session, String uuid, WsACE[] aces) { 108 for (IndexingAdapter adapter : getMergedAdapters()) { 109 aces = adapter.adaptDocumentLocalACL(session, uuid, aces); 110 } 111 return aces; 112 } 113 114 public DocumentBlob[] adaptDocumentBlobs(CoreSession session, String uuid, DocumentBlob[] blobs) 115 { 116 for (IndexingAdapter adapter : getMergedAdapters()) { 117 blobs = adapter.adaptDocumentBlobs(session, uuid, blobs); 118 } 119 return blobs; 120 } 121 122 public DocumentProperty[] adaptDocumentNoBlobProperties(CoreSession session, String uuid, 123 DocumentProperty[] properties) { 124 for (IndexingAdapter adapter : getMergedAdapters()) { 125 properties = adapter.adaptDocumentNoBlobProperties(session, uuid, properties); 126 } 127 return properties; 128 } 129 130 public DocumentProperty[] adaptDocumentProperties(CoreSession session, String uuid, DocumentProperty[] properties) 131 { 132 for (IndexingAdapter adapter : getMergedAdapters()) { 133 properties = adapter.adaptDocumentProperties(session, uuid, properties); 134 } 135 return properties; 136 } 137 138 protected List<IndexingAdapter> getMergedAdapters() { 139 if (mergedAdapters.isEmpty()) { 140 synchronized (this) { 141 Map<String, IndexingAdapterDescriptor> descriptorByClass = new HashMap<String, IndexingAdapterDescriptor>(); 142 // merge registered contribution by class names 143 for (IndexingAdapterDescriptor descriptor : registeredAdapters) { 144 descriptorByClass.put(descriptor.getClassName(), descriptor); 145 } 146 147 // sort merge contributions by order 148 List<IndexingAdapterDescriptor> mergedDescriptors = new ArrayList<IndexingAdapterDescriptor>( 149 descriptorByClass.values()); 150 Collections.sort(mergedDescriptors); 151 152 // filter out disabled adapters and collect the instances of the 153 // remaining sorted contributions 154 for (IndexingAdapterDescriptor descriptor : mergedDescriptors) { 155 if (descriptor.isEnabled()) { 156 mergedAdapters.add(descriptor.getAdapterInstance()); 157 } 158 } 159 } 160 } 161 return mergedAdapters; 162 } 163 164 public boolean useDownloadUrlForBlob() { 165 return useDownloadUrl; 166 } 167}