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