/* * * This is a simple Content Management System (CMS) * Copyright (C) 2009 Imran M Yousuf (imyousuf@smartitengineering.com) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.smartitengineering.cms.spi; import com.smartitengineering.cms.api.factory.write.PersistentWriter; import com.smartitengineering.cms.api.type.MutableContentType; import com.smartitengineering.cms.api.factory.SmartContentAPI; import com.smartitengineering.cms.spi.content.ContentSearcher; import com.smartitengineering.cms.spi.content.PersistentContentReader; import com.smartitengineering.cms.spi.content.RepresentationProvider; import com.smartitengineering.cms.spi.content.UriProvider; import com.smartitengineering.cms.spi.content.ValidatorProvider; import com.smartitengineering.cms.spi.content.VariationProvider; import com.smartitengineering.cms.spi.lock.LockHandler; import com.smartitengineering.cms.spi.persistence.PersistableDomainFactory; import com.smartitengineering.cms.spi.persistence.PersistentService; import com.smartitengineering.cms.spi.persistence.PersistentServiceRegistrar; import com.smartitengineering.cms.spi.type.ContentTypeDefinitionParsers; import com.smartitengineering.cms.spi.type.ContentTypeSearcher; import com.smartitengineering.cms.spi.type.PersistentContentTypeReader; import com.smartitengineering.cms.spi.type.SearchFieldNameGenerator; import com.smartitengineering.cms.spi.type.TypeValidators; import com.smartitengineering.cms.spi.workspace.WorkspaceService; import com.smartitengineering.util.bean.BeanFactoryRegistrar; import com.smartitengineering.util.bean.annotations.Aggregator; import com.smartitengineering.util.bean.annotations.InjectableField; import java.util.concurrent.Semaphore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * All SPI collection for SPI implementations. * */ @Aggregator(contextName = SmartContentSPI.SPI_CONTEXT) public final class SmartContentSPI { public static final String SPI_CONTEXT = SmartContentAPI.CONTEXT_NAME + ".spi"; private static final Logger LOGGER = LoggerFactory.getLogger(SmartContentSPI.class); /** * The lock handler implementation to be used to receive lock implementations. * Use <tt>lockHandler</tt> as bean name to be injected here. */ @InjectableField protected LockHandler lockHandler; /** * The type validator implementation which validatates a content type * definition file source. Use <tt>typeValidator</tt> as the bean name in * bean factory to be injected here. */ @InjectableField protected TypeValidators typeValidators; @InjectableField protected RepresentationProvider representationProvider; @InjectableField protected VariationProvider variationProvider; @InjectableField protected ValidatorProvider validatorProvider; @InjectableField private SearchFieldNameGenerator searchFieldNameGenerator; /** * The registrar for aggregating different implementations of * {@link PersistentService} for diffent domain types. Use the bean name * <tt>persistentServiceRegistrar</tt> for injecting it here. */ @InjectableField protected PersistentServiceRegistrar persistentServiceRegistrar; @InjectableField private ContentTypeDefinitionParsers contentTypeDefinitionParsers; @InjectableField private PersistentContentTypeReader contentTypeReader; @InjectableField private PersistentContentReader contentReader; @InjectableField private WorkspaceService workspaceService; @InjectableField private PersistableDomainFactory persistableDomainFactory; @InjectableField(beanName = "schemaLocationForContentTypeXml") private String schemaLocationForContentTypeXml; @InjectableField private ContentSearcher contentSearcher; @InjectableField private ContentTypeSearcher contentTypeSearcher; @InjectableField private UriProvider uriProvider; public UriProvider getUriProvider() { return uriProvider; } public ValidatorProvider getValidatorProvider() { return validatorProvider; } public ContentSearcher getContentSearcher() { return contentSearcher; } public ContentTypeSearcher getContentTypeSearcher() { return contentTypeSearcher; } public String getSchemaLocationForContentTypeXml() { return schemaLocationForContentTypeXml; } public PersistableDomainFactory getPersistableDomainFactory() { return persistableDomainFactory; } public WorkspaceService getWorkspaceService() { return workspaceService; } public PersistentContentReader getContentReader() { return contentReader; } public PersistentContentTypeReader getContentTypeReader() { return contentTypeReader; } public ContentTypeDefinitionParsers getContentTypeDefinitionParsers() { return contentTypeDefinitionParsers; } public PersistentServiceRegistrar getPersistentServiceRegistrar() { return persistentServiceRegistrar; } /** * An operation for retrieving the concrete implementation of persistent * service implementaion for the given persistable API bean. * @param <T> Should represent the class to be used in concrete SPI * implementations. For example, {@link MutableContentType} * @param writerClass The class to look for in the registrar. * @return Service for persisting the bean. * @see PersistentServiceRegistrar#getPersistentService(java.lang.Class) */ public <T extends PersistentWriter> PersistentService<T> getPersistentService(Class<T> writerClass) { final PersistentServiceRegistrar registrar = getPersistentServiceRegistrar(); if (registrar == null) { return null; } return registrar.getPersistentService(writerClass); } public SearchFieldNameGenerator getSearchFieldNameGenerator() { return searchFieldNameGenerator; } public TypeValidators getTypeValidators() { return typeValidators; } public LockHandler getLockHandler() { return lockHandler; } public RepresentationProvider getRepresentationProvider() { return representationProvider; } public VariationProvider getVariationProvider() { return variationProvider; } private SmartContentSPI() { } private static SmartContentSPI spi; private static final Semaphore MUTEX = new Semaphore(1); public static SmartContentSPI getInstance() { if (spi == null) { try { MUTEX.acquire(); } catch (Exception ex) { return null; } try { if (spi == null) { spi = new SmartContentSPI(); if (LOGGER.isInfoEnabled()) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); final StringBuilder builder = new StringBuilder(); for (StackTraceElement traceElement : stack) { builder.append(traceElement.getClassName()).append(':').append(traceElement.getMethodName()).append( ':').append(traceElement.getLineNumber()).append('\n'); } LOGGER.info(new StringBuilder("Initializing Smart Content SPI:\n").append(builder.toString()).toString()); } BeanFactoryRegistrar.aggregate(spi); } } finally { MUTEX.release(); } } return spi; } }