blob: fca8187cb85a6a98ab4fc35d0f4151f4c8be4eb7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.marmotta.platform.ldp.util;
import info.aduna.iteration.CloseableIteration;
import info.aduna.lang.FileFormat;
import org.apache.commons.lang3.StringUtils;
import org.apache.marmotta.commons.vocabulary.LDP;
import org.apache.marmotta.commons.vocabulary.XSD;
import org.apache.marmotta.platform.ldp.api.LdpService;
import org.apache.marmotta.platform.ldp.api.Preference;
import org.apache.marmotta.platform.ldp.webservices.PreferHeader;
import org.apache.tika.mime.MimeTypeException;
import org.apache.tika.mime.MimeTypes;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import org.openrdf.model.vocabulary.DCTERMS;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.repository.RepositoryException;
import org.openrdf.rio.*;
import org.slf4j.Logger;
import javax.ws.rs.core.MediaType;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Various Util-Methods for the {@link org.apache.marmotta.platform.ldp.api.LdpService}.
*/
public class LdpUtils {
private static Logger log = org.slf4j.LoggerFactory.getLogger(LdpUtils.class);
/**
* Urify the Slug: header value, i.e. replace all non-url chars with a single dash.
*
* @param slugHeaderValue the client-provided Slug-header
* @return the slugHeaderValue "urified"
*/
public static String urify(String slugHeaderValue) {
return slugHeaderValue.trim()
// Replace non-url chars with '-'
.replaceAll("[^\\w]+", "-");
}
/**
* Get the preferred file extension for the content type
*
* @param mediaType content type
* @return file extension (already including '.')
*/
public static String getExtension(MediaType mediaType) {
String contentType = getMimeType(mediaType);
return getExtension(contentType);
}
/**
* Get the preferred file extension for the content type
*
* @param mimeType mimeType
* @return file extension (already including '.')
*/
public static String getExtension(String mimeType) {
final String defaultExt = ".bin";
final MimeTypes allTypes = MimeTypes.getDefaultMimeTypes();
try {
final String ext = allTypes.forName(mimeType).getExtension();
log.trace("Tika's file-extension for {} is '{}'", mimeType, ext);
if (StringUtils.isNotBlank(ext)) {
return ext;
}
} catch (MimeTypeException e) {
log.trace("MimeTypeException: {}. Not critical, recovering...", e.getMessage());
}
log.trace("Using fallback file-extension '{}' for {}", defaultExt, mimeType);
return defaultExt;
}
/**
* Get <b>only</b> the mimeType from the {@link javax.ws.rs.core.MediaType}
*
* @param mediaType the mediaType
* @return the mimeType
*/
public static String getMimeType(MediaType mediaType) {
return (mediaType != null ? String.format("%s/%s", mediaType.getType(), mediaType.getSubtype()) : "");
}
/**
* LDP-Style to serialize a resource.
*
* @param writer the writer to serialize to
* @param subject the resource to serialize
* @param iteration the Iteration containing the data
* @throws RDFHandlerException
* @throws RepositoryException
*/
public static void exportIteration(RDFWriter writer, URI subject, CloseableIteration<Statement, RepositoryException> iteration) throws RDFHandlerException, RepositoryException {
writer.startRDF();
writer.handleNamespace(LDP.PREFIX, LDP.NAMESPACE);
writer.handleNamespace(RDF.PREFIX, RDF.NAMESPACE);
writer.handleNamespace(XSD.PREFIX, XSD.NAMESPACE);
writer.handleNamespace(DCTERMS.PREFIX, DCTERMS.NAMESPACE);
writer.handleNamespace("parent", subject.getNamespace());
writer.handleNamespace("child", subject.stringValue().replaceFirst("/*$", "/"));
writer.handleNamespace("this", subject.stringValue().replaceFirst("/*$", "#"));
while (iteration.hasNext()) {
writer.handleStatement(iteration.next());
}
writer.endRDF();
}
public static String getAcceptPostHeader(String extraFormats) {
final Collection<RDFFormat> rdfFormats = filterAvailableParsers(LdpService.SERVER_PREFERED_RDF_FORMATS);
final StringBuilder sb = new StringBuilder();
for (RDFFormat rdfFormat : rdfFormats) {
sb.append(rdfFormat.getDefaultMIMEType());
sb.append(", ");
}
if (StringUtils.isNotBlank(extraFormats)) {
sb.append(extraFormats);
} else {
sb.delete(sb.length()-2, sb.length());
}
return sb.toString();
}
/**
* Tries to match the specified MIME type with the MIME types of the supplied
* file formats.
* This method does exactly the same as {@link info.aduna.lang.FileFormat#matchMIMEType(String, Iterable)}
* but only considers the <strong>default</strong> mimeTypes.
*
* @param mimeType A MIME type, e.g. "text/plain".
* @param fileFormats The file formats to match the MIME type against.
* @return A FileFormat object if the MIME type was recognized, or {@code null} otherwise.
*
* @see #matchDefaultMIMEType(String, Iterable, info.aduna.lang.FileFormat)
* @see info.aduna.lang.FileFormat#matchMIMEType(String, Iterable)
*
*/
public static <FF extends FileFormat> FF matchDefaultMIMEType(String mimeType, Iterable<FF> fileFormats) {
return matchDefaultMIMEType(mimeType, fileFormats, null);
}
/**
* Tries to match the specified MIME type with the default MIME types of the supplied
* file formats. The supplied fallback format will be returned when no
* matching format was found.
* This method does exactly the same as {@link info.aduna.lang.FileFormat#matchMIMEType(String, Iterable, info.aduna.lang.FileFormat)}
* but only considers the <strong>default</strong> mimeTypes.
*
* @param mimeType A MIME type, e.g. "text/plain".
* @param fileFormats The file formats to match the MIME type against.
* @param fallback The file format to return if no matching format can be found.
* @return A FileFormat that matches the MIME type, or the fallback format if the extension was not recognized.
*
* @see info.aduna.lang.FileFormat#matchMIMEType(String, Iterable, info.aduna.lang.FileFormat)
*
*/
public static <FF extends FileFormat> FF matchDefaultMIMEType(String mimeType, Iterable<FF> fileFormats,
FF fallback) {
// Try to match with the default MIME type
for (FF fileFormat : fileFormats) {
if (fileFormat.hasDefaultMIMEType(mimeType)) {
return fileFormat;
}
}
return fallback;
}
public static String getContainer(String resource) throws MalformedURLException, URISyntaxException {
final int fragmentIndex = resource.indexOf('#');
if (fragmentIndex >= 0) {
return resource.substring(0, fragmentIndex);
}
return resource.substring(0, resource.lastIndexOf('/', resource.length() - 1));
}
public static URI getContainer(URI resource) throws MalformedURLException, URISyntaxException {
return new URIImpl(getContainer(resource.stringValue()));
}
/**
* Convert a PreferHeader into a LDP Preference.
* @param prefer the PreferHeader to parse
* @return the Preference
*/
public static Preference parsePreferHeader(PreferHeader prefer) {
if (prefer == null) return null;
// we only support "return"-prefers
if (!PreferHeader.PREFERENCE_RETURN.equals(prefer.getPreference())) {
return null;
}
if (PreferHeader.RETURN_MINIMAL.equals(prefer.getPreferenceValue())) {
return Preference.minimalPreference();
}
if (PreferHeader.RETURN_REPRESENTATION.equals(prefer.getPreferenceValue())) {
final String include = prefer.getParamValue(PreferHeader.RETURN_PARAM_INCLUDE);
final String omit = prefer.getParamValue(PreferHeader.RETURN_PARAM_OMIT);
if (StringUtils.isNotBlank(include) && StringUtils.isBlank(omit)) {
return Preference.includePreference(include.split("\\s+"));
} else if (StringUtils.isNotBlank(omit) && StringUtils.isBlank(include)) {
return Preference.omitPreference(omit.split("\\s+"));
} else if (StringUtils.isBlank(include) && StringUtils.isBlank(omit)) {
return Preference.defaultPreference();
} else {
return null;
}
}
return null;
}
public static List<RDFFormat> filterAvailableParsers(List<RDFFormat> rdfFormats) {
final List<RDFFormat> result = new ArrayList<>();
final RDFParserRegistry parserRegistry = RDFParserRegistry.getInstance();
for (RDFFormat f: rdfFormats) {
if (parserRegistry.has(f)) {
result.add(f);
}
}
return result;
}
public static List<RDFFormat> filterAvailableWriters(List<RDFFormat> rdfFormats) {
final List<RDFFormat> result = new ArrayList<>();
final RDFWriterRegistry writerRegistry = RDFWriterRegistry.getInstance();
for (RDFFormat f: rdfFormats) {
if (writerRegistry.has(f)) {
result.add(f);
}
}
return result;
}
private LdpUtils() {
// Static access only
}
}