com.elasticgrid.rest.ApplicationsResource.java Source code

Java tutorial

Introduction

Here is the source code for com.elasticgrid.rest.ApplicationsResource.java

Source

/**
 * Elastic Grid
 * Copyright (C) 2008-2010 Elastic Grid, LLC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.elasticgrid.rest;

import com.elasticgrid.cluster.ClusterManager;
import com.elasticgrid.model.Cluster;
import com.elasticgrid.model.internal.Applications;
import com.elasticgrid.utils.amazon.AWSUtils;
import com.elasticgrid.storage.Container;
import com.elasticgrid.storage.StorageException;
import com.elasticgrid.storage.StorageManager;
import com.elasticgrid.storage.spi.StorageEngine;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.ObjectWrapper;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.restlet.Context;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.ext.fileupload.RestletFileUpload;
import org.restlet.ext.freemarker.TemplateRepresentation;
import org.restlet.ext.jibx.JibxRepresentation;
import org.restlet.ext.wadl.DocumentationInfo;
import org.restlet.ext.wadl.MethodInfo;
import org.restlet.ext.wadl.RepresentationInfo;
import org.restlet.ext.wadl.WadlResource;
import org.restlet.resource.Representation;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ApplicationsResource extends WadlResource {
    private String clusterName;
    private String dropBucket;
    private Configuration config;
    private ClusterManager clusterManager;
    private StorageManager storageManager;
    private final Logger logger = Logger.getLogger(getClass().getName());

    @Override
    public void init(Context context, Request request, Response response) {
        super.init(context, request, response);
        clusterManager = RestJSB.getClusterManager();
        storageManager = RestJSB.getStorageManager();
        try {
            dropBucket = AWSUtils.getDropBucket();
        } catch (IOException e) {
            throw new IllegalStateException("Can't retrieve drop bucket", e);
        }
        // Allow modifications of this resource via POST requests
        setModifiable(true);
        // Declare the kind of representations supported by this resource
        getVariants().add(new Variant(MediaType.APPLICATION_XML));
        // Extract URI variables
        clusterName = (String) request.getAttributes().get("clusterName");
        // Setup FreeMarker template engine
        config = new Configuration();
        config.setObjectWrapper(ObjectWrapper.BEANS_WRAPPER);
        config.setTemplateLoader(new ClassTemplateLoader(getClass(), "/com/elasticgrid/rest"));
    }

    /**
     * Handle GET requests: describe all applications.
     */
    @Override
    public Representation represent(Variant variant) throws ResourceException {
        try {
            logger.log(Level.INFO, "Requested variant {0}", variant.getMediaType());
            Cluster cluster = clusterManager.cluster(clusterName);
            if (cluster == null)
                throw new ResourceException(Status.CLIENT_ERROR_NOT_FOUND, "Can't find cluster " + clusterName);
            logger.log(Level.INFO, "Found cluster {0}", cluster);

            if (MediaType.TEXT_HTML.equals(variant.getMediaType())
                    || MediaType.APPLICATION_XML.equals(variant.getMediaType())) {
                Map<String, Object> model = new HashMap<String, Object>();
                model.put("cluster", cluster);
                return new TemplateRepresentation("applications.ftl", config, model, MediaType.TEXT_HTML);
            } else {
                // return XML representation
                return new JibxRepresentation<Applications>(MediaType.APPLICATION_XML,
                        new Applications(cluster.getApplications()), "ElasticGridREST");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ResourceException(Status.SERVER_ERROR_SERVICE_UNAVAILABLE, e);
        }
    }

    /**
     * Handle POST requests: provision a new application.
     */
    @Override
    public void acceptRepresentation(Representation entity) throws ResourceException {
        super.acceptRepresentation(entity); //To change body of overridden methods use File | Settings | File Templates.
        try {
            StorageEngine storageEngine = storageManager.getPreferredStorageEngine();
            if (MediaType.MULTIPART_ALL.equals(entity.getMediaType(), true)
                    || MediaType.MULTIPART_FORM_DATA.equals(entity.getMediaType(), true)) {
                try {
                    DiskFileItemFactory factory = new DiskFileItemFactory();
                    factory.setSizeThreshold(1000240);
                    RestletFileUpload upload = new RestletFileUpload(factory);
                    List<FileItem> files = upload.parseRequest(getRequest());
                    logger.log(Level.INFO, "Found {0} items", files.size());
                    for (FileItem fi : files) {
                        if ("oar".equals(fi.getFieldName())) {
                            // download it as a temp file
                            File file = File.createTempFile("elastic-grid", "oar");
                            fi.write(file);
                            // upload it to storage container
                            logger.log(Level.INFO, "Uploading OAR ''{0}'' to {1}'s container ''{2}''",
                                    new Object[] { fi.getName(), storageEngine.getStorageName(), dropBucket });
                            Container container = storageEngine.findContainerByName(dropBucket);
                            try {
                                container.uploadStorable(file);
                            } catch (StorageException e) {
                                logger.log(Level.SEVERE,
                                        String.format("Could not upload OAR '%s' to %s's container '%s'",
                                                fi.getName(), storageEngine.getStorageName(), dropBucket),
                                        e);
                                throw new ResourceException(Status.SERVER_ERROR_INSUFFICIENT_STORAGE, e);
                            }
                        }
                    }
                    // Set the status of the response.
                    logger.info("Redirecting to " + getRequest().getOriginalRef());
                    getResponse().setLocationRef(getRequest().getOriginalRef().addSegment("??")); // todo: figure out the proper URL
                } catch (FileUploadException e) {
                    e.printStackTrace();
                    throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e);
                }
            } else if (new MediaType("application/oar").equals(entity.getMediaType())) {
                try {
                    // extract filename information
                    Form form = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
                    // upload it to storage container
                    String fileName = form.getFirstValue("x-filename");
                    logger.log(Level.INFO, "Uploading OAR ''{0}'' to {1}'s container ''{2}''",
                            new Object[] { fileName, storageEngine.getStorageName(), dropBucket });
                    Container container = storageEngine.findContainerByName(dropBucket);
                    try {
                        container.uploadStorable(fileName, entity.getStream(), "application/oar");
                    } catch (StorageException e) {
                        logger.log(Level.SEVERE, String.format("Could not upload OAR '%s' to %s's container '%s'",
                                fileName, storageEngine.getStorageName(), dropBucket), e);
                        throw new ResourceException(Status.SERVER_ERROR_INSUFFICIENT_STORAGE, e);
                    }
                    // Set the status of the response
                    logger.info("Redirecting to " + getRequest().getOriginalRef());
                    getResponse().setLocationRef(getRequest().getOriginalRef().addSegment("??")); // todo: figure out the proper URL
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e);
                }
            } else {
                throw new ResourceException(Status.CLIENT_ERROR_UNSUPPORTED_MEDIA_TYPE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e);
        }
    }

    @Override
    protected void describeGet(MethodInfo info) {
        super.describeGet(info);
        info.setDocumentation("Describe all applications running on the cluster {clusterName}.");
        info.getResponse().setDocumentation("The cluster.");
        RepresentationInfo representation = new RepresentationInfo();
        representation.setDocumentation("This resource exposes applications running on cluster {clusterName}.");
        representation.getDocumentations().get(0).setTitle("applications");
        representation.setMediaType(MediaType.APPLICATION_XML);
        representation.getDocumentations()
                .addAll(Arrays.asList(new DocumentationInfo(
                        "Example of output:<pre><![CDATA[" + "<applications xmlns=\"urn:elastic-grid:eg\">\n"
                                + "  <application name=\"myapp\" cluster=\"cluster2\">\n"
                                + "    <service name=\"My First Service\">\n"
                                + "      <provisioning planned=\"1\" deployed=\"1\" pending=\"0\"/>\n"
                                + "    </service>\n" + "    <service name=\"My Second Service\">\n"
                                + "      <provisioning planned=\"1\" deployed=\"1\" pending=\"0\"/>\n"
                                + "    </service>\n" + "  </application>\n" + "</applications>" + "]]></pre>")));
        representation.setXmlElement("eg:applications");
        info.getResponse().setRepresentations(Arrays.asList(representation));
    }

    @Override
    protected void describePost(MethodInfo info) {
        super.describePost(info);
        info.setDocumentation("Provision a new application on {clusterName}.");
        info.getRequest().setDocumentation("The application to provision packaged as an OAR.");
        RepresentationInfo formRepresentation = new RepresentationInfo();
        formRepresentation.setDocumentation("HTML form with file uploads.");
        formRepresentation.setMediaType(MediaType.MULTIPART_FORM_DATA);
        info.getRequest().setRepresentations(Arrays.asList(formRepresentation));
    }

    @Override
    public boolean allowPut() {
        return false;
    }

    @Override
    public boolean allowDelete() {
        return false;
    }
}