/**
* Copyright (c) Codice Foundation
* <p/>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p/>
* 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
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.mime.mapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.activation.MimeType;
import javax.activation.MimeTypeParseException;
import org.apache.commons.lang.StringUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.mime.MimeTypeToTransformerMapper;
/**
* {@link MimeTypeToTransformerMapper} Implementation that finds mimeType matches among transformer
* services
*
* @author Ashraf Barakat
* @author ddf.isgs@lmco.com
*
*/
public class MimeTypeToTransformerMapperImpl implements MimeTypeToTransformerMapper {
private static final Logger LOGGER = LoggerFactory
.getLogger(MimeTypeToTransformerMapperImpl.class);
public MimeTypeToTransformerMapperImpl() {
}
protected BundleContext getContext() {
Bundle cxfBundle = FrameworkUtil.getBundle(MimeTypeToTransformerMapperImpl.class);
if (cxfBundle != null) {
return cxfBundle.getBundleContext();
}
return null;
}
@Override
public <T> List<T> findMatches(Class<T> clazz, MimeType userMimeType) {
BundleContext bundleContext = getContext();
ServiceReference[] refs = null;
List<T> list = new ArrayList<T>();
if (bundleContext == null) {
LOGGER.debug("Cannot find matches, bundle context is null.");
return list;
}
if (clazz == null) {
LOGGER.warn("Cannot find matches, service argument is null.");
throw new IllegalArgumentException("Invalid argument supplied, null service argument");
}
/*
* Extract the services using the bundle context.
*/
try {
refs = bundleContext.getServiceReferences(clazz.getName(), null);
} catch (InvalidSyntaxException e) {
LOGGER.warn("Invalid filter syntax ", e);
throw new IllegalArgumentException(
"Invalid syntax supplied: " + userMimeType.toString());
}
// If no InputTransformers found, return empty list
if (refs == null) {
LOGGER.debug("No {} services found - return empty list", clazz.getName());
return list;
}
/*
* Sort the list of service references based in it's Comparable interface.
*/
Arrays.sort(refs, Collections.reverseOrder());
/*
* If the mime type is null return the whole list of service references
*/
if (userMimeType == null) {
if (refs.length > 0) {
for (ServiceReference ref : refs) {
Object service = (bundleContext.getService(ref));
T typedService = clazz.cast(service);
list.add(typedService);
}
}
return list;
}
String userIdValue = userMimeType.getParameter(MimeTypeToTransformerMapper.ID_KEY);
List<T> strictlyMatching = new ArrayList<T>();
for (ServiceReference ref : refs) {
List<String> mimeTypesServicePropertyList = getServiceMimeTypesList(ref);
String serviceId = getServiceId(ref);
for (String mimeTypeRawEntry : mimeTypesServicePropertyList) {
MimeType mimeTypeEntry = constructMimeType(mimeTypeRawEntry);
if (mimeTypeEntry != null && StringUtils
.equals(mimeTypeEntry.getBaseType(), userMimeType.getBaseType()) && (
userIdValue == null || StringUtils.equals(userIdValue, serviceId))) {
try {
T service = clazz.cast(bundleContext.getService(ref));
strictlyMatching.add(service);
break; // found exact mimetype, no need to continue within
// the same service
} catch (ClassCastException cce) {
LOGGER.debug("Caught illegal cast to transformer type. ", cce);
}
}
}
}
return strictlyMatching;
}
private MimeType constructMimeType(String mimeTypeRawEntry) {
try {
return new MimeType(mimeTypeRawEntry);
} catch (MimeTypeParseException e) {
LOGGER.debug("MIME type parse exception constructing MIME type", e);
}
return null;
}
private List<String> getServiceMimeTypesList(ServiceReference ref) {
Object mimeTypeServiceProperty = ref.getProperty(MIME_TYPE_KEY);
if (mimeTypeServiceProperty != null) {
if (mimeTypeServiceProperty instanceof String) {
/*
* We cannot enforce how the property is given to us whether it is a list or a
* single property. This case catches the single mime-type property.
*/
return Arrays.asList(mimeTypeServiceProperty.toString());
}
return (List<String>) mimeTypeServiceProperty;
}
/*
* An empty list is returned, if the call to getProperty has returned with a null value.
*/
return new ArrayList<String>();
}
private String getServiceId(ServiceReference ref) {
Object idServiceProperty = ref.getProperty(ID_KEY);
if (idServiceProperty != null) {
return idServiceProperty.toString();
}
return null;
}
}