diff --git a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamResourceTest.java b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java similarity index 94% rename from java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamResourceTest.java rename to java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java index e3ee499b227..1462ea0702e 100644 --- a/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamResourceTest.java +++ b/java/com.sap.sailing.server.gateway.test/src/com/sap/sailing/server/gateway/test/jaxrs/TeamImageTest.java @@ -27,14 +27,14 @@ import com.sap.sailing.domain.base.impl.NationalityImpl; import com.sap.sailing.domain.base.impl.PersonImpl; import com.sap.sailing.domain.base.impl.TeamImpl; import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; -import com.sap.sailing.server.gateway.jaxrs.api.TeamResource; +import com.sap.sailing.server.gateway.jaxrs.api.CompetitorsResource; import com.sap.sse.filestorage.FileStorageService; import com.sap.sse.filestorage.InvalidPropertiesException; import com.sap.sse.filestorage.OperationFailedException; import com.sap.sse.filestorage.testsupport.AmazonS3TestSupport; import com.sun.jersey.core.header.FormDataContentDisposition; -public class TeamResourceTest extends AbstractJaxRsApiTest { +public class TeamImageTest extends AbstractJaxRsApiTest { private static final String name = "Heiko KRĂ–GER"; private static final String id = "af855a56-9726-4a9c-a77e-da955bd289be"; private static final String boatClassName = "49er"; @@ -60,7 +60,7 @@ public class TeamResourceTest extends AbstractJaxRsApiTest { public void storeAndRemoveTeamImage() throws URISyntaxException, ParseException, MalformedURLException, IOException, OperationFailedException, InvalidPropertiesException { //set team image - TeamResource r = spyResource(new TeamResource()); + CompetitorsResource r = spyResource(new CompetitorsResource()); URL fileUrl = getClass().getResource("/" + teamImageFile); URI fileUri = new URI(fileUrl.toString()); long length = new File(fileUri).length(); diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java index 6543ea3bd5f..0f2c70e85f1 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/CompetitorsResource.java @@ -1,9 +1,18 @@ package com.sap.sailing.server.gateway.jaxrs.api; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; @@ -11,12 +20,26 @@ import javax.ws.rs.core.Response.Status; import org.json.simple.JSONObject; import com.sap.sailing.domain.base.Competitor; +import com.sap.sailing.domain.base.CompetitorStore; +import com.sap.sailing.domain.base.Team; +import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; +import com.sap.sailing.server.RacingEventService; import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; +import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; +import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; +import com.sap.sse.filestorage.InvalidPropertiesException; +import com.sap.sse.filestorage.OperationFailedException; +import com.sun.jersey.core.header.FormDataContentDisposition; +import com.sun.jersey.multipart.FormDataParam; @Path("/v1/competitors") public class CompetitorsResource extends AbstractSailingServerResource { + private static final Logger logger = Logger.getLogger(CompetitorsResource.class.getName()); + private static final int MAX_SIZE_IN_MB = 5; + public static JSONObject getCompetitorJSON(Competitor competitor) { - //see http://wiki.sapsailing.com/wiki/tracking-app-api-v1-draft#Competitor-Information + // see http://wiki.sapsailing.com/wiki/tracking-app-api-v1-draft#Competitor-Information JSONObject json = new JSONObject(); json.put("id", competitor.getId().toString()); json.put("name", competitor.getName()); @@ -27,7 +50,7 @@ public class CompetitorsResource extends AbstractSailingServerResource { return json; } - + @GET @Produces("application/json;charset=UTF-8") @Path("{competitorId}") @@ -37,12 +60,83 @@ public class CompetitorsResource extends AbstractSailingServerResource { competitorIdAsString); if (competitor == null) { response = Response.status(Status.NOT_FOUND) - .entity("Could not find a competitor with id '" + competitorIdAsString + "'.").type(MediaType.TEXT_PLAIN) - .build(); + .entity("Could not find a competitor with id '" + competitorIdAsString + "'.") + .type(MediaType.TEXT_PLAIN).build(); } else { String jsonString = getCompetitorJSON(competitor).toJSONString(); response = Response.ok(jsonString, MediaType.APPLICATION_JSON).build(); } return response; } + + @GET + @Produces("application/json;charset=UTF-8") + @Path("{competitor-id}/team") + public Response getTeam(@PathParam("competitor-id") String competitorId) { + Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorId); + + if (competitor == null) { + return Response.status(Status.NOT_FOUND) + .entity("Could not find a competitor with id '" + competitorId + "'.").type(MediaType.TEXT_PLAIN) + .build(); + } + + Team team = competitor.getTeam(); + + if (team == null) { + return Response.status(Status.NOT_FOUND) + .entity("Could not find a team associated with competitor '" + competitorId + "'.") + .type(MediaType.TEXT_PLAIN).build(); + } + + TeamJsonSerializer teamJsonSerializer = new TeamJsonSerializer(new PersonJsonSerializer( + new NationalityJsonSerializer())); + JSONObject teamJson = teamJsonSerializer.serialize(team); + String json = teamJson.toJSONString(); + + return Response.ok(json, MediaType.APPLICATION_JSON).build(); + } + + @POST + @Consumes(MediaType.MULTIPART_FORM_DATA) + @Produces("application/json;charset=UTF-8") + @Path("{competitor-id}/image") + public String setTeamImage(@PathParam("competitor-id") String competitorId, + @FormDataParam("file") InputStream uploadedInputStream, + @FormDataParam("file") FormDataContentDisposition fileDetails) { + + RacingEventService service = getService(); + CompetitorStore store = service.getCompetitorStore(); + Competitor competitor = store.getExistingCompetitorByIdAsString(competitorId); + if (competitor == null) { + logger.log(Level.INFO, "Could not find competitor to store image for: " + competitorId); + throw new WebApplicationException(Response.status(Status.BAD_REQUEST) + .entity("Could not find competitor with id " + competitorId).type(MediaType.TEXT_PLAIN).build()); + } + + URI imageUri; + try { + String fileName = fileDetails.getFileName(); + long sizeInBytes = fileDetails.getSize(); + + if (sizeInBytes > 1024 * 1024 * MAX_SIZE_IN_MB) { + throw new WebApplicationException(Response.status(Status.BAD_REQUEST) + .entity("Image is larger than " + MAX_SIZE_IN_MB + "MB").build()); + } + + imageUri = getService().getFileStorageService().storeFile(uploadedInputStream, fileName, sizeInBytes); + } catch (IOException | OperationFailedException | InvalidPropertiesException e) { + logger.log(Level.WARNING, "Could not store competitor image", e); + throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR) + .entity("Could not store competitor image").type(MediaType.TEXT_PLAIN).build()); + } + + getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), + competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri); + logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); + + JSONObject result = new JSONObject(); + result.put(DeviceMappingConstants.JSON_TEAM_IMAGE_URI, imageUri.toString()); + return result.toString(); + } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java index f0b0314e23a..0002c3620a3 100644 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java +++ b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/RestApiApplication.java @@ -17,7 +17,6 @@ public class RestApiApplication extends Application { classes.add(SearchResource.class); classes.add(GPSFixesResource.class); classes.add(CompetitorsResource.class); - classes.add(TeamResource.class); return classes; } } diff --git a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TeamResource.java b/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TeamResource.java deleted file mode 100644 index db25428d5f9..00000000000 --- a/java/com.sap.sailing.server.gateway/src/com/sap/sailing/server/gateway/jaxrs/api/TeamResource.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.sap.sailing.server.gateway.jaxrs.api; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - -import org.json.simple.JSONObject; - -import com.sap.sailing.domain.base.Competitor; -import com.sap.sailing.domain.base.CompetitorStore; -import com.sap.sailing.domain.base.Team; -import com.sap.sailing.domain.common.racelog.tracking.DeviceMappingConstants; -import com.sap.sailing.server.RacingEventService; -import com.sap.sailing.server.gateway.jaxrs.AbstractSailingServerResource; -import com.sap.sailing.server.gateway.serialization.impl.NationalityJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.PersonJsonSerializer; -import com.sap.sailing.server.gateway.serialization.impl.TeamJsonSerializer; -import com.sap.sse.filestorage.InvalidPropertiesException; -import com.sap.sse.filestorage.OperationFailedException; -import com.sun.jersey.core.header.FormDataContentDisposition; -import com.sun.jersey.multipart.FormDataParam; - -@Path("/v1/team") -public class TeamResource extends AbstractSailingServerResource { - - private static final Logger logger = Logger.getLogger(TeamResource.class.getName()); - - @GET - @Produces("application/json;charset=UTF-8") - @Path("{competitor-id}") - public Response getTeam(@PathParam("competitor-id") String competitorId) { - Competitor competitor = getService().getCompetitorStore().getExistingCompetitorByIdAsString(competitorId); - - if (competitor == null) { - return Response.status(Status.NOT_FOUND) - .entity("Could not find a competitor with id '" + competitorId + "'.").type(MediaType.TEXT_PLAIN) - .build(); - } - - Team team = competitor.getTeam(); - - if (team == null) { - return Response.status(Status.NOT_FOUND) - .entity("Could not find a team associated with competitor '" + competitorId + "'.") - .type(MediaType.TEXT_PLAIN).build(); - } - - TeamJsonSerializer teamJsonSerializer = new TeamJsonSerializer(new PersonJsonSerializer( - new NationalityJsonSerializer())); - JSONObject teamJson = teamJsonSerializer.serialize(team); - String json = teamJson.toJSONString(); - - return Response.ok(json, MediaType.APPLICATION_JSON).build(); - } - - @POST - @Consumes(MediaType.MULTIPART_FORM_DATA) - @Produces("application/json;charset=UTF-8") - @Path("{competitor-id}/image") - public String setTeamImage(@PathParam("competitor-id") String competitorId, - @FormDataParam("file") InputStream uploadedInputStream, - @FormDataParam("file") FormDataContentDisposition fileDetails) { - RacingEventService service = getService(); - CompetitorStore store = service.getCompetitorStore(); - Competitor competitor = store.getExistingCompetitorByIdAsString(competitorId); - if (competitor == null) { - logger.log(Level.INFO, "Could not find competitor to store image for: " + competitorId); - throw new WebApplicationException(Response.status(Status.BAD_REQUEST) - .entity("Could not find competitor with id " + competitorId).type(MediaType.TEXT_PLAIN).build()); - } - - URI imageUri; - try { - String fileName = fileDetails.getFileName(); - long sizeInBytes = fileDetails.getSize(); - imageUri = getService().getFileStorageService().storeFile(uploadedInputStream, fileName, sizeInBytes); - } catch (IOException | OperationFailedException | InvalidPropertiesException e) { - logger.log(Level.WARNING, "Could not store competitor image", e); - throw new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR) - .entity("Could not store competitor image").type(MediaType.TEXT_PLAIN).build()); - } - - getService().getCompetitorStore().updateCompetitor(competitorId, competitor.getName(), competitor.getColor(), - competitor.getBoat().getSailID(), competitor.getTeam().getNationality(), imageUri); - logger.log(Level.INFO, "Set team image for competitor " + competitor.getName()); - - JSONObject result = new JSONObject(); - result.put(DeviceMappingConstants.JSON_TEAM_IMAGE_URI, imageUri.toString()); - return result.toString(); - } -} diff --git a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java index 4c0fb558a13..70528aa689f 100644 --- a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java +++ b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/AmazonS3FileStorageServiceImpl.java @@ -91,7 +91,8 @@ public class AmazonS3FileStorageServiceImpl implements FileStorageService { private URI getUri(String key) { try { - return new URI(retrievalProtocol, bucketName.getValue() + "." + baseUrl, "/" + key, null); + // FIXME: region is missing s3-... see: http://stackoverflow.com/questions/10975475/amazon-s3-upload-file-and-get-url + return new URI(retrievalProtocol, baseUrl, "/" + bucketName.getValue() + "/" + key, null); } catch (URISyntaxException e) { logger.log(Level.WARNING, "Could not create URI for uploaded file with key " + key, e); return null; @@ -128,7 +129,6 @@ public class AmazonS3FileStorageServiceImpl implements FileStorageService { } logger.info("Removed file " + uri); } - @Override public Property[] getProperties() { return new Property[] { accessId, accessKey, bucketName }; diff --git a/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/LocalFileStorageServiceImpl.java b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/LocalFileStorageServiceImpl.java new file mode 100644 index 00000000000..b492306aaf3 --- /dev/null +++ b/java/com.sap.sse.filestorage/src/com/sap/sse/filestorage/impl/LocalFileStorageServiceImpl.java @@ -0,0 +1,112 @@ +package com.sap.sse.filestorage.impl; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.sap.sse.filestorage.FileStorageService; +import com.sap.sse.filestorage.InvalidPropertiesException; +import com.sap.sse.filestorage.Property; + +public class LocalFileStorageServiceImpl implements FileStorageService { + private static final Logger logger = Logger.getLogger(LocalFileStorageServiceImpl.class.getName()); + + private static final String host = "media.sapsailing.com"; + private static final String path = "images"; + private static final String retrievalProtocol = "http"; + + @Override + public URI storeFile(InputStream is, String originalFileName, long lengthInBytes) throws IOException { + OutputStream outputStream = null; + String pathToFile = path + "/" + getKey(originalFileName); + + outputStream = new FileOutputStream(new File(pathToFile)); + + try { + int read = 0; + byte[] bytes = new byte[1024]; + + while ((read = is.read(bytes)) != -1) { + outputStream.write(bytes, 0, read); + } + + } finally { + if (is != null) { + is.close(); + } + if (outputStream != null) { + outputStream.flush(); + outputStream.close(); + } + } + + return getUri(pathToFile); + } + + private static String getKey(String originalFileName) { + String key = UUID.randomUUID().toString(); + if (originalFileName != null) { + String ending = originalFileName.substring(originalFileName.lastIndexOf(".")); + key += ending; + // key += "/" + originalFileName; + } + return key; + } + + private static URI getUri(String pathToFile) { + try { + return new URI(retrievalProtocol, host, pathToFile, null); + } catch (URISyntaxException e) { + logger.log(Level.WARNING, "Could not create URI for uploaded file with path " + pathToFile, e); + return null; + } + } + + @Override + public void removeFile(URI uri) { + String filePath = uri.getPath(); + File file = new File(filePath); + + if(!file.delete()){ + logger.warning("Could not delete file with path "+filePath); + } + } + + @Override + public Property[] getProperties() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setProperty(String name, String value) throws IllegalArgumentException { + // TODO Auto-generated method stub + + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void testProperties() throws InvalidPropertiesException { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff --git a/mobile/com.sap.sailing.android.shared/.settings/org.eclipse.jdt.core.prefs b/mobile/com.sap.sailing.android.shared/.settings/org.eclipse.jdt.core.prefs index 980b98c1d5f..8505da607cf 100755 --- a/mobile/com.sap.sailing.android.shared/.settings/org.eclipse.jdt.core.prefs +++ b/mobile/com.sap.sailing.android.shared/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/mobile/com.sap.sailing.android.tracking.app/.settings/org.eclipse.jdt.core.prefs b/mobile/com.sap.sailing.android.tracking.app/.settings/org.eclipse.jdt.core.prefs index d17b6724d17..ef8a789ca02 100644 --- a/mobile/com.sap.sailing.android.tracking.app/.settings/org.eclipse.jdt.core.prefs +++ b/mobile/com.sap.sailing.android.tracking.app/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/mobile/com.sap.sailing.racecommittee.app/.settings/org.eclipse.jdt.core.prefs b/mobile/com.sap.sailing.racecommittee.app/.settings/org.eclipse.jdt.core.prefs index d17b6724d17..ef8a789ca02 100644 --- a/mobile/com.sap.sailing.racecommittee.app/.settings/org.eclipse.jdt.core.prefs +++ b/mobile/com.sap.sailing.racecommittee.app/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,12 @@ eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve -org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.compliance=1.6 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -org.eclipse.jdt.core.compiler.source=1.7 +org.eclipse.jdt.core.compiler.source=1.6