Package org.geoserver.importer.rest

Source Code of org.geoserver.importer.rest.TaskResource$ImportTaskJSONFormat

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.importer.rest;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;

import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.geoserver.rest.RestletException;
import org.geoserver.rest.format.DataFormat;
import org.geoserver.rest.format.StreamDataFormat;
import org.geoserver.importer.Directory;
import org.geoserver.importer.FileData;
import org.geoserver.importer.ImportContext;
import org.geoserver.importer.ImportData;
import org.geoserver.importer.ImportTask;
import org.geoserver.importer.Importer;
import org.geoserver.importer.ValidationException;
import org.geoserver.importer.transform.TransformChain;
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.resource.Representation;

/**
* REST resource for /imports/<import>/tasks[/<id>]
*
* @author Justin Deoliveira, OpenGeo
*
*/
public class TaskResource extends BaseResource {

    public TaskResource(Importer importer) {
        super(importer);
    }

    @Override
    protected List<DataFormat> createSupportedFormats(Request request, Response response) {
        return (List) Arrays.asList(new ImportTaskJSONFormat(MediaType.APPLICATION_JSON),
                new ImportTaskJSONFormat(MediaType.TEXT_HTML));
    }

    @Override
    public void handleGet() {
        if (getRequest().getResourceRef().getLastSegment().equals("progress")) {
            getResponse().setEntity(createProgressRepresentation());
        }
        else {
            Object obj = lookupTask(true);
            if (obj instanceof ImportTask) {
                getResponse().setEntity(getFormatGet().toRepresentation((ImportTask)obj));
            }
            else {
                getResponse().setEntity(getFormatGet().toRepresentation((List<ImportTask>)obj));
            }
        }
    }

    public boolean allowPost() {
        return getAttribute("task") == null;
    }

    public void handlePost() {
        ImportData data = null;

        getLogger().info("Handling POST of " + getRequest().getEntity().getMediaType());
        //file posted from form
        MediaType mimeType = getRequest().getEntity().getMediaType();
        if (MediaType.MULTIPART_FORM_DATA.equals(mimeType, true)) {
            data = handleMultiPartFormUpload(context());
        }
        else if (MediaType.APPLICATION_WWW_FORM.equals(mimeType, true)) {
            data = handleFormPost();
        }

        if (data == null) {
            throw new RestletException("Unsupported POST", Status.CLIENT_ERROR_FORBIDDEN);
        }

        acceptData(data);
    }

    private void acceptData(ImportData data) {
        ImportContext context = context();
        List<ImportTask> newTasks = null;
        try {
            newTasks = importer.update(context, data);
            //importer.prep(context);
            //context.updated();
        } catch (ValidationException ve) {
            throw ImportJSONWriter.badRequest(ve.getMessage());
        } catch (IOException e) {
            throw new RestletException("Error updating context", Status.SERVER_ERROR_INTERNAL, e);
        }

        if (!newTasks.isEmpty()) {
            Object result = newTasks;
            if (newTasks.size() == 1) {
                result = newTasks.get(0);
                long taskId = newTasks.get(0).getId();
                getResponse().redirectSeeOther(getPageInfo().rootURI(
                    String.format("/imports/%d/tasks/%d", context.getId(), taskId)));
            }

            getResponse().setEntity(getFormatGet().toRepresentation(result));
            getResponse().setStatus(Status.SUCCESS_CREATED);
        }

    }

    private Directory findOrCreateDirectory(ImportContext context) {
        if (context.getData() instanceof Directory) {
            return (Directory) context.getData();
        }
   
        try {
            return Directory.createNew(importer.getUploadRoot());
        } catch (IOException ioe) {
            throw new RestletException("File upload failed", Status.SERVER_ERROR_INTERNAL, ioe);
        }
    }
   
    private ImportData handleFileUpload(ImportContext context) {
        Directory directory = findOrCreateDirectory(context);

        try {
            directory.accept(getAttribute("task"),getRequest().getEntity().getStream());
        } catch (IOException e) {
            throw new RestletException("Error unpacking file",
                Status.SERVER_ERROR_INTERNAL, e);
        }
       
        return directory;
    }
   
    private ImportData handleMultiPartFormUpload(ImportContext context) {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        // @revisit - this appears to be causing OOME
        //factory.setSizeThreshold(102400000);

        RestletFileUpload upload = new RestletFileUpload(factory);
        List<FileItem> items = null;
        try {
            items = upload.parseRequest(getRequest());
        } catch (FileUploadException e) {
            throw new RestletException("File upload failed", Status.SERVER_ERROR_INTERNAL, e);
        }

        //look for a directory to hold the files
        Directory directory = findOrCreateDirectory(context);

        //unpack all the files
        for (FileItem item : items) {
            if (item.getName() == null) {
                continue;
            }
            try {
                directory.accept(item);
            } catch (Exception ex) {
                throw new RestletException("Error writing file " + item.getName(), Status.SERVER_ERROR_INTERNAL, ex);
            }
        }
        return directory;
    }

    public boolean allowPut() {
        return getAttribute("task") != null;
    }

    public void handlePut() {
        if (getRequest().getEntity().getMediaType().equals(MediaType.APPLICATION_JSON)) {
            handleTaskPut();
        } else {
            acceptData(handleFileUpload(context()));
        }
    }

    public boolean allowDelete() {
        return getAttribute("task") != null;
    }

    @Override
    public void handleDelete() {
        ImportTask task = (ImportTask) lookupTask(false);
        task.getContext().removeTask(task);
        importer.changed(task.getContext());
        getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
    }

   
    Object lookupTask(boolean allowAll) {
        ImportTask task = task(allowAll);

        if (task == null) {
            if (allowAll) {
                return context().getTasks();
            }
            throw new RestletException("No task specified", Status.CLIENT_ERROR_BAD_REQUEST);       
        }
        return task;
    }

    void handleTaskPut() {
        ImportTask orig = (ImportTask) lookupTask(false);
        ImportTask task;
        try {
            task = (ImportTask) getFormatPostOrPut().toObject(getRequest().getEntity());
        } catch (ValidationException ve) {
            getLogger().log(Level.WARNING, null, ve);
            throw ImportJSONWriter.badRequest(ve.getMessage());
        }

        boolean change = false;
        if (task.getStore() != null) {
            //JD: moved to TaskTargetResource, but handle here for backward compatability
            TaskTargetResource.updateStoreInfo(orig, task.getStore(), importer);
            change = true;
        }
        if (task.getData() != null) {
            //TODO: move this to data endpoint
            orig.getData().setCharsetEncoding(task.getData().getCharsetEncoding());
            change = true;
        }
        if (task.getUpdateMode() != null) {
            orig.setUpdateMode(task.getUpdateMode());
            change = orig.getUpdateMode() != task.getUpdateMode();
        }

        if (task.getLayer() != null) {
            change = true;
            //now handled by LayerResource, but handle here for backwards compatability
            LayerResource.updateLayer(orig, task.getLayer(), importer);
        }

        TransformChain chain = task.getTransform();
        if (chain != null) {
            orig.setTransform(chain);
            change = true;
        }

        if (!change) {
            throw new RestletException("Unknown representation", Status.CLIENT_ERROR_BAD_REQUEST);
        } else {
            importer.changed(orig);
            getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
        }
    }
   
    private ImportData handleFormPost() {
        Form form = getRequest().getEntityAsForm();
        String url = form.getFirstValue("url", null);
        if (url == null) {
            throw new RestletException("Invalid request", Status.CLIENT_ERROR_BAD_REQUEST);
        }
        URL location = null;
        try {
            location = new URL(url);
        } catch (MalformedURLException ex) {
            getLogger().warning("invalid URL specified in upload : " + url);
        }
        // @todo handling remote URL implies asynchronous processing at this stage
        if (location == null || !location.getProtocol().equalsIgnoreCase("file")) {
            throw new RestletException("Invalid url in request", Status.CLIENT_ERROR_BAD_REQUEST);
        }
        FileData file;
        try {
            file = FileData.createFromFile(new File(location.toURI().getPath()));
        } catch (Exception ex) {
            throw new RuntimeException("Unexpected exception", ex);
        }

        if (file instanceof Directory) {
            try {
                file.prepare();
            } catch (IOException ioe) {
                String msg = "Error processing file: " + file.getFile().getAbsolutePath();
                getLogger().log(Level.WARNING, msg, ioe);
                throw new RestletException(msg, Status.SERVER_ERROR_INTERNAL);
            }
        }

        return file;
    }

    private Representation createProgressRepresentation() {
        JSONObject progress = new JSONObject();
        long imprt = Long.parseLong(getAttribute("import"));
        ImportTask inProgress = importer.getCurrentlyProcessingTask(imprt);
        try {
            if (inProgress != null) {
                progress.put("progress", inProgress.getNumberProcessed());
                progress.put("total", inProgress.getTotalToProcess());
                progress.put("state", inProgress.getState().toString());
            } else {
                ImportTask task = (ImportTask) lookupTask(false);
                progress.put("state", task.getState().toString());
                if (task.getState() == ImportTask.State.ERROR) {
                    if (task.getError() != null) {
                        progress.put("message", task.getError().getMessage());
                    }
                }
            }
        } catch (JSONException jex) {
            throw new RestletException("Internal Error", Status.SERVER_ERROR_INTERNAL, jex);
        }
        return new JSONRepresentation(progress);
    }

    class ImportTaskJSONFormat extends StreamDataFormat {

        ImportTaskJSONFormat(MediaType type) {
            super(type);
        }

        @Override
        protected Object read(InputStream in) throws IOException {
            return newReader(in).task();
        }

        @Override
        protected void write(Object object, OutputStream out) throws IOException {
            ImportJSONWriter json = newWriter(out);

            if (object instanceof ImportTask) {
                ImportTask task = (ImportTask) object;
                json.task(task, true, expand(1));
            }
            else {
                json.tasks((List<ImportTask>)object, true, expand(0));
            }
        }

    }
}
TOP

Related Classes of org.geoserver.importer.rest.TaskResource$ImportTaskJSONFormat

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.