org.pepstock.jem.rest.services.GfsManager.java Source code

Java tutorial

Introduction

Here is the source code for org.pepstock.jem.rest.services.GfsManager.java

Source

/**
JEM, the BEE - Job Entry Manager, the Batch Execution Environment
Copyright (C) 2012-2015   Andrea "Stock" Stocchero
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
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 General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.pepstock.jem.rest.services;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.ws.rs.core.MediaType;
import javax.xml.bind.JAXBElement;

import org.apache.http.HttpStatus;
import org.pepstock.jem.gfs.UploadedGfsChunkFile;
import org.pepstock.jem.gfs.UploadedGfsFile;
import org.pepstock.jem.log.JemException;
import org.pepstock.jem.log.LogAppl;
import org.pepstock.jem.node.NodeMessage;
import org.pepstock.jem.rest.AbstractRestManager;
import org.pepstock.jem.rest.RestClient;
import org.pepstock.jem.rest.entities.GfsFileList;
import org.pepstock.jem.rest.entities.GfsOutputContent;
import org.pepstock.jem.rest.entities.GfsRequest;
import org.pepstock.jem.rest.entities.ReturnedObject;
import org.pepstock.jem.rest.paths.GfsManagerPaths;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;

/**
 * REST service to manage GFS.
 * <br>
 * It can manages all the actions of global file system, by REST.
 * 
 * @author Andrea "Stock" Stocchero
 * @version 2.2
 * 
 */
public class GfsManager extends AbstractRestManager {

    private List<UploadListener> listeners = new LinkedList<UploadListener>();

    /**
     * Creates a new REST manager using a RestClient
     * 
     * @param restClient
     *            REST client instance
     */
    public GfsManager(RestClient restClient) {
        super(restClient);
    }

    /**
     * Adds a upload listener. Used for upload
     * 
     * @param listener upload listeners
     */
    public void addUploadListener(UploadListener listener) {
        // adds listener if not already added
        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    /**
     * Removes a upload listener. Used for upload
     * 
     * @param listener upload listeners
     */
    public void removeUploadListener(UploadListener listener) {
        // removes listener if exists in the list
        if (listeners.contains(listener)) {
            listeners.remove(listener);
        }
    }

    /**
     * Returns a content file of a specific type
     * @param type type of file
     * @param request file name
     * @return content of file
     * @throws JemException if any exception occurs
     */
    public String getFile(GfsRequest request) throws JemException {
        // gets the web resource
        WebResource resource = getClient().getBaseWebResource();
        // creates the returned object
        GenericType<JAXBElement<GfsOutputContent>> generic = new GenericType<JAXBElement<GfsOutputContent>>() {
        };
        try {
            // creates the complete path of REST service, setting also the output format (XML)
            JAXBElement<GfsOutputContent> jaxbContact = resource.path(GfsManagerPaths.MAIN)
                    .path(GfsManagerPaths.OUTPUT_FILE_CONTENT_PATH).accept(MediaType.APPLICATION_XML)
                    .post(generic, request);
            // gets the returned object
            GfsOutputContent object = jaxbContact.getValue();
            // checks if has got any exception
            // Exception must be saved as attribute of returned object
            if (object.hasException()) {
                throw new JemException(object.getExceptionMessage());
            }
            return object.getContent();
        } catch (UniformInterfaceException e) {
            LogAppl.getInstance().debug(e.getMessage(), e);
            // checks http status 
            if (e.getResponse().getStatus() != 204) {
                throw new JemException(e.getMessage(), e);
            }
            return null;
        }
    }

    /**
     * Returns the list of file from a specific folder
     * @param type type of files
     * @param request specific folder
     * @return list of files
     * @throws JemException if any exception occurs
     */
    public GfsFileList getFilesList(GfsRequest request) throws JemException {
        // gets the web resource
        WebResource resource = getClient().getBaseWebResource();
        // creates the returned object
        GenericType<JAXBElement<GfsFileList>> generic = new GenericType<JAXBElement<GfsFileList>>() {
        };
        try {
            // creates the complete path of REST service, setting also the output format (XML)
            JAXBElement<GfsFileList> jaxbContact = resource.path(GfsManagerPaths.MAIN)
                    .path(GfsManagerPaths.FILE_LIST).accept(MediaType.APPLICATION_XML).post(generic, request);
            // gets the returned object
            GfsFileList object = jaxbContact.getValue();
            // checks if has got any exception
            // Exception must be saved as attribute of returned object
            if (object.hasException()) {
                throw new JemException(object.getExceptionMessage());
            }
            return object;
        } catch (UniformInterfaceException e) {
            LogAppl.getInstance().debug(e.getMessage(), e);
            // checks http status 
            if (e.getResponse().getStatus() != 204) {
                throw new JemException(e.getMessage(), e);
            }
            return null;
        }
    }

    /**
     * Uploads a file via rest service
     * @param file
     * @return response status
     * @throws JemException
     */
    public int upload(UploadedGfsFile file) throws JemException {
        // gets the web resource
        // adding paths for upload
        WebResource resource = getClient().getBaseWebResource().path(GfsManagerPaths.MAIN)
                .path(GfsManagerPaths.FILE_UPLOAD);
        ClientResponse response = null;
        FileInputStream fis = null;
        try {
            // file input stream to read 
            fis = new FileInputStream(file.getUploadedFile());
            // creates a chunk in bytes
            byte[] chunk = new byte[UploadedGfsChunkFile.MAX_CHUNK_SIZE];
            // creates a random code, to identify the chunk
            Random random = new Random();
            int randomNumber = random.nextInt(Integer.MAX_VALUE);
            // read and write file in chunks
            int readNum = 0;
            // reads the file with the buffer 
            // the last send will be done out of this FOR
            for (; (readNum = fis.read(chunk)) != -1;) {
                // creates a chunk object to serialize and send by REST
                UploadedGfsChunkFile chunkFile = new UploadedGfsChunkFile();
                // sets the data
                chunkFile.setChunk(chunk);
                // sets unique code
                chunkFile.setFileCode(randomNumber);
                // relative path must be used
                // when you want to upload the file
                // maintaining a relative path of source file
                if (file.getRelativePath() != null) {
                    chunkFile.setFilePath(file.getGfsPath() + file.getRelativePath());
                } else {
                    chunkFile.setFilePath(file.getGfsPath() + file.getUploadedFile().getName());
                }
                // sets transfer is not the LAST
                chunkFile.setTransferComplete(false);
                // number of bytes
                chunkFile.setNumByteToWrite(readNum);
                // where to put the file (GFS type)
                chunkFile.setType(file.getType());
                // sets the update time 
                chunkFile.setLastUpdate(file.getUploadedFile().lastModified());

                // creates and performs post HTTP
                response = resource.accept(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class,
                        chunkFile);
                // checks if everything went OK!
                if (response.getStatus() != HttpStatus.SC_OK) {
                    throw new JemException(NodeMessage.JEMC265E.toMessage().getFormattedMessage(
                            file.getUploadedFile().getAbsolutePath(), response.getEntity(String.class)));
                }
                // close the response and activate the listeners
                response.close();
                fireUploadListeners(readNum);
            }
            // the last chunk was read
            UploadedGfsChunkFile chunkFile = new UploadedGfsChunkFile();
            // adds the last chunk
            chunkFile.setChunk(chunk);
            // sets random unique code
            chunkFile.setFileCode(randomNumber);
            // relative path must be used
            // when you want to upload the file
            // maintaining a relative path of source file
            if (file.getRelativePath() != null) {
                chunkFile.setFilePath(file.getGfsPath() + file.getRelativePath());
            } else {
                chunkFile.setFilePath(file.getGfsPath() + file.getUploadedFile().getName());
            }
            // is the LAST call
            chunkFile.setTransferComplete(true);
            // where to put the file (GFS type)
            chunkFile.setType(file.getType());
            // sets the update time
            chunkFile.setLastUpdate(file.getUploadedFile().lastModified());

            // creates and performs post HTTP
            response = resource.accept(MediaType.APPLICATION_OCTET_STREAM).post(ClientResponse.class, chunkFile);
            // checks if everything went OK!
            if (response.getStatus() != HttpStatus.SC_OK) {
                throw new JemException(NodeMessage.JEMC265E.toMessage().getFormattedMessage(
                        file.getUploadedFile().getAbsolutePath(), response.getEntity(String.class)));
            }
            // activate the listeners
            fireUploadListeners(readNum);
            // doesn't close here the response. see finally
            return response.getStatus();
        } catch (UniformInterfaceException e) {
            LogAppl.getInstance().debug(e.getMessage(), e);
            if (e.getResponse().getStatus() != 204) {
                throw new JemException(e.getMessage(), e);
            }
            return e.getResponse().getStatus();
        } catch (IOException e) {
            LogAppl.getInstance().debug(e.getMessage(), e);
            throw new JemException(e.getMessage(), e);
        } finally {
            // if file inut stream
            // is open, it closes
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    LogAppl.getInstance().ignore(e.getMessage(), e);
                }
            }
            // important to CLOSE ALWAYS the response
            if (response != null) {
                response.close();
            }
        }
    }

    /**
     * Notifies upload listener
     * @param units number of byte uploaded
     */
    private void fireUploadListeners(int units) {
        // if not empty, 
        // scans all listeners calling
        // the method passing the amount of bytes
        // transferred to JEM
        if (!listeners.isEmpty()) {
            for (UploadListener listener : listeners) {
                listener.setUnitsDone(units);
            }
        }
    }

    /**
     * delete a file of a specific type
     * @param type type of file
     * @param request file name
     * @throws JemException if any exception occurs
     */
    public void delete(GfsRequest request) throws JemException {
        // gets the web resource
        WebResource resource = getClient().getBaseWebResource();
        // creates the returned object
        GenericType<JAXBElement<ReturnedObject>> generic = new GenericType<JAXBElement<ReturnedObject>>() {
        };
        try {
            // creates the complete path of REST service, setting also the output format (XML)
            JAXBElement<ReturnedObject> jaxbContact = resource.path(GfsManagerPaths.MAIN)
                    .path(GfsManagerPaths.FILE_DELETE).accept(MediaType.APPLICATION_XML).post(generic, request);
            // gets the returned object
            ReturnedObject object = jaxbContact.getValue();
            // checks if has got any exception
            // Exception must be saved as attribute of returned object
            if (object.hasException()) {
                throw new JemException(object.getExceptionMessage());
            }
        } catch (UniformInterfaceException e) {
            LogAppl.getInstance().debug(e.getMessage(), e);
            // checks http status 
            if (e.getResponse().getStatus() != 204) {
                throw new JemException(e.getMessage(), e);
            }
        }
    }

    /**
     * Inner service, which extends post the default post service.
     * 
     * @author Andrea "Stock" Stocchero
     * @version 2.2
     */
    class GfsPostService<T extends ReturnedObject, S> extends DefaultPostService<T, S> {

        /**
         * Constructs the REST service, using HTTP client and service and subservice paths, passed as argument
         * 
         * @param subService subservice path
         * 
         */
        public GfsPostService(String subService) {
            super(GfsManager.this.getClient(), GfsManagerPaths.MAIN, subService);
        }
    }
}