CCM NG/ccm-cms: Thumbnails for images in AssetBrowser

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4888 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: f7d7293868
pull/2/head
jensp 2017-07-27 10:26:14 +00:00
parent 01954befb0
commit 776e1719d3
10 changed files with 418 additions and 272 deletions

View File

@ -101,6 +101,8 @@ public class AssetFolderBrowser extends Table {
CMS_FOLDER_BUNDLE),
new GlobalizedMessage("cms.ui.folder.type",
CMS_FOLDER_BUNDLE),
new GlobalizedMessage("cms.ui.asset.thumbnail",
CMS_BUNDLE),
new GlobalizedMessage("cms.ui.folder.creation_date",
CMS_FOLDER_BUNDLE),
new GlobalizedMessage("cms.ui.folder.last_modified",
@ -120,6 +122,9 @@ public class AssetFolderBrowser extends Table {
nameColumn.setCellRenderer(new NameCellRenderer());
nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
getColumn(AssetFolderBrowserTableModel.COL_THUMBNAIL)
.setCellRenderer(new ThumbnailCellRenderer());
getColumn(AssetFolderBrowserTableModel.COL_CREATION_DATE)
.setHeaderRenderer(
new HeaderCellRenderer(SORT_KEY_CREATION_DATE));
@ -305,6 +310,26 @@ public class AssetFolderBrowser extends Table {
}
private class ThumbnailCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (value == null) {
return new Text("");
} else {
final Image image = new Image((String) value, "");
return image;
}
}
}
private class DateCellRenderer implements TableCellRenderer {
@Override

View File

@ -18,7 +18,9 @@
*/
package com.arsdigita.cms.ui.assets;
import com.arsdigita.cms.CMS;
import com.arsdigita.kernel.KernelConfig;
import com.arsdigita.web.CCMDispatcherServlet;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
@ -58,8 +60,10 @@ import org.librecms.contentsection.FolderRepository;
import java.util.Collections;
import java.util.Optional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.librecms.assets.Image;
import static org.librecms.CmsConstants.*;
@ -71,7 +75,7 @@ import static org.librecms.CmsConstants.*;
public class AssetFolderBrowserController {
private static final Logger LOGGER = LogManager
.getLogger(AssetFolderBrowserController.class);
.getLogger(AssetFolderBrowserController.class);
@Inject
private EntityManager entityManager;
@ -111,7 +115,7 @@ public class AssetFolderBrowserController {
@PostConstruct
private void init() {
final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class);
KernelConfig.class);
defaultLocale = kernelConfig.getDefaultLocale();
}
@ -128,9 +132,9 @@ public class AssetFolderBrowserController {
firstResult,
maxResults);
final List<AssetFolderBrowserTableRow> subFolderRows = subFolders
.stream()
.map(subFolder -> buildRow(subFolder))
.collect(Collectors.toList());
.stream()
.map(subFolder -> buildRow(subFolder))
.collect(Collectors.toList());
if (subFolders.size() > maxResults) {
return subFolderRows;
@ -145,9 +149,9 @@ public class AssetFolderBrowserController {
firstAsset,
maxAssets);
final List<AssetFolderBrowserTableRow> assetRows = assets
.stream()
.map(asset -> buildRow(asset))
.collect(Collectors.toList());
.stream()
.map(asset -> buildRow(asset))
.collect(Collectors.toList());
final List<AssetFolderBrowserTableRow> rows = new ArrayList<>();
rows.addAll(subFolderRows);
@ -177,19 +181,19 @@ public class AssetFolderBrowserController {
criteriaQuery = criteriaQuery.select(builder.count(from));
final List<Folder> subFolders = findSubFolders(
folder,
filterTerm,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
folder,
filterTerm,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
final List<Asset> assets = findAssetsInFolder(
folder,
filterTerm,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
folder,
filterTerm,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
if (subFolders.isEmpty() && assets.isEmpty()) {
return 0;
@ -199,8 +203,8 @@ public class AssetFolderBrowserController {
criteriaQuery = criteriaQuery.where(from.in(subFolders));
} else {
criteriaQuery = criteriaQuery.where(builder.or(
from.in(subFolders),
from.in(assets)));
from.in(subFolders),
from.in(assets)));
}
return entityManager.createQuery(criteriaQuery).getSingleResult();
@ -218,17 +222,17 @@ public class AssetFolderBrowserController {
if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
copyFolder(targetFolder,
Long.parseLong(objectId.substring(
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
} else if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_ASSET)) {
copyAsset(targetFolder,
Long.parseLong(objectId.substring(
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
} else {
throw new IllegalArgumentException(String.format(
"ID '%s' does not start with '%s' or '%s'.",
objectId,
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
FOLDER_BROWSER_KEY_PREFIX_ASSET));
"ID '%s' does not start with '%s' or '%s'.",
objectId,
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
FOLDER_BROWSER_KEY_PREFIX_ASSET));
}
}
@ -240,10 +244,10 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(targetFolder);
final Folder folder = folderRepo.findById(folderId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d in the database. "
+ "Where did that ID come from?",
folderId)));
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d in the database. "
+ "Where did that ID come from?",
folderId)));
folderManager.copyFolder(folder, targetFolder);
@ -255,10 +259,10 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(targetFolder);
final Asset asset = assetRepo
.findById(assetId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No asset ith ID %d in the database. Where did that ID come from?",
assetId)));
.findById(assetId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No asset ith ID %d in the database. Where did that ID come from?",
assetId)));
assetManager.copy(asset, targetFolder);
}
@ -274,17 +278,17 @@ public class AssetFolderBrowserController {
if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
moveFolder(targetFolder,
Long.parseLong(objectId.substring(
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length())));
} else if (objectId.startsWith(FOLDER_BROWSER_KEY_PREFIX_ASSET)) {
moveAsset(targetFolder,
Long.parseLong(objectId.substring(
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
FOLDER_BROWSER_KEY_PREFIX_ASSET.length())));
} else {
throw new IllegalArgumentException(String.format(
"ID '%s' does not start with '%s' or '%s'.",
objectId,
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
FOLDER_BROWSER_KEY_PREFIX_ASSET));
"ID '%s' does not start with '%s' or '%s'.",
objectId,
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
FOLDER_BROWSER_KEY_PREFIX_ASSET));
}
}
}
@ -294,10 +298,10 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(targetFolder);
final Folder folder = folderRepo.findById(folderId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d in the database. "
+ "Where did that ID come from?",
folderId)));
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d in the database. "
+ "Where did that ID come from?",
folderId)));
folderManager.moveFolder(folder, targetFolder);
}
@ -307,10 +311,10 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(targetFolder);
final Asset asset = assetRepo
.findById(assetId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No asset with ID %d in the database. Where did that ID come from?",
assetId)));
.findById(assetId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No asset with ID %d in the database. Where did that ID come from?",
assetId)));
assetManager.move(asset, targetFolder);
}
@ -321,20 +325,20 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(sources);
final List<String> sourceFolderIds = sources
.stream()
.filter(source -> source.startsWith(
FOLDER_BROWSER_KEY_PREFIX_FOLDER))
.collect(Collectors.toList());
.stream()
.filter(source -> source.startsWith(
FOLDER_BROWSER_KEY_PREFIX_FOLDER))
.collect(Collectors.toList());
final List<String> parentFolderIds = sourceFolderIds
.stream()
.map(sourceFolderId -> findParentFolderId(sourceFolderId))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
.stream()
.map(sourceFolderId -> findParentFolderId(sourceFolderId))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
final List<List<String>> subFolderIds = sourceFolderIds
.stream()
.map(sourceFolderId -> findSubFolderIds(sourceFolderId))
.collect(Collectors.toList());
.stream()
.map(sourceFolderId -> findSubFolderIds(sourceFolderId))
.collect(Collectors.toList());
final List<String> invalidTargetIds = new ArrayList<>();
invalidTargetIds.addAll(sourceFolderIds);
@ -353,26 +357,26 @@ public class AssetFolderBrowserController {
if (!folderId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
throw new IllegalArgumentException(String.format(
"Provided string '%s' is not an ID of a folder.",
folderId));
"Provided string '%s' is not an ID of a folder.",
folderId));
}
final long objectId = Long.parseLong(folderId.substring(
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
final Folder folder = folderRepo.findById(objectId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d found in database. "
+ "Where did that ID come form?",
objectId)));
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d found in database. "
+ "Where did that ID come form?",
objectId)));
final Optional<Folder> parentFolder = folderManager.getParentFolder(
folder);
folder);
if (parentFolder.isPresent()) {
return Optional.empty();
} else {
return Optional.ofNullable(String.format(
"%s%d",
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
parentFolder.get().getObjectId()));
"%s%d",
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
parentFolder.get().getObjectId()));
}
}
@ -382,23 +386,23 @@ public class AssetFolderBrowserController {
if (!folderId.startsWith(FOLDER_BROWSER_KEY_PREFIX_FOLDER)) {
throw new IllegalArgumentException(String.format(
"Provided string '%s' is not the ID of a folder.",
folderId));
"Provided string '%s' is not the ID of a folder.",
folderId));
}
final long objectId = Long.parseLong(folderId.substring(
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
FOLDER_BROWSER_KEY_PREFIX_FOLDER.length()));
final Folder folder = folderRepo.findById(objectId)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d found in database. "
+ "Where did that ID come form?",
objectId)));
.orElseThrow(() -> new IllegalArgumentException(String.format(
"No folder with ID %d found in database. "
+ "Where did that ID come form?",
objectId)));
return findSubFolders(folder)
.stream()
.map(subFolder -> String.format("%s%d",
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
subFolder.getObjectId()))
.collect(Collectors.toList());
.stream()
.map(subFolder -> String.format("%s%d",
FOLDER_BROWSER_KEY_PREFIX_FOLDER,
subFolder.getObjectId()))
.collect(Collectors.toList());
}
private List<Folder> findSubFolders(final Folder folder) {
@ -406,7 +410,7 @@ public class AssetFolderBrowserController {
Objects.requireNonNull(folder);
if (folder.getSubFolders() == null
|| folder.getSubFolders().isEmpty()) {
|| folder.getSubFolders().isEmpty()) {
return Collections.emptyList();
}
@ -431,21 +435,21 @@ public class AssetFolderBrowserController {
if (objectId.startsWith("folder-")) {
final long folderId = Long.parseLong(
objectId.substring("folder-".length()));
objectId.substring("folder-".length()));
folderRepo
.findById(folderId)
.ifPresent(folderRepo::delete);
.findById(folderId)
.ifPresent(folderRepo::delete);
} else if (objectId.startsWith("asset-")) {
final long assetId = Long.parseLong(
objectId.substring("asset-".length()));
objectId.substring("asset-".length()));
assetRepo
.findById(assetId)
.ifPresent(assetRepo::delete);
.findById(assetId)
.ifPresent(assetRepo::delete);
} else {
throw new IllegalArgumentException(
"The objectId is expected to start with 'folder-' or 'asset-'.");
"The objectId is expected to start with 'folder-' or 'asset-'.");
}
}
@ -457,15 +461,15 @@ public class AssetFolderBrowserController {
row.setObjectUuid(folder.getUuid());
row.setName(folder.getName());
if (folder.getTitle().hasValue(globalizationHelper
.getNegotiatedLocale())) {
.getNegotiatedLocale())) {
row.setTitle(folder.getTitle().getValue(globalizationHelper
.getNegotiatedLocale()));
.getNegotiatedLocale()));
} else {
row.setTitle(folder.getTitle().getValue(defaultLocale));
}
row.setFolder(true);
row.setDeletable(!categoryManager.hasSubCategories(folder)
&& !categoryManager.hasObjects(folder));
&& !categoryManager.hasObjects(folder));
return row;
}
@ -478,14 +482,22 @@ public class AssetFolderBrowserController {
row.setObjectUuid(asset.getUuid());
row.setName(asset.getDisplayName());
if (asset.getTitle().hasValue(globalizationHelper
.getNegotiatedLocale())) {
.getNegotiatedLocale())) {
row.setTitle(asset.getTitle().getValue(globalizationHelper
.getNegotiatedLocale()));
.getNegotiatedLocale()));
} else {
row.setTitle(asset.getTitle().getValue(defaultLocale));
}
if (asset instanceof Image) {
row.setThumbnailUrl(String
.format("%s/content-sections/%s/images/"
+ "uuid-%s?width=150&height=100",
CCMDispatcherServlet.getContextPath(),
CMS.getContext().getContentSection().getLabel(),
asset.getUuid()));
}
final AssetTypeInfo typeInfo = typesManager
.getAssetTypeInfo(asset.getClass());
.getAssetTypeInfo(asset.getClass());
row.setTypeLabelBundle(typeInfo.getLabelBundle());
row.setTypeLabelKey(typeInfo.getLabelKey());
@ -506,32 +518,32 @@ public class AssetFolderBrowserController {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Folder> criteria = builder
.createQuery(Folder.class);
.createQuery(Folder.class);
final Root<Folder> from = criteria.from(Folder.class);
final Order order;
if (AssetFolderBrowser.SORT_KEY_NAME.equals(orderBy)
&& AssetFolderBrowser.SORT_ACTION_DOWN.
equals(orderDirection)) {
&& AssetFolderBrowser.SORT_ACTION_DOWN.
equals(orderDirection)) {
order = builder.desc(from.get("name"));
} else {
order = builder.asc(from.get("name"));
}
final TypedQuery<Folder> query = entityManager
.createQuery(
criteria.where(
builder.and(
builder.
equal(from.get("parentCategory"),
folder),
builder.like(builder.lower(from.get(
"name")),
filterTerm)
)
)
.orderBy(order)
);
.createQuery(
criteria.where(
builder.and(
builder.
equal(from.get("parentCategory"),
folder),
builder.like(builder.lower(from.get(
"name")),
filterTerm)
)
)
.orderBy(order)
);
if (firstResult >= 0) {
query.setFirstResult(firstResult);
@ -582,35 +594,35 @@ public class AssetFolderBrowserController {
LOGGER.debug("The database contains {} assets.",
entityManager.createQuery(criteria.select(fromAsset)
.where(
builder.and(
builder.equal(join.get("category"),
folder),
builder.equal(join.get("type"),
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
builder.like(builder.lower(
fromAsset.get(
"displayName")),
filterTerm)
))).getResultList().size());
.where(
builder.and(
builder.equal(join.get("category"),
folder),
builder.equal(join.get("type"),
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
builder.like(builder.lower(
fromAsset.get(
"displayName")),
filterTerm)
))).getResultList().size());
final TypedQuery<Asset> query = entityManager
.createQuery(
criteria.select(fromAsset)
.where(
builder.and(
builder.equal(join.get(
"category"), folder),
builder.equal(join.get("type"),
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
builder.like(builder.lower(
fromAsset.get(
"displayName")),
filterTerm)
)
)
.orderBy(order)
);
.createQuery(
criteria.select(fromAsset)
.where(
builder.and(
builder.equal(join.get(
"category"), folder),
builder.equal(join.get("type"),
CmsConstants.CATEGORIZATION_TYPE_FOLDER),
builder.like(builder.lower(
fromAsset.get(
"displayName")),
filterTerm)
)
)
.orderBy(order)
);
if (firstResult >= 0) {
query.setFirstResult(firstResult);

View File

@ -35,9 +35,10 @@ class AssetFolderBrowserTableModel implements TableModel {
protected static final int COL_NAME = 0;
protected static final int COL_TITLE = 1;
protected static final int COL_TYPE = 2;
protected static final int COL_CREATION_DATE = 3;
protected static final int COL_LAST_MODIFIED = 4;
protected static final int COL_DELETEABLE = 5;
protected static final int COL_THUMBNAIL = 3;
protected static final int COL_CREATION_DATE = 4;
protected static final int COL_LAST_MODIFIED = 5;
protected static final int COL_DELETEABLE = 6;
private final Iterator<AssetFolderBrowserTableRow> iterator;
private AssetFolderBrowserTableRow currentRow;
@ -79,6 +80,8 @@ class AssetFolderBrowserTableModel implements TableModel {
} else {
return new GlobalizedMessage(typeLabelKey, typeLabelBundle);
}
case COL_THUMBNAIL:
return currentRow.getThumbnailUrl();
case COL_CREATION_DATE:
return currentRow.getCreated();
case COL_LAST_MODIFIED:

View File

@ -30,6 +30,7 @@ class AssetFolderBrowserTableRow {
private String objectUuid;
private String name;
private String title;
private String thumbnailUrl;
private String typeLabelBundle;
private String typeLabelKey;
private Date created;
@ -69,6 +70,14 @@ class AssetFolderBrowserTableRow {
this.title = title;
}
public String getThumbnailUrl() {
return thumbnailUrl;
}
public void setThumbnailUrl(final String thumbnailUrl) {
this.thumbnailUrl = thumbnailUrl;
}
public String getTypeLabelBundle() {
return typeLabelBundle;
}

View File

@ -62,6 +62,76 @@ public class Images {
@Inject
private AssetRepository assetRepo;
@GET
@Path("/uuid-{uuid}")
public Response getImageByUuid(
@PathParam("content-section")
final String sectionName,
@PathParam("uuid")
final String uuid,
@QueryParam("width")
@DefaultValue("-1")
final String widthParam,
@QueryParam("height")
@DefaultValue("-1")
final String heightParam) {
final Optional<Asset> asset = assetRepo
.findByUuidAndType(uuid, Image.class);
if (asset.isPresent()) {
if (asset.get() instanceof Image) {
return loadImage((Image) asset.get(), widthParam, heightParam);
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String
.format("The asset with the requested UUID \"%s\" "
+ "is not an image.",
uuid))
.build();
}
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String
.format("The requested image \"%s\" does not exist.",
uuid))
.build();
}
}
@GET
@Path("/uuid-{uuid}/properties")
public Response getImagePropertiesByUuid(
@PathParam("content-section") final String sectionName,
@PathParam("uuid") final String uuid) {
final Optional<Asset> asset = assetRepo.findByUuidAndType(uuid,
Image.class);
if (asset.isPresent()) {
if (asset.get() instanceof Image) {
return readImageProperties((Image) asset.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String
.format("The asset with the requested UUID \"%s\" "
+ "is not an image.",
uuid))
.build();
}
} else {
return Response
.status(Response.Status.NOT_FOUND)
.entity(String
.format("The requested image \"%s\" does not exist.",
uuid))
.build();
}
}
/**
* Return the image requested by the provided content section and path.
*
@ -119,80 +189,7 @@ public class Images {
if (asset.isPresent()) {
if (asset.get() instanceof Image) {
final Image image = (Image) asset.get();
final byte[] data = image.getData();
final String mimeType = image.getMimeType().toString();
final InputStream inputStream = new ByteArrayInputStream(data);
final BufferedImage bufferedImage;
final String imageFormat;
try {
final ImageInputStream imageInputStream = ImageIO
.createImageInputStream(inputStream);
final Iterator<ImageReader> readers = ImageIO
.getImageReaders(imageInputStream);
final ImageReader imageReader;
if (readers.hasNext()) {
imageReader = readers.next();
} else {
LOGGER.error("No image reader for image {} (UUID: {}) "
+ "available.",
image.getDisplayName(),
image.getUuid());
return Response.serverError().build();
}
imageReader.setInput(imageInputStream);
bufferedImage = imageReader.read(0);
imageFormat = imageReader.getFormatName();
} catch (IOException ex) {
LOGGER.error("Failed to load image {} (UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
// Yes, this is correct. The parameters provided in the URL
// are expected to be integers. The private scaleImage method
// works with floats to be accurate (divisions are performed
// with the values for width and height)
final int width = parseScaleParameter(widthParam, "width");
final int height = parseScaleParameter(heightParam, "height");
final java.awt.Image scaledImage = scaleImage(bufferedImage,
width,
height);
final ByteArrayOutputStream outputStream
= new ByteArrayOutputStream();
final BufferedImage bufferedScaledImage = new BufferedImage(
scaledImage.getWidth(null),
scaledImage.getHeight(null),
bufferedImage.getType());
bufferedScaledImage
.getGraphics()
.drawImage(scaledImage, 0, 0, null);
try {
ImageIO
.write(bufferedScaledImage, imageFormat, outputStream);
} catch (IOException ex) {
LOGGER.error("Failed to render scaled variant of image {} "
+ "(UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
// return Response
// .ok(String.format(
// "Requested image \"%s\" in content section \"%s\"",
// path,
// section.get().getLabel()),
// "text/plain")
// .build();
return Response
.ok(outputStream.toByteArray(), mimeType)
.build();
return loadImage((Image) asset.get(), widthParam, heightParam);
} else {
return Response
.status(Response.Status.NOT_FOUND)
@ -210,16 +207,6 @@ public class Images {
path))
.build();
}
// final Response.ResponseBuilder builder = Response
// .ok(String.format(
// "Requested image \"%s\" from folder \"%s\" in content section \"%s\"",
// imageName,
// folderPath,
// section.get().getLabel()),
// "text/plain");
//
// return builder.build();
}
/**
@ -253,39 +240,7 @@ public class Images {
if (asset.isPresent()) {
if (asset.get() instanceof Image) {
final Image image = (Image) asset.get();
final byte[] data = image.getData();
final String mimeType = image.getMimeType().toString();
final InputStream inputStream = new ByteArrayInputStream(data);
final BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(inputStream);
} catch (IOException ex) {
LOGGER.error("Failed to load image {} (UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
final String imageProperties = String
.format("{%n"
+ " \"name\": \"%s\",%n"
+ " \"filename\": \"%s\",%n"
+ " \"mimetype\": \"%s\",%n"
+ " \"width\": %d,%n"
+ " \"height\": %d%n"
+ "}",
image.getDisplayName(),
image.getFileName(),
mimeType,
bufferedImage.getWidth(),
bufferedImage.getHeight());
return Response
.ok(imageProperties, "application/json")
.build();
return readImageProperties((Image) asset.get());
} else {
return Response
.status(Response.Status.NOT_FOUND)
@ -305,6 +260,134 @@ public class Images {
}
}
/**
* Helper method for loading the image from the {@link Image} asset entity.
*
* This method also does the scaling of the image.
*
* @param image The image asset containing the image.
* @param widthParam The value of the width parameter.
* @param heightParam The value of the height parameter.
*
* @return The {@link Response} for sending the (scaled) image to the
* requesting user agent.
*/
private Response loadImage(final Image image,
final String widthParam,
final String heightParam) {
final byte[] data = image.getData();
final String mimeType = image.getMimeType().toString();
final InputStream inputStream = new ByteArrayInputStream(data);
final BufferedImage bufferedImage;
final String imageFormat;
try {
final ImageInputStream imageInputStream = ImageIO
.createImageInputStream(inputStream);
final Iterator<ImageReader> readers = ImageIO
.getImageReaders(imageInputStream);
final ImageReader imageReader;
if (readers.hasNext()) {
imageReader = readers.next();
} else {
LOGGER.error("No image reader for image {} (UUID: {}) "
+ "available.",
image.getDisplayName(),
image.getUuid());
return Response.serverError().build();
}
imageReader.setInput(imageInputStream);
bufferedImage = imageReader.read(0);
imageFormat = imageReader.getFormatName();
} catch (IOException ex) {
LOGGER.error("Failed to load image {} (UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
// Yes, this is correct. The parameters provided in the URL
// are expected to be integers. The private scaleImage method
// works with floats to be accurate (divisions are performed
// with the values for width and height)
final int width = parseScaleParameter(widthParam, "width");
final int height = parseScaleParameter(heightParam, "height");
final java.awt.Image scaledImage = scaleImage(bufferedImage,
width,
height);
final ByteArrayOutputStream outputStream
= new ByteArrayOutputStream();
final BufferedImage bufferedScaledImage = new BufferedImage(
scaledImage.getWidth(null),
scaledImage.getHeight(null),
bufferedImage.getType());
bufferedScaledImage
.getGraphics()
.drawImage(scaledImage, 0, 0, null);
try {
ImageIO
.write(bufferedScaledImage, imageFormat, outputStream);
} catch (IOException ex) {
LOGGER.error("Failed to render scaled variant of image {} "
+ "(UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
return Response
.ok(outputStream.toByteArray(), mimeType)
.build();
}
/**
* Helper method for reading the image properties and converting them into
* an JSON response.
*
* @param image The image which properties are read.
*
* @return A {@link Response} with the image properties as JSON.
*/
private Response readImageProperties(final Image image) {
final byte[] data = image.getData();
final String mimeType = image.getMimeType().toString();
final InputStream inputStream = new ByteArrayInputStream(data);
final BufferedImage bufferedImage;
try {
bufferedImage = ImageIO.read(inputStream);
} catch (IOException ex) {
LOGGER.error("Failed to load image {} (UUID: {}).",
image.getDisplayName(),
image.getUuid());
LOGGER.error(ex);
return Response.serverError().build();
}
final String imageProperties = String
.format("{%n"
+ " \"name\": \"%s\",%n"
+ " \"filename\": \"%s\",%n"
+ " \"mimetype\": \"%s\",%n"
+ " \"width\": %d,%n"
+ " \"height\": %d%n"
+ "}",
image.getDisplayName(),
image.getFileName(),
mimeType,
bufferedImage.getWidth(),
bufferedImage.getHeight());
return Response
.ok(imageProperties, "application/json")
.build();
}
/**
* Helper method for parsing the parameters for scaling an image into
* integers.

View File

@ -386,3 +386,4 @@ related_info_step_description=Add related information
cms.ui.authoring.file_upload.auto_detect=(Auto-Detect)
cms.ui.upload_new_content=Upload new content
cms.ui.asset.name=Name
cms.ui.asset.thumbnail=Preview

View File

@ -383,3 +383,4 @@ related_info_step_description=Weiterf\u00fchrende Informationen hinzuf\u00fcgen
cms.ui.authoring.file_upload.auto_detect=(Automatisch erkennen)
cms.ui.upload_new_content=Neuen Inhalt hochladen
cms.ui.asset.name=Name
cms.ui.asset.thumbnail=Vorschau

View File

@ -342,3 +342,4 @@ related_info_step_description=Add related information
cms.ui.authoring.file_upload.auto_detect=(Auto-Detect)
cms.ui.upload_new_content=Upload new content
cms.ui.asset.name=Name
cms.ui.asset.thumbnail=Preview

View File

@ -52,9 +52,12 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import java.net.URLEncoder;
import javax.servlet.ServletRequestWrapper;
/**
* Class static helper methods for request dispatching. Contains various
* generally useful procedural abstractions.
@ -70,7 +73,8 @@ public final class DispatcherHelper implements DispatcherConstants {
* set com.arsdigita.dispatcher.DispatcherHelper=DEBUG by uncommenting or
* adding the line.
*/
private static final Logger LOGGER = LogManager.getLogger(DispatcherHelper.class);
private static final Logger LOGGER = LogManager.getLogger(
DispatcherHelper.class);
private static String s_webappCtx;
private static String s_staticURL;
private static boolean s_cachingActive;
@ -177,7 +181,14 @@ public final class DispatcherHelper implements DispatcherConstants {
}
public static String getDispatcherPrefix(HttpServletRequest req) {
return (String) req.getAttribute(DISPATCHER_PREFIX_ATTR);
final HttpServletRequest request;
if (req instanceof ShiroHttpServletRequest) {
request = (HttpServletRequest) ((ServletRequestWrapper) req)
.getRequest();
} else {
request = req;
}
return (String) request.getAttribute(DISPATCHER_PREFIX_ATTR);
}
public static void setDispatcherPrefix(HttpServletRequest req,
@ -541,10 +552,10 @@ public final class DispatcherHelper implements DispatcherConstants {
if (previous instanceof MultipartHttpServletRequest) {
LOGGER.debug("Build new multipart request from previous "
+ previous + " and current " + orig);
+ previous + " and current " + orig);
MultipartHttpServletRequest previousmp
= (MultipartHttpServletRequest) previous;
= (MultipartHttpServletRequest) previous;
sreq = new MultipartHttpServletRequest(previousmp,
orig);
@ -567,7 +578,7 @@ public final class DispatcherHelper implements DispatcherConstants {
}
} else {
LOGGER.debug("The request is not multipart; proceeding "
+ "without wrapping the request");
+ "without wrapping the request");
}
return sreq;
}
@ -681,14 +692,14 @@ public final class DispatcherHelper implements DispatcherConstants {
destination = URL.there(req, url.substring(0, sep), params);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Setting destination with map to "
+ destination);
+ destination);
}
}
throw new RedirectSignal(destination, true);
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Redirecting to URL without using URL.there. "
+ "URL is " + url);
+ "URL is " + url);
}
throw new RedirectSignal(url, true);
}
@ -875,7 +886,7 @@ public final class DispatcherHelper implements DispatcherConstants {
LOGGER.warn(
"webappContext changed. Expected='" + s_webappCtx
+ "' found='" + webappCtx
+ "'.\nPerhaps the enterprise.init "
+ "'.\nPerhaps the enterprise.init "
+ "com.arsdigita.dispatcher.Initializer webappContext "
+ "parameter is wrong.");
// Save the webappCtx from the request for future use.
@ -1193,7 +1204,7 @@ public final class DispatcherHelper implements DispatcherConstants {
// Set the preferedLocale to the default locale (first entry in the
// config parameter list)
Locale preferedLocale
= new Locale(kernelConfig.getDefaultLanguage(), "", "");
= new Locale(kernelConfig.getDefaultLanguage(), "", "");
// The ACCEPTED_LANGUAGES from the client
Enumeration locales = null;

View File

@ -706,7 +706,7 @@ public class URL {
@SuppressWarnings("unchecked")
final Bean<ConfigurationManager> bean
= (Bean<ConfigurationManager>) iterator
.next();
.next();
final CreationalContext<ConfigurationManager> ctx = beanManager
.createCreationalContext(bean);
confManager = (ConfigurationManager) beanManager.getReference(