/** * Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0/ * * or in the "LICENSE" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions * and limitations under the License. */ package awslabs.lab51; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import com.amazonaws.AmazonServiceException; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.regions.Region; import com.amazonaws.regions.Regions; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient; import com.amazonaws.services.dynamodbv2.model.AttributeDefinition; import com.amazonaws.services.dynamodbv2.model.AttributeValue; import com.amazonaws.services.dynamodbv2.model.Condition; import com.amazonaws.services.dynamodbv2.model.CreateTableRequest; import com.amazonaws.services.dynamodbv2.model.DeleteTableRequest; import com.amazonaws.services.dynamodbv2.model.DescribeTableRequest; import com.amazonaws.services.dynamodbv2.model.DescribeTableResult; import com.amazonaws.services.dynamodbv2.model.KeySchemaElement; import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput; import com.amazonaws.services.dynamodbv2.model.PutItemRequest; import com.amazonaws.services.dynamodbv2.model.QueryRequest; import com.amazonaws.services.dynamodbv2.model.ScanRequest; import com.amazonaws.services.dynamodbv2.model.TableDescription; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; /** * Project: Lab5.1 */ public abstract class SolutionCode implements ILabCode, IOptionalLabCode { private Lab51 labController; public Lab51 getLabController() { return labController; } public SolutionCode(Lab51 lab) { labController = lab; } @Override public String getUrlForItem(AmazonS3Client s3Client, String key, String bucket) { Date nowPlusTwoMinutes = new Date(System.currentTimeMillis() + 120000L); // Construct a GeneratePresignedUrlRequest object for the provided object. GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucket, key); // Set the expiration value in the request to the nowPlusOneHour object // (this specifies a time one hour from now). generatePresignedUrlRequest.setExpiration(nowPlusTwoMinutes); // Submit the request using the generatePresignedUrl method of the s3Client object. URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest); // Return the URL as a string. return url.toString(); } @Override public List<Map<String, AttributeValue>> getImageItems(AmazonDynamoDBClient dynamoDbClient) { try { String tableName = System.getProperty("SESSIONTABLE"); String keyPrefix = System.getProperty("PARAM3"); ScanRequest scanRequest = new ScanRequest(tableName).withSelect("ALL_ATTRIBUTES"); if (!keyPrefix.isEmpty()) { Map<String, Condition> scanFilter = new HashMap<String, Condition>(); scanFilter.put("Key", new Condition().withAttributeValueList(new AttributeValue().withS(keyPrefix)) .withComparisonOperator("BEGINS_WITH")); scanRequest.withScanFilter(scanFilter); } return dynamoDbClient.scan(scanRequest).getItems(); } catch (Exception ex) { labController.logMessageToPage("getImageItems Error: " + ex.getMessage() + ":" + ex.getStackTrace()); return null; } } @Override public AmazonS3Client createS3Client(AWSCredentials credentials) { Region region = Region.getRegion(Regions.fromName(System.getProperty("REGION"))); AmazonS3Client client = new AmazonS3Client(); client.setRegion(region); return client; } @Override public AmazonDynamoDBClient createDynamoDbClient(AWSCredentials credentials) { Region region = Region.getRegion(Regions.fromName(System.getProperty("REGION"))); AmazonDynamoDBClient client = new AmazonDynamoDBClient(); client.setRegion(region); return client; } @Override public void addItemsToPage(AmazonS3Client s3Client, List<Map<String, AttributeValue>> items) { for (Map<String, AttributeValue> item : items) { AttributeValue key, bucket; if (item.containsKey("Key") && item.containsKey("Bucket")) { key = item.get("Key"); bucket = item.get("Bucket"); String itemUrl = getUrlForItem(s3Client, key.getS(), bucket.getS()); labController.addImageToPage(itemUrl, bucket.getS(), key.getS()); } } } @Override public Boolean isImageInDynamo(AmazonDynamoDBClient dynamoDbClient, String tableName, String key) { QueryRequest queryRequest = new QueryRequest(tableName).withConsistentRead(true); queryRequest.addKeyConditionsEntry("Key", new Condition().withComparisonOperator("EQ").withAttributeValueList(new AttributeValue(key))); return (dynamoDbClient.query(queryRequest).getCount() > 0); } @Override public Boolean validateSchema(TableDescription tableDescription) { if (tableDescription == null) { labController.logMessageToPage("Null table description passed to validation method."); return false; } if (!tableDescription.getTableStatus().equals("ACTIVE")) { labController.logMessageToPage("Table is not active."); return false; } if (tableDescription.getAttributeDefinitions() == null || tableDescription.getKeySchema() == null) { labController.logMessageToPage("Schema doesn't match."); return false; } for (AttributeDefinition attributeDefinition : tableDescription.getAttributeDefinitions()) { String attributeName = attributeDefinition.getAttributeName(); if (attributeName.equals("Key") || attributeName.equals("Bucket")) { if (!attributeDefinition.getAttributeType().equals("S")) { // We have a matching attribute, but the type is wrong. labController.logMessageToPage(attributeDefinition.getAttributeName() + " attribute is wrong type in attribute definition."); return false; } } } // If we've gotten here, the attributes are good. Now check the key schema. if (tableDescription.getKeySchema().size() != 2) { labController.logMessageToPage("Wrong number of elements in the key schema."); return false; } for (KeySchemaElement keySchemaElement : tableDescription.getKeySchema()) { String attributeName = keySchemaElement.getAttributeName(); if (attributeName.equals("Key")) { if (!keySchemaElement.getKeyType().equals("HASH")) { // We have a matching attribute, but the type is wrong. labController.logMessageToPage("Key attribute is wrong type in key schema."); return false; } } else if (attributeName.equals("Bucket")) { if (!keySchemaElement.getKeyType().equals("RANGE")) { // We have a matching attribute, but the type is wrong. labController.logMessageToPage("Bucket attribute is wrong type in key schema."); return false; } } else { labController.logMessageToPage("Unexpected attribute (" + keySchemaElement.getAttributeName() + ") in the key schema."); } } labController.logMessageToPage("Table schema is valid."); // We've passed our checks. return true; } @Override public TableDescription getTableDescription(AmazonDynamoDBClient ddbClient, String tableName) { try { DescribeTableRequest describeTableRequest = new DescribeTableRequest().withTableName(tableName); DescribeTableResult describeTableResult = ddbClient.describeTable(describeTableRequest); return describeTableResult.getTable(); } catch (AmazonServiceException ase) { // If the table isn't found, there's no problem. // If the error is something else, re-throw the exception to bubble it up to the caller. if (!ase.getErrorCode().equals("ResourceNotFoundException")) { throw ase; } return null; } } @Override public String getTableStatus(AmazonDynamoDBClient ddbClient, String tableName) { TableDescription tableDescription = getTableDescription(ddbClient, tableName); if (tableDescription == null) { return "NOTFOUND"; } return tableDescription.getTableStatus(); } @Override public void waitForStatus(AmazonDynamoDBClient ddbClient, String tableName, String status) { while (!getTableStatus(ddbClient, tableName).equals(status)) { // Sleep for one second. try { Thread.sleep(1000); } catch (InterruptedException e) { // Just gobble up the exception. } } } @Override public void deleteTable(AmazonDynamoDBClient ddbClient, String tableName) { ddbClient.deleteTable(new DeleteTableRequest().withTableName(tableName)); } @Override public void addImage(AmazonDynamoDBClient dynamoDbClient, String tableName, AmazonS3Client s3Client, String bucketName, String imageKey, String filePath) { try { File file = new File(filePath); if (file.exists()) { s3Client.putObject(bucketName, imageKey, file); PutItemRequest putItemRequest = new PutItemRequest().withTableName(tableName); putItemRequest.addItemEntry("Key", new AttributeValue(imageKey)); putItemRequest.addItemEntry("Bucket", new AttributeValue(bucketName)); dynamoDbClient.putItem(putItemRequest); labController.logMessageToPage("Added imageKey: " + imageKey); } else { labController.logMessageToPage("Image doesn't exist on disk. Skipped: " + imageKey + "[" + filePath + "]"); } } catch (Exception ex) { labController.logMessageToPage("addImage Error: " + ex.getMessage()); } } @Override public void buildTable(AmazonDynamoDBClient ddbClient, String tableName) { CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName); createTableRequest.setAttributeDefinitions(new ArrayList<AttributeDefinition>()); // Define attributes createTableRequest.getAttributeDefinitions().add( new AttributeDefinition().withAttributeName("Key").withAttributeType("S")); createTableRequest.getAttributeDefinitions().add( new AttributeDefinition().withAttributeName("Bucket").withAttributeType("S")); // Define key schema createTableRequest.setKeySchema(new ArrayList<KeySchemaElement>()); createTableRequest.getKeySchema().add(new KeySchemaElement().withAttributeName("Key").withKeyType("HASH")); createTableRequest.getKeySchema().add(new KeySchemaElement().withAttributeName("Bucket").withKeyType("RANGE")); // Define provisioned throughput createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits(5L) .withWriteCapacityUnits(5L)); // Submit create request ddbClient.createTable(createTableRequest); // Pause until the table is active waitForStatus(ddbClient, tableName, "ACTIVE"); labController.logMessageToPage("Table created and active."); } }