Package org.geoserver.catalog.rest

Source Code of org.geoserver.catalog.rest.StoreFileResource

/* (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.catalog.rest;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.rest.RestletException;
import org.geoserver.rest.util.RESTUploadPathMapper;
import org.geoserver.rest.util.RESTUtils;
import org.geotools.data.DataUtilities;
import org.geotools.util.logging.Logging;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.Resource;

public abstract class StoreFileResource extends Resource {

    static Logger LOGGER = Logging.getLogger("org.geoserver.catalog.rest");
   
    protected Catalog catalog;
   
    public StoreFileResource( Request request, Response response, Catalog catalog) {
        super( null, request, response );
        this.catalog = catalog;
    }
   
    @Override
    public boolean allowPut() {
        return true;
    }
     /**
      * Convenience method for subclasses to look up the (URL-decoded)value of
      * an attribute from the request, ie {@link Request#getAttributes()}.
      *
      * @param attribute The name of the attribute to lookup.
      *
      * @return The value as a string, or null if the attribute does not exist
      *     or cannot be url-decoded.
      */
     protected String getAttribute(String attribute) {
         return RESTUtils.getAttribute(getRequest(), attribute);
     }

     /**
      * Determines the upload method from a request.
      */
     protected String getUploadMethod(Request request) {
         return ((String) request.getResourceRef().getLastSegment()).toLowerCase();
     }
    
     /**
      * Determines if the upload method is inline, ie the content is specified directly in the
      * request payload, or referenced by a url.
      *
      * @param method One of 'file.' (inline), 'url.' (via url), or 'external.' (already on server)
      */
     protected boolean isInlineUpload(String method) {
         return method != null && (method.startsWith("file.") || method.startsWith("url."));
     }
    
     /**
      * Does the file upload based on the specified method.
      *
      * @param method The method, one of 'file.' (inline), 'url.' (via url), or 'external.' (already on server)
      * @param storeName The name of the store being added
      * @param format The store format.
      */
     protected List<File> doFileUpload(String method, String workspaceName, String storeName, String format) {
         File directory = null;
        
         // Prepare the directory only in case this is not an external upload
         if (isInlineUpload(method)){
             try {                
                 // Mapping of the input directory
                 if(method.startsWith("url.")){
                     // For URL upload method, workspace and StoreName are not considered
                     directory = createFinalRoot(null, null);
                 }else{
                     directory = createFinalRoot(workspaceName, storeName);
                 }
             }
             catch (IOException e) {
                 throw new RestletException( e.getMessage(), Status.SERVER_ERROR_INTERNAL, e );
             }
         }
         return handleFileUpload(storeName, workspaceName, format, directory);
     }

    private File createFinalRoot(String workspaceName, String storeName) throws IOException {
        // Check if the Request is a POST request, in order to search for an existing coverage
        Method method = getRequest().getMethod();
        boolean isPost = method.equals(Method.POST);
        File directory = null;
        if (isPost && storeName != null) {
            // Check if the coverage already exists
            CoverageStoreInfo coverage = catalog.getCoverageStoreByName(storeName);
            if (coverage != null) {
                if (workspaceName == null
                        || (workspaceName != null && coverage.getWorkspace().getName()
                                .equalsIgnoreCase(workspaceName))) {
                    // If the coverage exists then the associated directory is defined by its URL
                    File dirFile = DataUtilities.urlToFile(new URL(coverage.getURL()));
                    // If the directory does not exists, it means that the path is relative and then
                    // the directory is searched inside the data directory
                    if (!dirFile.exists()) {
                        directory = catalog.getResourceLoader().findOrCreateDirectory(dirFile, "");
                    } else {
                        // Else the directory is used
                        directory = dirFile;
                    }
                }
            }
        }
        // If the directory has not been found then it is created directly
        if (directory == null) {
            directory = catalog.getResourceLoader().findOrCreateDirectory("data", workspaceName,
                    storeName);
        }

        // Selection of the original ROOT directory path
        StringBuilder root = new StringBuilder(directory.getAbsolutePath());
        // StoreParams to use for the mapping.
        Map<String, String> storeParams = new HashMap<String, String>();
        // Listing of the available pathMappers
        List<RESTUploadPathMapper> mappers = GeoServerExtensions
                .extensions(RESTUploadPathMapper.class);
        // Mapping of the root directory
        for (RESTUploadPathMapper mapper : mappers) {
            mapper.mapStorePath(root, workspaceName, storeName, storeParams);
        }
        // Creation of a new File pointing to the new root
        directory = new File(root.toString());
        // Creation of the new directory
        directory.mkdirs();
        return directory;
    }

    /**
     *
     * @param store
     * @param format
     * @param directory
     * @return
     */
    protected List<File> handleFileUpload(String store, String workspace, String format, File directory) {
        getResponse().setStatus(Status.SUCCESS_ACCEPTED);

        MediaType mediaType = getRequest().getEntity().getMediaType();
        if(LOGGER.isLoggable(Level.INFO))
            LOGGER.info("PUT file, mimetype: " + mediaType );

        List<File> files = new ArrayList<File>();
       
        File uploadedFile = null;
        boolean external = false;
        try {
            String method = (String) getRequest().getResourceRef().getLastSegment();
            if (method != null && method.toLowerCase().startsWith("file.")) {
                uploadedFile = RESTUtils.handleBinUpload(store + "." + format, workspace, directory, getRequest());
            }
            else if (method != null && method.toLowerCase().startsWith("url.")) {
                uploadedFile = RESTUtils.handleURLUpload(store + "." + format, workspace, directory, getRequest());
            }   
            else if (method != null && method.toLowerCase().startsWith("external.")) {
                uploadedFile = RESTUtils.handleEXTERNALUpload(getRequest());
                external = true;
            }
            else{
                final StringBuilder builder =
                    new StringBuilder("Unrecognized file upload method: ").append(method);
                throw new RestletException( builder.toString(), Status.CLIENT_ERROR_BAD_REQUEST);
            }
        }
        catch (Throwable t) {
            if(t instanceof RestletException) {
                throw (RestletException) t;
            } else {
                throw new RestletException( "Error while storing uploaded file:", Status.SERVER_ERROR_INTERNAL, t );
            }
        }
       
        //handle the case that the uploaded file was a zip file, if so unzip it
        if (mediaType!=null && RESTUtils.isZipMediaType( mediaType ) ) {
            //rename to .zip if need be
            if ( !uploadedFile.getName().endsWith( ".zip") ) {
                File newUploadedFile = new File( uploadedFile.getParentFile(), FilenameUtils.getBaseName(uploadedFile.getAbsolutePath()) + ".zip" );
                String oldFileName = uploadedFile.getName();
                if (!uploadedFile.renameTo( newUploadedFile )) {
                    String errorMessage = "Error renaming zip file from " + oldFileName
                            + " -> " + newUploadedFile.getName();
                    throw new RestletException(errorMessage, Status.SERVER_ERROR_INTERNAL);
                }
                uploadedFile = newUploadedFile;
            }
            //unzip the file
            try {
                // Unzipping of the file and, if it is a POST request, filling of the File List
                RESTUtils.unzipFile(uploadedFile, directory, workspace , store, getRequest(), files, external);

               
                //look for the "primary" file
                //TODO: do a better check
                File primaryFile = findPrimaryFile( directory, format );
                if ( primaryFile != null ) {
                    uploadedFile = primaryFile;
                }
                else {
                    throw new RestletException( "Could not find appropriate " + format + " file in archive", Status.CLIENT_ERROR_BAD_REQUEST );
                }
            }
            catch( RestletException e ) {
                throw e;
            }
            catch( Exception e ) {
                throw new RestletException( "Error occured unzipping file", Status.SERVER_ERROR_INTERNAL, e );
            }
        }
        // If the File List is empty then the uploaded file must be added   
        if(files.isEmpty() && uploadedFile != null){
            files.add(uploadedFile);
        }
       
        return files;
    }

    /**
     *
     * @param directory
     * @param format
     * @return
     */
    protected File findPrimaryFile(File directory, String format) {
        for (File f : FileUtils.listFiles(directory, new String[] { format }, true)) {
            // assume the first
            return f;
        }
        return null;
    }

}
TOP

Related Classes of org.geoserver.catalog.rest.StoreFileResource

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.