/*
* (C) Copyright 2006-2007 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* Nuxeo - initial API and implementation
*
* $Id: DocumentViewCodecService.java 22535 2007-07-13 14:57:58Z atchertchian $
*/
package org.nuxeo.ecm.platform.url.service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.platform.url.api.DocumentView;
import org.nuxeo.ecm.platform.url.api.DocumentViewCodecManager;
import org.nuxeo.ecm.platform.url.codec.api.DocumentViewCodec;
import org.nuxeo.ecm.platform.url.codec.descriptor.DocumentViewCodecDescriptor;
import org.nuxeo.runtime.model.ComponentContext;
import org.nuxeo.runtime.model.ComponentInstance;
import org.nuxeo.runtime.model.DefaultComponent;
public class DocumentViewCodecService extends DefaultComponent implements DocumentViewCodecManager {
private static final long serialVersionUID = -4521897334653742494L;
private static final Log log = LogFactory.getLog(DocumentViewCodecService.class);
public static final String NAME = DocumentViewCodecService.class.getName();
public static final String CODECS_EXTENSION_POINT = "codecs";
protected String defaultCodecName;
protected final Map<String, DocumentViewCodecDescriptor> descriptors;
protected final Map<String, DocumentViewCodec> codecs;
public DocumentViewCodecService() {
descriptors = new ConcurrentHashMap<String, DocumentViewCodecDescriptor>();
codecs = new ConcurrentHashMap<String, DocumentViewCodec>();
}
@Override
public void deactivate(ComponentContext context) {
descriptors.clear();
codecs.clear();
}
@Override
@SuppressWarnings("unchecked")
public <T> T getAdapter(Class<T> adapter) {
if (adapter.isAssignableFrom(DocumentViewCodecManager.class)) {
return (T) this;
}
return null;
}
@Override
public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
if (CODECS_EXTENSION_POINT.equals(extensionPoint)) {
DocumentViewCodecDescriptor desc = (DocumentViewCodecDescriptor) contribution;
String codecName = desc.getName();
if (desc.getDefaultCodec()) {
defaultCodecName = codecName;
}
// try to instantiate it
String className = desc.getClassName();
if (className == null) {
throw new IllegalArgumentException(
String.format("Invalid class for codec '%s': check ERROR logs" + " at startup", codecName));
}
DocumentViewCodec codec;
try {
// Thread context loader is not working in isolated EARs
codec = (DocumentViewCodec) DocumentViewCodecManager.class.getClassLoader()
.loadClass(className)
.newInstance();
} catch (ReflectiveOperationException e) {
String msg = String.format("Caught error when instantiating codec '%s' with " + "class '%s' ",
codecName, className);
throw new IllegalArgumentException(msg, e);
}
String prefix = desc.getPrefix();
if (prefix != null) {
codec.setPrefix(prefix);
}
if (!descriptors.containsKey(codecName) || desc.getPriority() > descriptors.get(codecName).getPriority()) {
descriptors.put(codecName, desc);
codecs.put(codecName, codec);
}
log.debug("Added URL codec: " + codecName);
}
}
@Override
public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
if (CODECS_EXTENSION_POINT.equals(extensionPoint)) {
DocumentViewCodecDescriptor codecDesc = (DocumentViewCodecDescriptor) contribution;
String codecName = codecDesc.getName();
descriptors.remove(codecName);
codecs.remove(codecName);
log.debug("Removed URL codec: " + codecName);
}
}
public List<String> getDocumentViewCodecDescriptorNames() {
List<String> lst = new ArrayList<String>();
for (String k : descriptors.keySet()) {
if (descriptors.get(k).getEnabled()) {
lst.add(k);
}
}
return lst;
}
@Override
public String getDefaultCodecName() {
String name = defaultCodecName;
if (name == null) {
// take first one
List<String> descs = getDocumentViewCodecDescriptorNames();
if (descs != null && !descs.isEmpty()) {
Collections.sort(descs);
name = descs.get(0);
}
}
return name;
}
public DocumentViewCodec getCodec() {
return getCodec(defaultCodecName);
}
@Override
public DocumentViewCodec getCodec(String codecName) {
if (StringUtils.isBlank(codecName)) {
return null;
}
return codecs.get(codecName);
}
@Override
public String getUrlFromDocumentView(DocumentView docView, boolean needBaseUrl, String baseUrl) {
String url = null;
DocumentViewCodec codec = getCodec(getDefaultCodecName());
if (codec != null && codec.handleDocumentView(docView)) {
url = getUrlFromDocumentView(codec, docView, needBaseUrl, baseUrl);
}
if (url == null) {
for (String codecName : descriptors.keySet()) {
if (!codecName.equals(defaultCodecName)) {
codec = getCodec(codecName);
if (codec != null && codec.handleDocumentView(docView)) {
url = getUrlFromDocumentView(codec, docView, needBaseUrl, baseUrl);
if (url != null) {
break;
}
}
}
}
}
return url;
}
@Override
public String getUrlFromDocumentView(String codecName, DocumentView docView, boolean needBaseUrl, String baseUrl) {
DocumentViewCodec codec = getCodec(codecName);
return getUrlFromDocumentView(codec, docView, needBaseUrl, baseUrl);
}
protected String getUrlFromDocumentView(DocumentViewCodec codec, DocumentView docView, boolean needBaseUrl,
String baseUrl) {
if (codec != null) {
String partialUrl = codec.getUrlFromDocumentView(docView);
if (partialUrl != null) {
if (needBaseUrl && !StringUtils.isBlank(baseUrl)) {
if (baseUrl.endsWith("/") || partialUrl.startsWith("/")) {
return baseUrl + partialUrl;
} else {
return baseUrl + "/" + partialUrl;
}
} else {
return partialUrl;
}
}
}
return null;
}
@Override
public DocumentView getDocumentViewFromUrl(String url, boolean hasBaseUrl, String baseUrl) {
DocumentView docView = null;
String finalUrl = getUrlWithoutBase(url, hasBaseUrl, baseUrl);
DocumentViewCodec codec = getCodec(getDefaultCodecName());
if (codec != null && codec.handleUrl(finalUrl)) {
docView = getDocumentViewFromUrl(codec, finalUrl);
}
if (docView == null) {
for (String codecName : descriptors.keySet()) {
if (!codecName.equals(defaultCodecName)) {
codec = getCodec(codecName);
if (codec != null && codec.handleUrl(finalUrl)) {
docView = getDocumentViewFromUrl(codec, finalUrl);
if (docView != null) {
break;
}
}
}
}
}
return docView;
}
@Override
public DocumentView getDocumentViewFromUrl(String codecName, String url, boolean hasBaseUrl, String baseUrl) {
DocumentViewCodec codec = getCodec(codecName);
String finalUrl = getUrlWithoutBase(url, hasBaseUrl, baseUrl);
return getDocumentViewFromUrl(codec, finalUrl);
}
protected String getUrlWithoutBase(String url, boolean hasBaseUrl, String baseUrl) {
if (hasBaseUrl && baseUrl != null) {
if (url.startsWith(baseUrl)) {
url = url.substring(baseUrl.length());
}
}
return url;
}
protected DocumentView getDocumentViewFromUrl(DocumentViewCodec codec, String finalUrl) {
if (codec != null) {
DocumentView docView = codec.getDocumentViewFromUrl(finalUrl);
return docView;
}
return null;
}
}