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