Moving the backend call to the Sailing service and a few code style improvements

This commit is contained in:
RobinFleige committed 2018-08-03 14:25:02 +02:00
1 parent 282a81916f
commit 0c2db48626
13 files changed
+247 -336

No files matched your search

@@ -19,7 +19,7 @@ public class EventCreateDialog extends EventDialog {
public EventCreateDialog(Collection<EventDTO> existingEvents, List<LeaderboardGroupDTO> availableLeaderboardGroups,
SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback<EventDTO> callback) {
super(new EventParameterValidator(stringMessages, existingEvents), sailingService, stringMessages, errorReporter,
super(new EventParameterValidator(stringMessages, existingEvents), sailingService, stringMessages,
availableLeaderboardGroups, /* leaderboardGroups */ Collections.<LeaderboardGroupDTO>emptyList(), callback);
nameEntryField = createTextBox(null);
nameEntryField.setVisibleLength(50);
@@ -33,7 +33,6 @@ import com.sap.sailing.gwt.ui.shared.CourseAreaDTO;
import com.sap.sailing.gwt.ui.shared.EventDTO;
import com.sap.sailing.gwt.ui.shared.LeaderboardGroupDTO;
import com.sap.sailing.gwt.ui.shared.VenueDTO;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.IconResources;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
@@ -147,7 +146,7 @@ public abstract class EventDialog extends DataEntryDialogWithDateTimeBox<EventDT
* assignments for re-association with the new {@link EventDTO} created by the {@link #getResult} method.
*/
public EventDialog(EventParameterValidator validator, SailingServiceAsync sailingService,
StringMessages stringMessages, ErrorReporter errorReporter, List<LeaderboardGroupDTO> availableLeaderboardGroups,
StringMessages stringMessages, List<LeaderboardGroupDTO> availableLeaderboardGroups,
Iterable<LeaderboardGroupDTO> leaderboardGroupsOfEvent, DialogCallback<EventDTO> callback) {
super(stringMessages.event(), null, stringMessages.ok(), stringMessages.cancel(), validator, callback);
testFileStorageService(sailingService);//callback: the earlier the better to improve user experience
@@ -181,7 +180,7 @@ public abstract class EventDialog extends DataEntryDialogWithDateTimeBox<EventDT
new StringConstantsListEditorComposite.ExpandedUi(stringMessages, IconResources.INSTANCE.removeIcon(),
leaderboardGroupNames, stringMessages.selectALeaderboardGroup()));
leaderboardGroupList.addValueChangeHandler(valueChangeHandler);
imagesListComposite = new ImagesListComposite(sailingService, stringMessages,errorReporter,storageServiceAvailable);
imagesListComposite = new ImagesListComposite(sailingService, stringMessages,storageServiceAvailable);
videosListComposite = new VideosListComposite(sailingService,stringMessages,storageServiceAvailable);
externalLinksComposite = new ExternalLinksComposite(stringMessages);
final List<String> suggestedWindFinderSpotCollections = AvailableWindFinderSpotCollections
@@ -14,7 +14,7 @@ import com.sap.sse.gwt.client.controls.datetime.DateTimeInput.Accuracy;
public class EventEditDialog extends EventDialog {
public EventEditDialog(EventDTO event, Collection<EventDTO> otherExistingEvents, List<LeaderboardGroupDTO> availableLeaderboardGroups,
SailingServiceAsync sailingService, StringMessages stringMessages, ErrorReporter errorReporter, DialogCallback<EventDTO> callback) {
super(new EventParameterValidator(stringMessages, otherExistingEvents), sailingService, stringMessages, errorReporter, availableLeaderboardGroups, event.getLeaderboardGroups(), callback);
super(new EventParameterValidator(stringMessages, otherExistingEvents), sailingService, stringMessages, availableLeaderboardGroups, event.getLeaderboardGroups(), callback);
nameEntryField = createTextBox(event.getName());
nameEntryField.setVisibleLength(50);
descriptionEntryField = createTextArea(event.getDescription());
@@ -6,6 +6,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -245,10 +247,10 @@ public abstract class ImageDialog extends DataEntryDialog<ImageDTO> {
doResizeLabel.setVisible(false);
tagsListEditor = new StringListInlineEditorComposite(Collections.<String> emptyList(),
new GenericStringListInlineEditorWithCheckboxesComposite.ExpandedUi<String>(stringMessages, IconResources.INSTANCE.removeIcon(), /* suggestValues */
MediaConstants.imageTagSuggestions, stringMessages.enterTagsForTheImage(), 30, doResize,doResizeLabel,new ValueChangeHandler<Boolean>() {
MediaConstants.imageTagSuggestions, stringMessages.enterTagsForTheImage(), 30, doResize,doResizeLabel,new ClickHandler() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
public void onClick(ClickEvent event) {
validateAndUpdate();
CheckBox checkBox = (CheckBox)event.getSource();
if(checkBox.getValue()) {
@@ -256,6 +258,7 @@ public abstract class ImageDialog extends DataEntryDialog<ImageDTO> {
}else {
checkBox.getElement().getStyle().setBackgroundColor("red");
}
}
}));
tagsListEditor.addValueChangeHandler(new ValueChangeHandler<Iterable<String>>() {
@@ -265,7 +268,7 @@ public abstract class ImageDialog extends DataEntryDialog<ImageDTO> {
}
});
}
@Override
protected ImageDTO getResult() {
List<String> tags = new ArrayList<String>();
@@ -1,8 +1,6 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import com.google.gwt.cell.client.AbstractCell;
@@ -11,17 +9,6 @@ import com.google.gwt.cell.client.SafeHtmlCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONBoolean;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
@@ -31,6 +18,7 @@ import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HorizontalPanel;
@@ -46,7 +34,6 @@ import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sailing.gwt.ui.common.client.DateAndTimeFormatterUtil;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.util.NaturalComparator;
import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.Notification;
import com.sap.sse.gwt.client.Notification.NotificationType;
import com.sap.sse.gwt.client.celltable.BaseCelltable;
@@ -62,7 +49,6 @@ import com.sap.sse.gwt.client.media.ToResizeImageDTO;
public class ImagesListComposite extends Composite {
private final StringMessages stringMessages;
private final SailingServiceAsync sailingService;
private final ErrorReporter errorReporter;
private CellTable<ImageDTO> imageTable;
private SingleSelectionModel<ImageDTO> imageSelectionModel;
@@ -89,10 +75,9 @@ public class ImagesListComposite extends Composite {
private final AdminConsoleTableResources tableRes = GWT.create(AdminConsoleTableResources.class);
public ImagesListComposite(SailingServiceAsync sailingService, final StringMessages stringMessages, final ErrorReporter errorReporter, MutableBoolean storageServiceAvailable) {
public ImagesListComposite(SailingServiceAsync sailingService, final StringMessages stringMessages, MutableBoolean storageServiceAvailable) {
this.sailingService = sailingService;
this.stringMessages = stringMessages;
this.errorReporter = errorReporter;
this.storageServiceAvailable = storageServiceAvailable;
mainPanel = new SimplePanel();
@@ -299,7 +284,7 @@ public class ImagesListComposite extends Composite {
@Override
public void ok(ImageDTO newImage) {
if(newImage.getClass().equals(ToResizeImageDTO.class)) {
callResizingServlet(null, (ToResizeImageDTO) newImage);
callResizingService(newImage, null);
}else {
imageListDataProvider.getList().add(newImage);
updateTableVisisbilty();
@@ -322,7 +307,7 @@ public class ImagesListComposite extends Composite {
@Override
public void ok(ImageDTO updatedImage) {
if(updatedImage.getClass().equals(ToResizeImageDTO.class)) {
callResizingServlet(selectedImage, (ToResizeImageDTO) updatedImage);
callResizingService(updatedImage,selectedImage);
}else {
imageListDataProvider.getList().remove(selectedImage);
imageListDataProvider.getList().add(updatedImage);
@@ -332,67 +317,26 @@ public class ImagesListComposite extends Composite {
});
dialog.show();
}
private String imageToJSON(ToResizeImageDTO image) {
JSONObject obj = new JSONObject();
obj.put("URI", new JSONString(image.getSourceRef()));
obj.put("Title", new JSONString(image.getTitle()));
obj.put("Subtitle", new JSONString(image.getSubtitle()));
obj.put("Height", new JSONNumber(image.getHeightInPx()));
obj.put("Width", new JSONNumber(image.getWidthInPx()));
obj.put("Date", new JSONNumber(image.getCreatedAtDate().getTime()));
obj.put("Copyright", new JSONString(image.getCopyright()));
JSONObject doResizeMap = new JSONObject();
for(String doResize : image.getMap().keySet()) {
doResizeMap.put(doResize, JSONBoolean.getInstance(image.resizeForTag(doResize)));
}
obj.put("ResizeMap", doResizeMap);
JSONArray tags = new JSONArray();
for(int i = 0; i < image.getTags().size(); i++) {
tags.set(i, new JSONString(image.getTags().get(i)));
}
obj.put("Tags", tags);
return obj.toString();
}
private void callResizingServlet(ImageDTO originalImage, ToResizeImageDTO image) {
protected void callResizingService(ImageDTO newImage, ImageDTO originalImage) {
sailingService.resizeImage((ToResizeImageDTO) newImage, new AsyncCallback<ImageDTO[]>(){
@Override
public void onFailure(Throwable caught) {
Notification.notify(stringMessages.resizeUnsuccessfull(), NotificationType.ERROR);
}
@Override
public void onSuccess(ImageDTO[] result) {
for(int i = 0; i < result.length; i++) {
imageListDataProvider.getList().add(result[i]);
}
imageListDataProvider.getList().remove(originalImage);
updateTableVisisbilty();
Notification.notify(stringMessages.resizeSuccessfull(), NotificationType.SUCCESS);
}});
RequestBuilder builder = new RequestBuilder(RequestBuilder.POST,"/sailingserver/imageResize");
builder.setHeader("Content-Type", "application/json");
try {
builder.sendRequest(imageToJSON(image), new RequestCallback() {
@Override
public void onResponseReceived(Request request, Response response) {
String responseText = response.getText();
JSONArray images = JSONParser.parseStrict(responseText).isArray();
for(int i = 0; i < images.size(); i++) {
ImageDTO image = new ImageDTO(images.get(i).isObject().get("URI").isString().stringValue(),new Date(Long.valueOf(images.get(i).isObject().get("Date").isNumber().toString())));
List<String> tags = new ArrayList<>();
JSONArray jsonTags = images.get(i).isObject().get("Tags").isArray();
for(int j = 0; j < jsonTags.size(); j++) {
tags.add(jsonTags.get(j).isString().stringValue());
}
image.setTags(tags);
image.setTitle(images.get(i).isObject().get("Title").isString().stringValue());
image.setSubtitle(images.get(i).isObject().get("Subtitle").isString().stringValue());
image.setSizeInPx(Integer.valueOf(images.get(i).isObject().get("Width").isNumber().toString()), Integer.valueOf(images.get(i).isObject().get("Height").isNumber().toString()));
imageListDataProvider.getList().add(image);
}
imageListDataProvider.getList().remove(originalImage);
updateTableVisisbilty();
errorReporter.reportError(stringMessages.resizeSuccessfull(), true);
}
@Override
public void onError(Request request, Throwable exception) {
errorReporter.reportError(stringMessages.resizeUnsuccessfull(), false);
}
});
} catch (RequestException e) {
e.printStackTrace();
}
}
private void updateTableVisisbilty() {
@@ -121,6 +121,7 @@ import com.sap.sse.common.mail.MailException;
import com.sap.sse.gwt.client.ServerInfoDTO;
import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtService;
import com.sap.sse.gwt.client.media.ImageDTO;
import com.sap.sse.gwt.client.media.ToResizeImageDTO;
import com.sap.sse.gwt.client.media.VideoDTO;
import com.sap.sse.gwt.client.replication.RemoteReplicationService;
@@ -782,4 +783,6 @@ public interface SailingService extends RemoteService, FileStorageManagementGwtS
* Checks if the given race is currently in state tracking or loading.
*/
Boolean checkIfRaceIsTracking(RegattaAndRaceIdentifier race);
ImageDTO[] resizeImage(ToResizeImageDTO toResizeImage) throws Exception;
}
@@ -108,6 +108,7 @@ import com.sap.sse.common.Util.Triple;
import com.sap.sse.gwt.client.ServerInfoRetriever;
import com.sap.sse.gwt.client.filestorage.FileStorageManagementGwtServiceAsync;
import com.sap.sse.gwt.client.media.ImageDTO;
import com.sap.sse.gwt.client.media.ToResizeImageDTO;
import com.sap.sse.gwt.client.media.VideoDTO;
import com.sap.sse.gwt.client.replication.RemoteReplicationServiceAsync;
import com.sap.sse.pairinglist.PairingList;
@@ -989,4 +990,6 @@ public interface SailingServiceAsync extends ServerInfoRetriever, FileStorageMan
* @see SailingService#checkIfRaceIsTracking(RegattaAndRaceIdentifier)
*/
void checkIfRaceIsTracking(RegattaAndRaceIdentifier raceIdentifier, AsyncCallback<Boolean> asyncCallback);
void resizeImage(ToResizeImageDTO updatedImage, AsyncCallback<ImageDTO[]> asyncCallback) ;
}
@@ -1,5 +1,10 @@
package com.sap.sailing.gwt.ui.server;
import static java.lang.Math.toIntExact;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterInputStream;
@@ -52,6 +57,13 @@ import java.util.regex.Pattern;
import java.util.stream.StreamSupport;
import java.util.zip.GZIPInputStream;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -449,6 +461,7 @@ import com.sap.sailing.gwt.ui.shared.WaypointDTO;
import com.sap.sailing.gwt.ui.shared.WindDTO;
import com.sap.sailing.gwt.ui.shared.WindInfoForRaceDTO;
import com.sap.sailing.gwt.ui.shared.WindTrackInfoDTO;
import com.sap.sailing.gwt.ui.shared.media.MediaConstants;
import com.sap.sailing.manage2sail.EventResultDescriptor;
import com.sap.sailing.manage2sail.Manage2SailEventResultsParserImpl;
import com.sap.sailing.manage2sail.RaceResultDescriptor;
@@ -544,12 +557,16 @@ import com.sap.sse.common.impl.DegreeBearingImpl;
import com.sap.sse.common.impl.MillisecondsTimePoint;
import com.sap.sse.common.impl.TimeRangeImpl;
import com.sap.sse.common.mail.MailException;
import com.sap.sse.common.media.ImageConverter;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.common.media.MimeType;
import com.sap.sse.filestorage.FileStorageManagementService;
import com.sap.sse.filestorage.FileStorageService;
import com.sap.sse.filestorage.InvalidPropertiesException;
import com.sap.sse.filestorage.OperationFailedException;
import com.sap.sse.gwt.client.ServerInfoDTO;
import com.sap.sse.gwt.client.media.ImageDTO;
import com.sap.sse.gwt.client.media.ToResizeImageDTO;
import com.sap.sse.gwt.client.media.VideoDTO;
import com.sap.sse.gwt.dispatch.servlets.ProxiedRemoteServiceServlet;
import com.sap.sse.gwt.server.filestorage.FileStorageServiceDTOUtils;
@@ -7877,4 +7894,167 @@ public class SailingServiceImpl extends ProxiedRemoteServiceServlet implements S
}
}
}
@Override
public ImageDTO[] resizeImage(ToResizeImageDTO toResizeImage) throws Exception {
//In following size tag will describe the tags, that have a defined size in MediaConstants, which is LOGO, TEASER and STAGE at the moment
//create ArrayList that will contain all images that are to return
List<ImageDTO> resizedImages = new ArrayList<ImageDTO>();
//calculating the fileType of the image by its uri
String fileType = toResizeImage.getSourceRef().substring(toResizeImage.getSourceRef().lastIndexOf(".")+1);
//splitting the size-tags in size-tags that need a resize and size-tags that do not need a resize
List<String> resizeTags = new ArrayList<>();
List<String> notResizeSizeTags = new ArrayList<>();
ImageConverter.splitSizeTags(toResizeImage.getMap(),resizeTags,notResizeSizeTags);
//deleting all size-tags from the tags list, because after resizing there should only be one size tag per image
toResizeImage.getTags().removeAll(toResizeImage.getMap().keySet());
//trying to receive the EXIF data and loading the image. If this does not work only the image is loaded
IIOMetadata metadata = null;
BufferedImage img = null;
boolean loaded = false;
try(InputStream is = getService().getFileStorageManagementService().getActiveFileStorageService().loadFile(new URI(toResizeImage.getSourceRef()))){
Iterator<ImageReader> readerIterator = ImageIO.getImageReadersBySuffix(fileType);
while(readerIterator.hasNext()&&!loaded) {
ImageReader reader = readerIterator.next();
reader.setInput(ImageIO.createImageInputStream(is));
metadata = reader.getImageMetadata(0);
img = reader.read(0);
loaded = metadata != null;
}
if(!loaded) {
throw new Exception("Loading file via ImageReader did not work, not able to load metadata, retrying to load with ImageIO.read()");
}
}catch(Exception e) {
e.printStackTrace();
}
if(!loaded) {
try (InputStream is = getService().getFileStorageManagementService().getActiveFileStorageService().loadFile(new URI(toResizeImage.getSourceRef()))){
img = ImageConverter.isToBi(is);
} catch (NoCorrespondingServiceRegisteredException | OperationFailedException | InvalidPropertiesException
| IOException | URISyntaxException e) {
throw e;
}
}
//iterating over every size-tag that needs a resize
for(String resizeTag : resizeTags) {
//creating a new ImageDTO object with all values from the ToResizeImageDTO object
ImageDTO image = toImageDTO(toResizeImage);
//re-adding the size-tag for this iteration, so every ImageDTO object only has one size-tag
image.getTags().add(resizeTag);
//resizing the image
BufferedImage resizedBufferedImage = resizeImage(img, resizeTag, fileType);
//adding the new width and h eight to the ImageDTO object
image.setSizeInPx(resizedBufferedImage.getWidth(), resizedBufferedImage.getHeight());
//storing the image on FileStorageService
String newUri = storeImage(resizedBufferedImage, fileType, metadata).toString();
//saving the new image ref uri to the ImageDTO object
image.setSourceRef(newUri);
//adding the resized ImageDTO object to arraylist
resizedImages.add(image);
}
//if there is no size tag that does not need a resize we can delete the original source
if(notResizeSizeTags.isEmpty()) {
try {
getService().getFileStorageManagementService().getActiveFileStorageService().removeFile(new URI(toResizeImage.getSourceRef()));
} catch (NoCorrespondingServiceRegisteredException | OperationFailedException | InvalidPropertiesException
| IOException | URISyntaxException e) {
e.printStackTrace();
//file deleting did not work -> no important error, because the "only" result of this is one more stored image
}
}
//otherwise we have to create an ImageDTO object for every non-resize-size-tag
else {
for(String resizeTag : notResizeSizeTags) {
ImageDTO image = toImageDTO(toResizeImage);
//re-add the deleted specific size tag
image.getTags().add(resizeTag);
resizedImages.add(image);
}
}
return resizedImages.toArray(new ImageDTO[resizedImages.size()]);
}
private BufferedImage resizeImage(BufferedImage img, String resizeTag, String fileType) {
BufferedImage resizedImage = null;
switch(resizeTag) {
case MediaTagConstants.LOGO:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_LOGO_IMAGE_WIDTH, MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, MediaConstants.MAX_LOGO_IMAGE_HEIGHT, fileType, false);
break;
case MediaTagConstants.STAGE:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_STAGE_IMAGE_WIDTH, MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, MediaConstants.MAX_STAGE_IMAGE_HEIGHT, fileType, false);
break;
case MediaTagConstants.TEASER:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT, fileType, false);
break;
default://can not occur, because we only loop over the sizeTags, which are the same as in the switch case
break;
}
return resizedImage;
}
private URI storeImage(BufferedImage resizedBufferedImage, String fileType, IIOMetadata metaData) throws Exception {
URI imgUri = null;
byte[] bytes = null;
//trying to obtain OutputStream of the image with EXIF data
try (ImageOutputStream ios = ImageIO.createImageOutputStream(new ByteArrayOutputStream())){
//the following should write the exif data of the image to all copies of the image//it should already work, but due to a bug the data array stays empty
Iterator<ImageWriter> writers = ImageIO.getImageWritersBySuffix(fileType);
while(writers.hasNext() && bytes == null) {
ImageWriter writer = writers.next();
if(writer != null) {
writer.setOutput(ios);
IIOImage iioImage = new IIOImage(resizedBufferedImage, null, metaData);
ImageWriteParam param = writer.getDefaultWriteParam();
IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(param);
writer.write(streamMetadata, iioImage, param);
writer.dispose();
bytes = new byte[toIntExact(ios.length())];
ios.read(bytes);
if(isZeroByteArray(bytes))
bytes = null;
}
}
if(bytes == null)
throw new Exception("Saving file via FileWriter did not work, not able to write file with metadata, retrying with ImageIO.write()");
} catch (Exception e) {
bytes = null;
e.printStackTrace();
}
//if obtaining an OutputStream if the image with EXIF data did not work, then write it without
if(bytes == null) {
try(InputStream is = ImageConverter.biToIs(resizedBufferedImage, fileType)){
imgUri = getService().getFileStorageManagementService().getActiveFileStorageService().storeFile(is, "."+fileType, new Long(is.available()));
}
}else {//if it did work, then write the OutputStream to the FileStorageService
try(ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes)){
imgUri = getService().getFileStorageManagementService().getActiveFileStorageService().storeFile(byteStream, "."+fileType, new Long(byteStream.available()));
}
}
return imgUri;
}
private boolean isZeroByteArray(byte[] bytes) {
for(int i= 0; i < bytes.length; i++){
if(bytes[i] != 0)
return true;
}
return false;
}
public ImageDTO toImageDTO(ToResizeImageDTO toResizeImage) {
ImageDTO toReturn = new ImageDTO(toResizeImage.getSourceRef(), toResizeImage.getCreatedAtDate());
toReturn.setTitle(toResizeImage.getTitle());
toReturn.setCopyright(toResizeImage.getCopyright());
toReturn.setLocale(toResizeImage.getLocale());
toReturn.setMimeType(MimeType.byName(toResizeImage.getMimeType().name()));//creating a new mimetype object so they do not use the same reference
toReturn.setSizeInPx(toResizeImage.getWidthInPx(), toResizeImage.getHeightInPx());
toReturn.setSubtitle(toResizeImage.getSubtitle());
List<String> tags = new ArrayList<>();//Creating a new list, so they have the same tags, but not use the same reference to these tags, otherwise they could affect each other by editing this list
tags.addAll(toResizeImage.getTags());
toReturn.setTags(tags);
return toReturn;
}
}
@@ -8,6 +8,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.sap.sailing.gwt.ui.shared.media,
com.sap.sailing.server,
com.sap.sailing.server.operationaltransformation,
com.sap.sse.gwt.client.media,
javax.ws.rs;version="1.1.1",
javax.ws.rs.core;version="1.1.1",
javax.ws.rs.ext;version="1.1.1",
@@ -213,15 +213,7 @@
<servlet-name>FileUploadServlet</servlet-name>
<url-pattern>/fileupload</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ImageResizingServlet</servlet-name>
<servlet-class>com.sap.sailing.server.gateway.impl.ImageResizingServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageResizingServlet</servlet-name>
<url-pattern>/imageResize</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Jersey REST API</servlet-name>
<servlet-class>com.sap.sailing.server.gateway.jaxrs.RestServletContainer</servlet-class>
@@ -1,205 +0,0 @@
package com.sap.sailing.server.gateway.impl;
import static java.lang.Math.toIntExact;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import com.sap.sailing.gwt.ui.shared.media.MediaConstants;
import com.sap.sailing.server.gateway.AbstractJsonHttpServlet;
import com.sap.sse.common.NoCorrespondingServiceRegisteredException;
import com.sap.sse.common.media.ImageConverter;
import com.sap.sse.common.media.MediaTagConstants;
import com.sap.sse.filestorage.InvalidPropertiesException;
import com.sap.sse.filestorage.OperationFailedException;
public class ImageResizingServlet extends AbstractJsonHttpServlet {
private static final long serialVersionUID = 4240540462729675752L;
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//In following size tag will describe the tags, that have a defined size in MediaConstants, which is LOGO, TEASER and STAGE at the moment
String jsonString = new BufferedReader(new InputStreamReader(req.getInputStream())).readLine();
JSONObject obj = getObjFromJSON(jsonString);
List<String> resizeTags = new ArrayList<>();
List<String> notResizeSizeTags = new ArrayList<>();
JSONArray toReturnArray = new JSONArray();
if(obj != null) {
String fileType = ((String)obj.get("URI")).substring(((String)obj.get("URI")).lastIndexOf(".")+1);
JSONArray tags = (JSONArray) obj.get("Tags");
JSONObject resizeMap = (JSONObject) obj.get("ResizeMap");
IIOMetadata metadata = null;
BufferedImage img;
try(InputStream is = getInputStreamFromURIString(((String)obj.get("URI")))){
ImageReader reader = ImageIO.getImageReadersBySuffix(fileType).next();
reader.setInput(ImageIO.createImageInputStream(is));
metadata = reader.getImageMetadata(0);
img = reader.read(0);
}catch(Exception e) {
InputStream is = getInputStreamFromURIString(((String)obj.get("URI")));
img = ImageConverter.isToBi(is);
is.close();
}
for(Object tagKey : resizeMap.keySet()) {
if((boolean) resizeMap.get(tagKey)) {
resizeTags.add((String)tagKey);//size tags, that have the resize checkBox checked
}else{
notResizeSizeTags.add((String)tagKey);//size tags, that not have the resize checkBox checked
}
}
for(String resizeTag : resizeTags) {
for(String toDeleteTag : resizeTags) {//delete all size tags
tags.remove(toDeleteTag);
}
for(String toDeleteTag : notResizeSizeTags) {//delete all size tags
tags.remove(toDeleteTag);
}
tags.add(resizeTag);//read the deleted specific size tag
resizeAndAddToAr(img, toReturnArray, obj, resizeTag, fileType, metadata);
obj = getObjFromJSON(jsonString);//reset the object
tags = (JSONArray) obj.get("Tags");//and the tags
}
if(notResizeSizeTags.isEmpty()) {//if there is no size tag that does not need a resize we can delete the original source
try {
getService().getFileStorageManagementService().getActiveFileStorageService().removeFile(new URI((String)obj.get("URI")));
} catch (NoCorrespondingServiceRegisteredException | OperationFailedException
| InvalidPropertiesException | URISyntaxException e) {
e.printStackTrace();
}
}else {
for(String resizeTag : notResizeSizeTags) {
for(String toDeleteTag : resizeTags) {//delete all size tags
tags.remove(toDeleteTag);
}
for(String toDeleteTag : notResizeSizeTags) {//delete all size tags
tags.remove(toDeleteTag);
}
tags.add(resizeTag);//re-add the deleted specific size tag
toReturnArray.add(obj);
obj = getObjFromJSON(jsonString);//reset the object for next size-tag-iteration
tags = (JSONArray) obj.get("Tags");//and the tags
}
}
}
resp.getWriter().write(toReturnArray.toJSONString());
}
private InputStream getInputStreamFromURIString(String uri) {
try {
return getService().getFileStorageManagementService().getActiveFileStorageService().loadFile(new URI(uri));
} catch (NoCorrespondingServiceRegisteredException | OperationFailedException | InvalidPropertiesException
| IOException | URISyntaxException e) {
e.printStackTrace();
}
return null;
}
private JSONObject getObjFromJSON(String json) {
JSONParser parser = new JSONParser();
try {
return (JSONObject) parser.parse(json);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}
private void resizeAndAddToAr(BufferedImage img, JSONArray array, JSONObject resizedImageObject, String tag, String fileType, IIOMetadata metaData) {
URI imgUri = null;
BufferedImage resizedImage = null;
switch(tag) {
case MediaTagConstants.LOGO:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_LOGO_IMAGE_WIDTH, MediaConstants.MAX_LOGO_IMAGE_WIDTH, MediaConstants.MIN_LOGO_IMAGE_HEIGHT, MediaConstants.MAX_LOGO_IMAGE_HEIGHT, fileType, false);
break;
case MediaTagConstants.STAGE:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_STAGE_IMAGE_WIDTH, MediaConstants.MAX_STAGE_IMAGE_WIDTH, MediaConstants.MIN_STAGE_IMAGE_HEIGHT, MediaConstants.MAX_STAGE_IMAGE_HEIGHT, fileType, false);
break;
case MediaTagConstants.TEASER:
resizedImage = ImageConverter.resize(img, MediaConstants.MIN_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MAX_EVENTTEASER_IMAGE_WIDTH, MediaConstants.MIN_EVENTTEASER_IMAGE_HEIGHT, MediaConstants.MAX_EVENTTEASER_IMAGE_HEIGHT, fileType, false);
break;
default://can not occur, because we only loop over the sizeTags, which are the same as in the switch case
break;
}
try (ImageOutputStream ios = ImageIO.createImageOutputStream(new ByteArrayOutputStream())){
//the following should write the exif data of the image to all copies of the image//it should already work, but due to a bug the data array stays empty
Iterator<ImageWriter> writers = ImageIO.getImageWritersBySuffix(fileType);
byte[] bytes = null;
while(writers.hasNext() && bytes == null) {
ImageWriter writer = writers.next();
if(writer != null) {
writer.setOutput(ios);
IIOImage iioImage = new IIOImage(resizedImage, null, metaData);
ImageWriteParam param = writer.getDefaultWriteParam();
IIOMetadata streamMetadata = writer.getDefaultStreamMetadata(param);
writer.write(streamMetadata, iioImage, param);
writer.dispose();
bytes = new byte[toIntExact(ios.length())*2];
ios.read(bytes);
bytes = trim(bytes);
if(bytes.length == 0)
bytes = null;
}
}
if(bytes == null) {
InputStream is = ImageConverter.biToIs(resizedImage, fileType);
imgUri = getService().getFileStorageManagementService().getActiveFileStorageService().storeFile(is, "."+fileType, new Long(is.available()));
is.close();
}else {
ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
imgUri = getService().getFileStorageManagementService().getActiveFileStorageService().storeFile(byteStream, "."+fileType, new Long(byteStream.available()));
byteStream.close();
}
} catch (IOException | NoCorrespondingServiceRegisteredException | OperationFailedException | InvalidPropertiesException e1) {
e1.printStackTrace();
}
resizedImageObject.put("URI", imgUri.toString());
resizedImageObject.put("Width", resizedImage.getWidth());
resizedImageObject.put("Height", resizedImage.getHeight());
array.add(resizedImageObject);
}
static byte[] trim(byte[] bytes)
{
int i = bytes.length - 1;
while (i >= 0 && bytes[i] == 0)
{
--i;
}
return Arrays.copyOf(bytes, i + 1);
}
}
@@ -6,27 +6,14 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.commons.codec.binary.Base64;
public class ImageConverter {
public static String resizeAndConvertToBase64(InputStream is, int minWidth, int maxWidth, int minHeight,
int maxHeight, String imageFormat, boolean upsize) {
BufferedImage img = isToBi(is);
if(img.getWidth()>maxWidth || img.getHeight() > maxHeight || (upsize && (img.getWidth() < minWidth || img.getHeight() < minHeight))) {
int[] dimensions = calculateActualDimensions(img.getWidth(), img.getHeight(), minWidth, maxWidth, minHeight,
maxHeight, upsize);
if(dimensions != null) {
img = resize(img, dimensions[0], dimensions[1]);
return convertToBase64(biToBy(img, imageFormat));
}else {
return null;
}
}else {
return null;
}
}
private static int[] calculateActualDimensions(double width, double height, double minWidth, double maxWidth, double minHeight,
double maxHeight, boolean upsize) {
@@ -125,5 +112,14 @@ public class ImageConverter {
g.dispose();
return resizedImage;
}
public static void splitSizeTags(Map<String,Boolean> sizeTags, List<String> resizeTags, List<String> notResizeSizeTags) {
for(Object tagKey : sizeTags.keySet()) {
if(sizeTags.get(tagKey)) {
resizeTags.add((String)tagKey);//size tags, that have the resize checkBox checked
}else{
notResizeSizeTags.add((String)tagKey);//size tags, that not have the resize checkBox checked
}
}
}
}
@@ -1,7 +1,8 @@
package com.sap.sse.gwt.client.controls.listedit;
import java.util.List;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Grid;
@@ -24,14 +25,14 @@ public abstract class GenericStringListInlineEditorWithCheckboxesComposite<Value
private List<CheckBox> checkBoxes;
private Label checkBoxTopLabel;
private ValueChangeHandler<Boolean> checkBoxValueChangeHandler;
private ClickHandler checkBoxClickHandler;
public ExpandedUi(StringMessages stringMessages, ImageResource removeImage, List<String> suggestValues,
String placeholderTextForAddTextbox, int textBoxSize, List<CheckBox> checkBoxes, Label checkBoxTopLabel, ValueChangeHandler<Boolean> checkBoxValueChangeHandler) {
String placeholderTextForAddTextbox, int textBoxSize, List<CheckBox> checkBoxes, Label checkBoxTopLabel, ClickHandler clickHandler) {
super(stringMessages, removeImage, suggestValues, placeholderTextForAddTextbox, textBoxSize);
this.checkBoxes = checkBoxes;
this.checkBoxTopLabel = checkBoxTopLabel;
this.checkBoxValueChangeHandler = checkBoxValueChangeHandler;
this.checkBoxClickHandler = clickHandler;
}
@@ -43,18 +44,12 @@ public abstract class GenericStringListInlineEditorWithCheckboxesComposite<Value
expandedValuesGrid.setWidget(expandedValuesGrid.getRowCount()-1, 2, checkBox);
checkBox.setVisible(false);
checkBox.getElement().getStyle().setBackgroundColor("red");
checkBox.addValueChangeHandler(checkBoxValueChangeHandler);
/*checkBox.addDomHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if(checkBox.getValue()) {
checkBox.getElement().getStyle().clearBackgroundColor();
}else {
checkBox.getElement().getStyle().setBackgroundColor("red");
}
}
}, ClickEvent.getType());*/
checkBox.addClickHandler(checkBoxClickHandler);
}
@Override
public void onRowRemoved() {
refresh();
}
@Override