io.wcm.handler.mediasource.inline.InlineMediaSource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of io.wcm.handler.media Show documentation
Show all versions of io.wcm.handler.media Show documentation
Media resolving, processing and markup generation.
/*
* #%L
* wcm.io
* %%
* Copyright (C) 2014 wcm.io
* %%
* 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.
* #L%
*/
package io.wcm.handler.mediasource.inline;
import io.wcm.handler.commons.dom.HtmlElement;
import io.wcm.handler.media.Asset;
import io.wcm.handler.media.Media;
import io.wcm.handler.media.MediaArgs;
import io.wcm.handler.media.MediaInvalidReason;
import io.wcm.handler.media.MediaNameConstants;
import io.wcm.handler.media.MediaRequest;
import io.wcm.handler.media.impl.JcrBinary;
import io.wcm.handler.media.spi.helpers.AbstractMediaSource;
import io.wcm.sling.commons.util.Escape;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.adapter.Adaptable;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.injectorspecific.OSGiService;
import org.apache.sling.models.annotations.injectorspecific.Self;
import org.osgi.annotation.versioning.ProviderType;
import com.day.cq.commons.jcr.JcrConstants;
/**
* Default implementation for media references to binaries stored in a node inside the content page.
*/
@Model(adaptables = {
SlingHttpServletRequest.class, Resource.class
})
@ProviderType
public final class InlineMediaSource extends AbstractMediaSource {
@Self
private Adaptable adaptable;
@OSGiService(optional = true)
private MimeTypeService mimeTypeService;
/**
* Media source ID
*/
public static final String ID = "inline";
@Override
public String getId() {
return ID;
}
@Override
public boolean accepts(MediaRequest mediaRequest) {
// if no media source id is defined fallback to auto-detection of inline media object in resource
String mediaSourceId = mediaRequest.getResourceProperties().get(MediaNameConstants.PN_MEDIA_SOURCE, String.class);
if (StringUtils.isEmpty(mediaSourceId)) {
// accept for inline media if "mediaInline" child node is present
return getMediaInlineResource(mediaRequest) != null;
}
else {
return super.accepts(mediaRequest);
}
}
@Override
public boolean accepts(String mediaRef) {
// not supported
return false;
}
@Override
public String getPrimaryMediaRefProperty() {
// not supported
return null;
}
@Override
public Media resolveMedia(Media media) {
MediaArgs mediaArgs = media.getMediaRequest().getMediaArgs();
// the resource that was referenced originally (and may contain additional attributes)
Resource referencedResource = media.getMediaRequest().getResource();
Resource ntFileResource = null;
Resource ntResourceResource = null;
// get and check resource holding binary data (with primary node type nt:resource)
Resource mediaInlineResource = getMediaInlineResource(media.getMediaRequest());
if (mediaInlineResource != null) {
if (JcrBinary.isNtFile(mediaInlineResource)) {
ntFileResource = mediaInlineResource;
ntResourceResource = mediaInlineResource.getChild(JcrConstants.JCR_CONTENT);
}
else if (JcrBinary.isNtResource(mediaInlineResource)) {
ntResourceResource = mediaInlineResource;
}
}
// skip further processing if nor binary resource found
if (ntResourceResource == null) {
media.setMediaInvalidReason(MediaInvalidReason.MEDIA_REFERENCE_INVALID);
return media;
}
// Alternative text - if there is a custom alt text specified in the media args then use that one
if (StringUtils.isEmpty(mediaArgs.getAltText()) && referencedResource != null) {
// otherwise check if there is a custom altText specified in the component's properties
ValueMap props = referencedResource.getValueMap();
mediaArgs.altText(props.get(MediaNameConstants.PN_MEDIA_ALTTEXT, String.class));
}
// Check for crop dimensions
media.setCropDimension(getMediaCropDimension(media.getMediaRequest()));
// detect and clean up file name
String fileName = detectFileName(referencedResource, ntFileResource, ntResourceResource);
fileName = cleanupFileName(fileName);
// generate media item and rendition for inline media
Asset asset = getInlineAsset(ntResourceResource, media, fileName);
media.setAsset(asset);
// resolve rendition
boolean renditionsResolved = resolveRenditions(media, asset, mediaArgs);
// set media invalid reason
if (!renditionsResolved) {
if (media.getRenditions().isEmpty()) {
media.setMediaInvalidReason(MediaInvalidReason.NO_MATCHING_RENDITION);
}
else {
media.setMediaInvalidReason(MediaInvalidReason.NOT_ENOUGH_MATCHING_RENDITIONS);
}
}
return media;
}
/**
* Get implementation of inline media item
* @param ntResourceResource nt:resource node
* @param media Media metadata
* @param fileName File name
* @return Inline media item instance
*/
private Asset getInlineAsset(Resource ntResourceResource, Media media, String fileName) {
return new InlineAsset(ntResourceResource, media, fileName, adaptable);
}
/**
* Detect filename for inline binary.
* @param referencedResource Resource that was referenced in media reference and may contain file name property.
* @param ntFileResource nt:file resource (optional, null if not existent)
* @param ntResourceResource nt:resource resource
* @return Detected or virtual filename. Never null.
*/
private String detectFileName(Resource referencedResource, Resource ntFileResource,
Resource ntResourceResource) {
// detect file name
String fileName = null;
// if referenced resource is not the nt:file node check for Name property
if (ntFileResource != null && !referencedResource.equals(ntFileResource)) {
fileName = referencedResource.getValueMap().get(ntFileResource.getName() + "Name", String.class);
}
// if not nt:file node exists and the referenced resource is not the nt:resource node check for Name property
else if (ntFileResource == null && !referencedResource.equals(ntResourceResource)) {
fileName = referencedResource.getValueMap().get(ntResourceResource.getName() + "Name", String.class);
}
// otherwise use node name of nt:file resource if it exists
else if (ntFileResource != null) {
fileName = ntFileResource.getName();
}
// make sure filename has an extension, otherwise build virtual file name
if (!StringUtils.contains(fileName, ".")) {
fileName = null;
}
// if no filename found detect extension from mime type and build virtual filename
if (StringUtils.isBlank(fileName)) {
String fileExtension = null;
if (ntResourceResource != null) {
String mimeType = ntResourceResource.getValueMap().get(JcrConstants.JCR_MIMETYPE, String.class);
if (StringUtils.isNotEmpty(mimeType) && mimeTypeService != null) {
fileExtension = mimeTypeService.getExtension(mimeType);
}
}
if (StringUtils.isEmpty(fileExtension)) {
fileExtension = "bin";
}
fileName = "file." + fileExtension;
}
return fileName;
}
/**
* Make sure filename contains no invalid characters or path parts
* @param fileName File name
* @return Cleaned up file name
*/
private String cleanupFileName(String fileName) {
String processedFileName = fileName;
// strip off path parts
if (StringUtils.contains(processedFileName, "/")) {
processedFileName = StringUtils.substringAfterLast(processedFileName, "/");
}
if (StringUtils.contains(processedFileName, "\\")) {
processedFileName = StringUtils.substringAfterLast(processedFileName, "\\");
}
// make sure filename does not contain any invalid characters
processedFileName = Escape.validFilename(processedFileName);
return processedFileName;
}
/**
* Get resource with media inline data (nt:file node).
* @param mediaRequest Media reference
* @return Resource or null if not present
*/
private Resource getMediaInlineResource(MediaRequest mediaRequest) {
Resource resource = mediaRequest.getResource();
if (resource == null) {
return null;
}
// check if resource itself is a nt:file node
if (JcrBinary.isNtFileOrResource(resource)) {
return resource;
}
// check if child node exists which is a nt:file node
String refProperty = StringUtils.defaultString(mediaRequest.getRefProperty(), MediaNameConstants.NN_MEDIA_INLINE);
Resource mediaInlineResource = resource.getChild(refProperty);
if (JcrBinary.isNtFileOrResource(mediaInlineResource)) {
return mediaInlineResource;
}
// not found
return null;
}
@Override
public void enableMediaDrop(HtmlElement element, MediaRequest mediaRequest) {
// not supported
}
@Override
public String toString() {
return ID;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy