Amazon CloudFront
Developer Guide (API Version 2012-05-05)
Print this pageEmail this pageGo to the ForumsView the PDFShare this page on TwitterShare this page on FacebookBookmark this page on DeliciousSubmit this page to RedditSubmit this page to DiggDid this page help you?  Yes  No   Tell us about it...

Java Sample Code for Digital Element

The code example provided here obtains the country code that is associated with an end user's IP address and allows the user to access CloudFront content if the user is in a location where distribution is allowed. For the purposes of the example, the program is authorized to distribute the requested content to any country except Australia (country code AU).

GetCountryCodeServlet.java

GetCountryCodeServlet.java calls GetDigitalElementCountryCode.java, which is shown later in this article, to ask Digital Element for the country code that is associated with an end user's IP address. If the country code is not AU (Australia), GetCountryCodeServlet.java calls SignedUrl.java to create a signed URL that the end user can use to access a file in the CloudFront distribution.

/*
 * Copyright 2011 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.
 */

// Signed URLs for a private distribution
// Note that Java supports SSL certificates only in DER format, 
// so you will need to convert your PEM-formatted file to DER format. 
// To do this, you can use openssl:
// openssl pkcs8 -topk8 -nocrypt -in origin.pem -inform PEM -out new.der -outform DER 
// For the encoder to work correctly, you should also add the 
// bouncy castle jar to your project and then add the provider.ds.

import java.io.IOException;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class GetCountryCodeServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
   
   final String GEOAPIURL = "Digital Element URL";
   final String GEOAPITOKEN = "Digital Element user token";
   final String PATHTODER = "path to .der file";
   final String KEYPAIRID ="CloudFront key pair ID";
   final String HTTPORHTTPS = "https";
   final String CFDISTRIBUTION = "dxxxx.cloudfront.net";
   final String CFPATH = "CloudFront URL for file";
   // date and time that CloudFront's signed URL expires, 
   // in Coordinated Universal Time
   final String EXPIRETS = "2012-11-14T22:20:00.000Z";
   final String BLOCKEDCOUNTRY="AU";
       
   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   
      String ip = null;
      StringTokenizer st = null;
      PrintWriter out = response.getWriter();
      
      String headers = request.getHeader("X-FORWARDED-FOR");
      
      if (headers!= null){
         st = new StringTokenizer(headers,",");
         
         while (st.hasMoreTokens()) {
            ip = st.nextToken();
         }
      }
      
      //Get the client's IP addr in case X-Forwarded-IP header doesn't exist 
      
      if (ip == null) ip = request.getRemoteAddr();
             
      try {
         GetDigitalElementCountryCode country = new GetDigitalElementCountryCode( GEOAPIURL,GEOAPITOKEN );
         
         if ( !country.getCountry(ip).equalsIgnoreCase(BLOCKEDCOUNTRY)){
            
            SignedUrl myApp = new SignedUrl(KEYPAIRID,PATHTODER);
            out.println(myApp.getSignedHash(HTTPORHTTPS,CFDISTRIBUTION,CFPATH,EXPIRETS));

         }else {
            out.println("You cannot access this link.");
         }
      } catch (Exception e1) {
         e1.printStackTrace();
      }
   }
}

GetDigitalElementCountryCode.java

GetDigitalElementCountryCode.java sends Digital Element a request that includes an end user's IP address. The return value is a country code.

/*
 * Copyright 2011 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.
 */

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class GetDigitalElementCountryCode {

   private static String geoApiEndPoint;
   private static String apiToken;
   
   GetDigitalElementCountryCode(String mygeoApiEndPoint, String myapiToken){
      geoApiEndPoint = mygeoApiEndPoint;
      apiToken = myapiToken;
   }

    public String getCountry(String enduserIP) throws Exception {

      String geoApiURL = "http://"+geoApiEndPoint+"?u="+apiToken+"&ip="+enduserIP;

      DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
      Document doc = docBuilder.parse(geoApiURL);
      // normalize text representation
      doc.getDocumentElement ().normalize ();

      NodeList listOfPersons = doc.getElementsByTagName("response");
      Element el = (Element)listOfPersons.item(0);
      String country = el.getAttribute("edge-two-letter-country");
      
      return country;
   }
}

SignedUrl.java

SignedUrl.java creates a signed URL that the end user can use to access a file in the CloudFront distribution.

/*
 * Copyright 2011 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.
 */

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.Security;
import java.text.ParseException;

import org.jets3t.service.CloudFrontService;
import org.jets3t.service.CloudFrontServiceException;
import org.jets3t.service.utils.ServiceUtils;

public class SignedUrl {
   // Signed URLs for a private distribution
   // Note that Java supports SSL certificates only in DER format, 
   // so you need to convert your PEM-formatted file to DER format. 
   // To do this, you can use openssl:
   // openssl pkcs8 -topk8 -nocrypt -in origin.pem -inform PEM -out new.der -outform DER 
   // For the encoder to work correctly, you should also add the 
   // bouncy castle jar to your project and then add the provider.ds.
   
   private static String keyPairId;
   private static String privateKeyFilePath;
   
   SignedUrl(String mykeyPairId, String myprivateKeyFilePath){
      keyPairId = mykeyPairId;
      privateKeyFilePath = myprivateKeyFilePath;
   }
   
   public String getSignedHash(String protocol, String cfDistribution, String objectUri, String expTime) throws FileNotFoundException, IOException,
   CloudFrontServiceException, ParseException{
      
   Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

   // Convert your DER file into a byte array.

      byte[] derPrivateKey = ServiceUtils.readInputStreamToBytes(new FileInputStream(privateKeyFilePath));

   // Generate a "canned" signed URL to allow access to a 
   // specific distribution and object

   String signedUrlCanned = CloudFrontService.signUrlCanned(
       protocol+ "://" + cfDistribution + "/" + objectUri, // Resource URL or Path
       keyPairId,     // Certificate identifier, 
                      // an active trusted signer for the distribution
       derPrivateKey, // DER Private key data
       ServiceUtils.parseIso8601Date(expTime) // DateLessThan
       );
   
   return signedUrlCanned;
   }
}