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-2.1.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 * Dragos Mihalache 016 */ 017package org.nuxeo.ecm.core.uidgen; 018 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.Map; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.nuxeo.ecm.core.api.DocumentModel; 026import org.nuxeo.ecm.core.api.model.PropertyNotFoundException; 027import org.nuxeo.ecm.core.uidgen.UIDGenerator; 028import org.nuxeo.ecm.core.uidgen.UIDSequencer; 029import org.nuxeo.runtime.api.Framework; 030import org.nuxeo.runtime.model.ComponentContext; 031import org.nuxeo.runtime.model.DefaultComponent; 032import org.nuxeo.runtime.model.Extension; 033 034/** 035 * Service that writes MetaData. 036 */ 037public class UIDGeneratorComponent extends DefaultComponent implements UIDGeneratorService { 038 039 public static final String ID = "org.nuxeo.ecm.core.uidgen.UIDGeneratorService"; 040 041 public static final String UID_GENERATORS_EXTENSION_POINT = "generators"; 042 043 public static final String SEQUENCERS_EXTENSION_POINT = "sequencers"; 044 045 /** 046 * Extension point is deprecated should be removed - preserved for now only for startup warnings. 047 */ 048 public static final String EXTENSION_POINT_SEQUENCER_FACTORY = "sequencerFactory"; 049 050 private static final Log log = LogFactory.getLog(UIDGeneratorComponent.class); 051 052 protected final Map<String, UIDGenerator> generators = new HashMap<String, UIDGenerator>(); 053 054 protected final Map<String, UIDSequencer> sequencers = new HashMap<String, UIDSequencer>(); 055 056 protected final LinkedHashMap<String, UIDSequencerProviderDescriptor> sequencerContribs = new LinkedHashMap<String, UIDSequencerProviderDescriptor>(); 057 058 protected String defaultSequencer; 059 060 @Override 061 public void activate(ComponentContext context) { 062 for (String name : sequencers.keySet()) { 063 sequencers.get(name).init(); 064 } 065 super.activate(context); 066 } 067 068 @Override 069 public void deactivate(ComponentContext context) { 070 for (String name : sequencers.keySet()) { 071 sequencers.get(name).dispose(); 072 } 073 super.deactivate(context); 074 } 075 076 @Override 077 public void registerExtension(Extension extension) { 078 super.registerExtension(extension); 079 final String extPoint = extension.getExtensionPoint(); 080 if (UID_GENERATORS_EXTENSION_POINT.equals(extPoint)) { 081 log.info("register contributions for extension point: " + UID_GENERATORS_EXTENSION_POINT); 082 final Object[] contribs = extension.getContributions(); 083 registerGenerators(extension, contribs); 084 } else if (SEQUENCERS_EXTENSION_POINT.equals(extPoint)) { 085 log.info("register contributions for extension point: " + SEQUENCERS_EXTENSION_POINT); 086 final Object[] contribs = extension.getContributions(); 087 registerSequencers(extension, contribs); 088 computeDefault(); 089 } else if (EXTENSION_POINT_SEQUENCER_FACTORY.equals(extPoint)) { 090 String msg = "UIDSequencer factory no more supported from version 5.4. Faulty component: " 091 + extension.getComponent(); 092 Framework.getRuntime().getWarnings().add(msg); 093 log.error(msg); 094 } else { 095 log.warn("extension not handled: " + extPoint); 096 } 097 } 098 099 @Override 100 public void unregisterExtension(Extension extension) { 101 final String extPoint = extension.getExtensionPoint(); 102 if (UID_GENERATORS_EXTENSION_POINT.equals(extPoint)) { 103 log.info("unregister contributions for extension point: " + UID_GENERATORS_EXTENSION_POINT); 104 // final Object[] contribs = extension.getContributions(); 105 // unregisterGenerators(extension, contribs); 106 } else if (SEQUENCERS_EXTENSION_POINT.equals(extPoint)) { 107 log.info("unregister contributions for extension point: " + SEQUENCERS_EXTENSION_POINT); 108 final Object[] contribs = extension.getContributions(); 109 unregisterSequencers(extension, contribs); 110 computeDefault(); 111 } else { 112 log.warn("extension not handled: " + extPoint); 113 } 114 super.unregisterExtension(extension); 115 } 116 117 protected void computeDefault() { 118 String def = null; 119 String last = null; 120 for (UIDSequencerProviderDescriptor contrib : sequencerContribs.values()) { 121 if (contrib.isIsdefault()) { 122 def = contrib.getName(); 123 } 124 last = contrib.getName(); 125 } 126 127 if (def == null) { 128 def = last; 129 } 130 defaultSequencer = def; 131 } 132 133 protected void registerSequencers(Extension extension, final Object[] contribs) { 134 for (Object contrib : contribs) { 135 UIDSequencerProviderDescriptor seqDescriptor = (UIDSequencerProviderDescriptor) contrib; 136 String name = seqDescriptor.getName(); 137 138 try { 139 UIDSequencer seq = seqDescriptor.getSequencer(); 140 if (seq != null) { 141 seq.setName(name); 142 } 143 sequencers.put(name, seq); 144 sequencerContribs.put(name, seqDescriptor); 145 } catch (Exception e) { 146 log.error("Unable to create UIDSequencer with name " + name, e); 147 } 148 } 149 } 150 151 protected void unregisterSequencers(Extension extension, final Object[] contribs) { 152 for (Object contrib : contribs) { 153 UIDSequencerProviderDescriptor seqDescriptor = (UIDSequencerProviderDescriptor) contrib; 154 String name = seqDescriptor.getName(); 155 sequencers.remove(name); 156 sequencerContribs.remove(name); 157 } 158 } 159 160 protected void registerGenerators(Extension extension, final Object[] contribs) { 161 162 // read the list of generators 163 for (Object contrib : contribs) { 164 final UIDGeneratorDescriptor generatorDescriptor = (UIDGeneratorDescriptor) contrib; 165 final String generatorName = generatorDescriptor.getName(); 166 167 UIDGenerator generator; 168 try { 169 generator = (UIDGenerator) extension.getContext().loadClass(generatorDescriptor.getClassName()).newInstance(); 170 } catch (ReflectiveOperationException e) { 171 throw new RuntimeException(e); 172 } 173 174 final String[] propNames = generatorDescriptor.getPropertyNames(); 175 if (propNames.length == 0) { 176 log.error("no property name defined on generator " + generatorName); 177 } 178 // set the property name on generator 179 generator.setPropertyNames(propNames); 180 181 // Register Generator for DocTypes and property name 182 final String[] docTypes = generatorDescriptor.getDocTypes(); 183 registerGeneratorForDocTypes(generator, docTypes); 184 185 log.info("registered UID generator: " + generatorName); 186 } 187 } 188 189 /** 190 * Registers given UIDGenerator for the given document types. If there is already a generator registered for one of 191 * document type it will be discarded (and replaced with the new generator). 192 */ 193 private void registerGeneratorForDocTypes(final UIDGenerator generator, final String[] docTypes) { 194 195 for (String docType : docTypes) { 196 final UIDGenerator previous = generators.put(docType, generator); 197 if (previous != null) { 198 log.info("Overwriting generator: " + previous.getClass() + " for docType: " + docType); 199 } 200 log.info("Registered generator: " + generator.getClass() + " for docType: " + docType); 201 } 202 } 203 204 /** 205 * Returns the uid generator to use for this document. 206 * <p> 207 * Choice is made following the document type and the generator configuration. 208 */ 209 @Override 210 public UIDGenerator getUIDGeneratorFor(DocumentModel doc) { 211 final String docTypeName = doc.getType(); 212 final UIDGenerator generator = generators.get(docTypeName); 213 214 if (generator == null) { 215 log.debug("No UID Generator defined for doc type: " + docTypeName); 216 return null; 217 } 218 // TODO maybe maintain an initialization state for generators 219 // so the next call could be avoided (for each request) 220 generator.setSequencer(Framework.getService(UIDSequencer.class)); 221 222 return generator; 223 } 224 225 /** 226 * Creates a new UID for the given doc and sets the field configured in the generator component with this value. 227 */ 228 @Override 229 public void setUID(DocumentModel doc) throws PropertyNotFoundException { 230 final UIDGenerator generator = getUIDGeneratorFor(doc); 231 if (generator != null) { 232 generator.setUID(doc); 233 } 234 } 235 236 /** 237 * @return a new UID for the given document 238 */ 239 @Override 240 public String createUID(DocumentModel doc) { 241 final UIDGenerator generator = getUIDGeneratorFor(doc); 242 if (generator == null) { 243 return null; 244 } else { 245 return generator.createUID(doc); 246 } 247 } 248 249 @Override 250 public <T> T getAdapter(Class<T> adapter) { 251 if (UIDSequencer.class.isAssignableFrom(adapter)) { 252 return adapter.cast(getSequencer()); 253 } 254 if (UIDGeneratorService.class.isAssignableFrom(adapter)) { 255 return adapter.cast(this); 256 } 257 return null; 258 } 259 260 @Override 261 public UIDSequencer getSequencer() { 262 return getSequencer(null); 263 } 264 265 @Override 266 public UIDSequencer getSequencer(String name) { 267 if (name == null) { 268 name = defaultSequencer; 269 } 270 return sequencers.get(name); 271 } 272 273}