Java tutorial
/***************************************************************************** * Copyright Shapeways, Inc. (c) 2011 * Java Source * * This source is licenses under the Apache License, version 2.0 * * http://www.apache.org/licenses/LICENSE-2.0.html * * ****************************************************************************/ package shapeways.api.robocreator; // Standard imports import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.regions.Region; import com.amazonaws.regions.RegionUtils; import com.amazonaws.services.sqs.AmazonSQS; import com.amazonaws.services.sqs.AmazonSQSClient; import com.amazonaws.services.sqs.model.Message; import com.google.gson.Gson; import shapeways.api.JSONMunger; import shapeways.api.ShapewaysAPI; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.URL; import java.net.URLConnection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; /** * Base class for RoboCreator examples * * @author Alan Hudson */ public abstract class BaseRoboCreator extends HttpServlet implements ModelGenerator, SQSQueueListener { private static final boolean DEBUG = true; private static final int DEFAULT_POLL_FREQUENCY = 5000; private static final String QUEUE_PREPEND = "RoboCreator_"; private String shapewaysHost; // Shapeways Credentials private String consumerKey; private String consumerSecret; private String accessToken; private String accessSecret; // Internal service queue for threads private ThreadPoolExecutor threadPool; // Queue name for messages across machines. private String serviceQueue; private String queueUrl; private Integer visibilityTimeout; private int pollFrequency; protected AmazonSQS sqs; private QueueReceiver listener; private int threads; /** * Initialize the servlet. Sets up the base directory properties for finding * stuff later on. */ public void init() throws ServletException { // DirectorServlet overrides all but this method. If your making changes here // you might need to change that class as well ServletConfig config = getServletConfig(); ServletContext ctx = config.getServletContext(); serviceQueue = getInitParameter("ServiceQueue"); if (serviceQueue == null) { System.out.println("ServiceQueue is null, add entry to web.xml"); } shapewaysHost = getInitParameter("ShapewaysHost"); System.out.println("ShapewaysHost: " + shapewaysHost); if (shapewaysHost == null) { shapewaysHost = ShapewaysAPI.getShapewaysHost(); } String instanceType = getInstanceMetadata("instance-type", "localhost"); // 0 = number of processors. > 0 specific number. Default is 1 String num_threads_st = getInitParameter("NumThreads"); Gson gson = new Gson(); Map<String, Number> threadsMap = new HashMap<String, Number>(); try { threadsMap = gson.fromJson(num_threads_st, Map.class); } catch (Exception e) { System.out.println( "Cannot parse threads: " + serviceQueue + ". Should be map of instanceType to numThreads"); System.out.println("numThreads: " + num_threads_st); e.printStackTrace(); } threads = threadsMap.get(instanceType).intValue(); if (threads == 0) { threads = Runtime.getRuntime().availableProcessors(); ; } threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(threads); consumerKey = getInitParameter("ShapewaysConsumerKey"); consumerSecret = getInitParameter("ShapewaysConsumerSecret"); accessToken = getInitParameter("ShapewaysAccessToken"); accessSecret = getInitParameter("ShapewaysAccessSecret"); String proxyType = getInitParameter("ProxyType"); String proxyHost = getInitParameter("ProxyHost"); String proxyPort = getInitParameter("ProxyPort"); if (proxyHost != null) { // TODO: think about selectors as this is per JVM System.out.println("Configuring proxy: " + proxyHost + ":" + proxyPort); Properties systemSettings = System.getProperties(); systemSettings.put("proxySet", "true"); if (proxyType.equalsIgnoreCase("SOCKS")) { systemSettings.put("socksProxyHost", proxyHost); systemSettings.put("socksProxyPort", proxyPort); } else { systemSettings.put("http.proxyHost", proxyHost); systemSettings.put("http.proxyPort", proxyPort); } } String awsAccessKey = getInitParameter("AWSAccessKey"); String awsAccessSecret = getInitParameter("AWSAccessSecret"); String awsRegion = getInitParameter("AWSRegion"); String st = getInitParameter("AWSSQSVisibilityTimeout"); if (st != null) { visibilityTimeout = Integer.parseInt(st); } st = getInitParameter("AWSSQSMessagePollFrequency"); if (st != null) { pollFrequency = Integer.parseInt(st); } else { pollFrequency = DEFAULT_POLL_FREQUENCY; } // TODO: Not certain we want to do these here as it delays deploy and might stop all deploys if AWS is down. // Switch to a threaded runnable or maybe just add the job to the threadPool we have. sqs = new AmazonSQSClient(new BasicAWSCredentials(awsAccessKey, awsAccessSecret)); Region region = RegionUtils.getRegion(awsRegion); sqs.setRegion(region); threadPool.submit(new SQSCreateQueueTask(sqs, QUEUE_PREPEND + serviceQueue, visibilityTimeout, this)); } @Override public void destroy() { listener.setTerminate(true); threadPool.shutdown(); } @Override public void queueCreated(String name, String url) { queueUrl = url; listener = new QueueReceiver(threads, sqs, queueUrl, pollFrequency, threadPool, this); listener.start(); } @Override public void queueFailed(String name, Exception e) { } @Override public void messagesReceived(List<Message> messages) { for (Message msg : messages) { String json = msg.getBody(); if (DEBUG) { System.out.println("Received Msg: " + json); } Gson gson = new Gson(); Map params = gson.fromJson(json, Map.class); Integer modelId = JSONMunger.toInteger(params.get("modelId")); ModelUploader uploader = new ModelUploader(shapewaysHost, consumerKey, consumerSecret, accessToken, accessSecret); ModelGeneratorRunner runner = new ModelGeneratorRunner(this, params, uploader, modelId, "cube.x3dv", X3DEncodingType.X3DV, sqs, queueUrl, msg.getReceiptHandle()); threadPool.submit(runner); } } /** * Get the public facing hostname for this machine. Uses AWS metadata service. */ protected String getInstanceMetadata(String name, String defValue) { ByteArrayOutputStream baos = null; BufferedOutputStream bout = null; String ret_val = null; InputStream is = null; try { URL url = new URL("http://169.254.169.254/latest/meta-data/" + name); URLConnection urlConn = url.openConnection(); urlConn.setConnectTimeout(5000); urlConn.setReadTimeout(15000); urlConn.setAllowUserInteraction(false); urlConn.setDoOutput(true); is = new BufferedInputStream(urlConn.getInputStream()); baos = new ByteArrayOutputStream(); bout = new BufferedOutputStream(baos, 1024); int buffSize = 8 * 1024; byte data[] = new byte[buffSize]; int count; while ((count = is.read(data, 0, buffSize)) >= 0) { baos.write(data, 0, count); } ret_val = baos.toString(); } catch (Exception e) { // ignore //e.printStackTrace(); } finally { try { bout.close(); is.close(); } catch (Exception e) { // ignore } } if (ret_val == null) { ret_val = defValue; } return ret_val; } }