shapeways.api.robocreator.BaseRoboCreator.java Source code

Java tutorial

Introduction

Here is the source code for shapeways.api.robocreator.BaseRoboCreator.java

Source

/*****************************************************************************
 *                        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;
    }

}