/*
* Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Florent Guillaume
*/
package org.eclipse.ecr.convert.service;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.ecr.convert.api.ConversionException;
import org.eclipse.ecr.convert.api.ConversionService;
import org.eclipse.ecr.convert.api.ConverterCheckResult;
import org.eclipse.ecr.convert.api.ConverterNotAvailable;
import org.eclipse.ecr.convert.api.ConverterNotRegistered;
import org.eclipse.ecr.convert.cache.CacheKeyGenerator;
import org.eclipse.ecr.convert.cache.ConversionCacheHolder;
import org.eclipse.ecr.convert.extension.Converter;
import org.eclipse.ecr.convert.extension.ConverterDescriptor;
import org.eclipse.ecr.convert.extension.ExternalConverter;
import org.eclipse.ecr.convert.extension.GlobalConfigDescriptor;
import org.eclipse.ecr.core.api.ClientException;
import org.eclipse.ecr.core.api.blobholder.BlobHolder;
import org.eclipse.ecr.runtime.model.ComponentInstance;
import org.eclipse.ecr.runtime.model.DefaultComponent;
/**
* Runtime Component that also provides the POJO implementation of the
* {@link ConversionService}.
*
* @author tiry
*/
public class ConversionServiceImpl extends DefaultComponent implements
ConversionService {
private static final Log log = LogFactory.getLog(ConversionServiceImpl.class);
public static final String CONVERTER_EP = "converter";
public static final String CONFIG_EP = "configuration";
protected static final Map<String, ConverterDescriptor> converterDescriptors
= new HashMap<String, ConverterDescriptor>();
protected static final GlobalConfigDescriptor config = new GlobalConfigDescriptor();
/**
* Component implementation.
*/
@Override
public void registerContribution(Object contribution,
String extensionPoint, ComponentInstance contributor)
throws Exception {
if (CONVERTER_EP.equals(extensionPoint)) {
ConverterDescriptor desc = (ConverterDescriptor) contribution;
registerConverter(desc);
} else if (CONFIG_EP.equals(extensionPoint)) {
GlobalConfigDescriptor desc = (GlobalConfigDescriptor) contribution;
config.update(desc);
} else {
log.error("Unable to handle unknown extensionPoint "
+ extensionPoint);
}
}
@Override
public void unregisterContribution(Object contribution,
String extensionPoint, ComponentInstance contributor)
throws Exception {
}
/* Component API */
public static Converter getConverter(String converterName) {
ConverterDescriptor desc = converterDescriptors.get(converterName);
if (desc == null) {
return null;
}
return desc.getConverterInstance();
}
public static ConverterDescriptor getConverterDescriptor(String converterName) {
return converterDescriptors.get(converterName);
}
public static long getGCIntervalInMinutes() {
return config.getGCInterval();
}
public static void registerConverter(ConverterDescriptor desc) {
if (converterDescriptors.containsKey(desc.getConverterName())) {
ConverterDescriptor existing = converterDescriptors.get(
desc.getConverterName());
desc = existing.merge(desc);
}
try {
desc.initConverter();
} catch (Exception e) {
log.error("Unable to init converter " + desc.getConverterName(), e);
return;
}
MimeTypeTranslationHelper.addConverter(desc);
converterDescriptors.put(desc.getConverterName(), desc);
}
public static int getMaxCacheSizeInKB() {
return config.getDiskCacheSize();
}
public static boolean isCacheEnabled() {
return config.isCacheEnabled();
}
public static String getCacheBasePath() {
return config.getCachingDirectory();
}
/* Service API */
@Override
public List<String> getRegistredConverters() {
List<String> converterNames = new ArrayList<String>();
converterNames.addAll(converterDescriptors.keySet());
return converterNames;
}
@Override
public BlobHolder convert(String converterName, BlobHolder blobHolder,
Map<String, Serializable> parameters) throws ConversionException {
// exist if not registered
ConverterCheckResult check = isConverterAvailable(converterName);
if (!check.isAvailable()) {
// exist is not installed / configured
throw new ConverterNotAvailable(converterName);
}
ConverterDescriptor desc = converterDescriptors.get(converterName);
if (desc == null) {
throw new ConversionException("Converter " + converterName
+ " can not be found");
}
String cacheKey = CacheKeyGenerator.computeKey(converterName,
blobHolder, parameters);
BlobHolder cachedResult = ConversionCacheHolder.getFromCache(cacheKey);
if (cachedResult != null) {
return cachedResult;
} else {
Converter converter = desc.getConverterInstance();
BlobHolder result = converter.convert(blobHolder, parameters);
if (config.isCacheEnabled()) {
ConversionCacheHolder.addToCache(cacheKey, result);
}
return result;
}
}
@Override
public BlobHolder convertToMimeType(String destinationMimeType,
BlobHolder blobHolder, Map<String, Serializable> parameters)
throws ConversionException {
String converterName;
try {
String srcMt = blobHolder.getBlob().getMimeType();
converterName = MimeTypeTranslationHelper.getConverterName(srcMt,
destinationMimeType);
} catch (ClientException e) {
throw new ConversionException(
"error while trying to determine converter name", e);
}
if (converterName == null) {
throw new ConversionException(
"unable to find converter for target mime type");
}
return convert(converterName, blobHolder, parameters);
}
@Override
public List<String> getConverterNames(String sourceMimeType, String destinationMimeType) {
return MimeTypeTranslationHelper.getConverterNames(sourceMimeType,
destinationMimeType);
}
@Override
public String getConverterName(String sourceMimeType,
String destinationMimeType) {
List<String> converterNames = getConverterNames(sourceMimeType, destinationMimeType);
if (!converterNames.isEmpty()) {
return converterNames.get(converterNames.size() - 1);
}
return null;
}
@Override
public ConverterCheckResult isConverterAvailable(String converterName)
throws ConversionException {
return isConverterAvailable(converterName, false);
}
protected final Map<String, ConverterCheckResult> checkResultCache
= new HashMap<String, ConverterCheckResult>();
@Override
public ConverterCheckResult isConverterAvailable(String converterName,
boolean refresh) throws ConversionException {
if (!refresh) {
if (checkResultCache.containsKey(converterName)) {
return checkResultCache.get(converterName);
}
}
ConverterDescriptor descriptor = converterDescriptors.get(converterName);
if (descriptor == null) {
throw new ConverterNotRegistered(converterName);
}
Converter converter = descriptor.getConverterInstance();
ConverterCheckResult result;
if (converter instanceof ExternalConverter) {
ExternalConverter exConverter = (ExternalConverter) converter;
result = exConverter.isConverterAvailable();
} else {
// return success since there is nothing to test
result = new ConverterCheckResult();
}
result.setSupportedInputMimeTypes(descriptor.getSourceMimeTypes());
checkResultCache.put(converterName, result);
return result;
}
}