org.occiware.mart.servlet.utils.ServletUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.occiware.mart.servlet.utils.ServletUtils.java

Source

/**
 * Copyright (c) 2015-2017 Inria
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <p>
 * Contributors:
 * - Christophe Gourdin <christophe.gourdin@inria.fr>
 */
package org.occiware.mart.servlet.utils;

import org.apache.commons.io.IOUtils;
import org.occiware.mart.server.parser.HeaderPojo;
import org.occiware.mart.server.utils.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * Utility class for rest queries.
 *
 * @author cgourdin
 */
public class ServletUtils {

    private static final String REGEX_CONTROL_UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
    private static final Logger LOGGER = LoggerFactory.getLogger(ServletUtils.class);
    private static int uniqueInt = 1;

    /**
     * Client OCCI user agent version control.
     *
     * @param headers
     * @return null if no response, not null if failed response.
     */
    public static boolean checkClientOCCIVersion(HeaderPojo headers) {
        boolean result = true;
        String val = headers.getFirst(Constants.HEADER_USER_AGENT);
        if (val != null) {

            if (val.contains("OCCI/") || val.contains("occi/")) {
                // Check if version is compliant with supported occi version 1.2 currently.
                if (!val.contains(Constants.OCCI_SERVER_VERSION)) {
                    // Check if client version is > 1.2.
                    int index = val.indexOf("OCCI/") + 5;
                    String versionStr = val.substring(index);
                    if (!versionStr.isEmpty()) {

                        // Check version number.
                        try {
                            Float version = Float.valueOf(versionStr);
                            if (version > Constants.OCCI_SERVER_VERSION_NUMBER) {
                                result = false;
                            }
                        } catch (NumberFormatException ex) {
                            // Version is unparseable.
                        }
                    }
                }
            }
        }

        return result;
    }

    /**
     * Simple copy a stream with a buffer of 1024 bytes into an outputstream.
     *
     * @param in
     * @param os
     * @return a String representation of copied bytes, null if outputstream is
     * not a ByteArrayOutputStream.
     * @throws IOException
     */
    public static String copyStream(InputStream in, OutputStream os) throws IOException {
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            os.write(buf, 0, len);
        }
        os.flush();
        if (os instanceof ByteArrayOutputStream) {
            return new String(((ByteArrayOutputStream) os).toByteArray(), "UTF-8");
        }
        return null;
    }

    /**
     * Close quietly an inputstream without exception thrown.
     *
     * @param in
     */
    public static void closeQuietly(InputStream in) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                /* ignore */
            }
        }
    }

    public static void closeQuietly(BufferedReader br) {
        if (br != null) {
            try {
                br.close();
            } catch (IOException e) {
                /* ignore */
            }
        }
    }

    public static void closeQuietly(Reader r) {
        if (r != null) {
            try {
                r.close();
            } catch (IOException e) {
                /* ignore */
            }
        }
    }

    /**
     * Close quietly an outputstream without exception thrown.
     *
     * @param os
     */
    public static void closeQuietly(OutputStream os) {
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                /* ignore */
            }
        }
    }

    /**
     * Serialize an object to make an MD5 hash after call getMd5Digest Method.
     *
     * @param obj
     * @return
     * @throws IOException
     */
    private static byte[] serialize(Object obj) throws IOException {
        byte[] byteArray = null;
        ByteArrayOutputStream baos;
        ObjectOutputStream out = null;
        try {
            // These objects are closed in the finally.
            baos = new ByteArrayOutputStream();
            out = new ObjectOutputStream(baos);
            out.writeObject(obj);
            byteArray = baos.toByteArray();
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return byteArray;
    }

    /**
     * Create a MD5 hash.
     *
     * @param bytes (array of bytes).
     * @return
     */
    private static String getMd5Digest(byte[] bytes) {
        MessageDigest md;
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            return "1";
            // throw new RuntimeException("MD5 cryptographic algorithm is not
            // available.", e);
        }
        byte[] messageDigest = md.digest(bytes);
        BigInteger number = new BigInteger(1, messageDigest);
        // prepend a zero to get a "proper" MD5 hash value
        return "0" + number.toString(16);
    }

    /**
     * Create an eTag (Serial number, serialize an object) for dbus interaction.
     *
     * @param obj
     * @return an eTag number.
     */
    public static Long createEtagNumber(Object obj) {
        String eTag;
        try {
            eTag = getMd5Digest(serialize(obj));
        } catch (IOException ioe) {
            LOGGER.warn("IOException thrown : {0}", ioe.getMessage());
            eTag = "1";
        }

        StringBuilder sb = new StringBuilder();
        for (char c : eTag.toCharArray()) {
            sb.append((int) c);
        }
        return new Long(sb.toString());
    }

    /**
     * Serialize a string (entity id for example with an owner)
     *
     * @param id
     * @param owner
     * @param version (version number, will increment with each update on this
     *                object).
     * @return
     */
    public static Long createEtagNumber(final String id, final String owner, final int version) {
        String eTag;
        if (id == null) {
            eTag = "1";
        } else {
            try {
                eTag = getMd5Digest(serialize(id + owner + version));
            } catch (IOException ioe) {
                LOGGER.warn("IOException thrown : {0}", ioe.getMessage());
                eTag = "1";
            }
        }
        StringBuilder sb = new StringBuilder();

        for (char c : eTag.toCharArray()) {
            sb.append((int) c);
        }
        String result = sb.toString().substring(0, 7);

        return new Long(result);
    }

    /**
     * Check if an UUID is provided on a String or attribute occi.core.id.
     *
     * @param id,  an uuid or a path like foo/bar/myuuid
     * @param attr
     * @return true if provided or false if not provided
     */
    public static boolean isEntityUUIDProvided(final String id, final Map<String, Object> attr) {
        String[] uuids = id.split("/");
        boolean match = false;

        for (String uuid : uuids) {
            if (uuid.matches(REGEX_CONTROL_UUID)) {
                match = true;
                break;
            }
        }
        String occiCoreId = (String) attr.get("occi.core.id");
        if (!match && occiCoreId != null && !occiCoreId.isEmpty()) {
            String[] spls = { "/", ":" };
            for (String spl : spls) {
                uuids = occiCoreId.split(spl);
                for (String uuid : uuids) {
                    if (uuid.matches(REGEX_CONTROL_UUID)) {
                        match = true;
                        break;
                    }
                }
                if (match) {
                    break;
                }
            }

        }

        return match;
    }

    /**
     * Search for UUID on a entityId String before attribute occi.core.id.
     *
     * @param path
     * @param attr
     * @return the UUID provided may return null if uuid not found.
     */
    public static String getUUIDFromPath(final String path, final Map<String, Object> attr) {
        String[] uuids = path.split("/");
        String uuidToReturn = null;

        for (String uuid : uuids) {
            if (uuid.matches(REGEX_CONTROL_UUID)) {
                uuidToReturn = uuid;
                break;
            }
        }
        if (uuidToReturn != null) {
            return uuidToReturn;
        }

        // Check with occi.core.id attribute.
        String occiCoreId = (String) attr.get(Constants.OCCI_CORE_ID);
        if (occiCoreId == null) {
            return null;
        }
        occiCoreId = occiCoreId.replace(Constants.URN_UUID_PREFIX, "");
        if (!occiCoreId.isEmpty()) {
            String[] spls = { "/", ":" };
            for (String spl : spls) {
                uuids = occiCoreId.split(spl);
                for (String uuid : uuids) {
                    if (uuid.matches(REGEX_CONTROL_UUID)) {
                        return uuid;
                    }
                }
            }
        }

        return null;
    }

    /**
     * Check if the uuid is a valid one.
     *
     * @param uuid
     * @return true if the uuid provided is valid false elsewhere.
     */
    public static boolean isUUIDValid(final String uuid) {
        if (uuid == null || uuid.trim().isEmpty()) {
            return false;
        }
        return uuid.matches(REGEX_CONTROL_UUID);
    }

    /**
     * Helper for converting action attributes parameters in array.
     *
     * @param actionAttributes
     * @return parameters for an action null if none.
     */
    public static String[] getActionParametersArray(Map<String, String> actionAttributes) {
        String[] actionParameters = null;
        if (actionAttributes != null && !actionAttributes.isEmpty()) {
            actionParameters = new String[actionAttributes.size()];
            String value;
            int index = 0;
            for (Map.Entry<String, String> entry : actionAttributes.entrySet()) {
                value = entry.getValue();
                actionParameters[index] = value;
                index++;
            }
        }

        return actionParameters;
    }

    public static synchronized int getUniqueInt() {
        return uniqueInt++;
    }

    /**
     * Parse a string to a number without knowning its type output.
     *
     * @param str
     * @param instanceClassType can be null.
     * @return a non null number object.
     */
    public static Number parseNumber(String str, String instanceClassType) {
        Number number;
        if (instanceClassType == null) {

            try {
                number = Float.parseFloat(str);

            } catch (NumberFormatException e) {
                try {
                    number = Double.parseDouble(str);
                } catch (NumberFormatException e1) {
                    try {
                        number = Integer.parseInt(str);
                    } catch (NumberFormatException e2) {
                        try {
                            number = Long.parseLong(str);
                        } catch (NumberFormatException e3) {
                            throw e3;
                        }
                    }
                }
            }
        } else {
            switch (instanceClassType) {
            // We know here the instanceClass.

            case "int":
            case "Integer":
                // Convert to integer.
                try {
                    number = Integer.parseInt(str);
                } catch (NumberFormatException ex) {
                    throw ex;
                }
                break;
            case "float":
            case "Float":
                try {
                    number = Float.parseFloat(str);
                } catch (NumberFormatException ex) {
                    throw ex;
                }
                break;
            case "BigDecimal":
            case "double":
            case "Double":
                try {
                    number = Double.parseDouble(str);
                } catch (NumberFormatException ex) {
                    throw ex;
                }

                break;
            case "Long":
            case "long":
                try {
                    number = Long.parseLong(str);
                } catch (NumberFormatException ex) {
                    throw ex;
                }
                break;
            default:
                throw new NumberFormatException("Unknown format.");
            }

        }

        return number;
    }

    /**
     * Convert an input stream to a String object.
     *
     * @param jsonInput
     * @return
     * @throws IOException
     */
    public static String convertInputStreamToString(InputStream jsonInput) throws IOException {
        String contentStr;
        StringBuilder content = new StringBuilder();
        try {
            List<String> lines = IOUtils.readLines(jsonInput, "UTF8");
            for (String line : lines) {
                content.append(line);
            }
            //            if (content.toString().isEmpty()) {
            //                return content.toString();
            //                // throw new IOException("No input text file defined.");
            //            }
        } catch (IOException ex) {
            LOGGER.error("This stream is not a text stream.");
            throw new IOException("The input file is not a text file or has unknown characters.");
        }
        contentStr = content.toString();
        return contentStr;
    }

    /**
     * @param path
     * @return
     */
    public static String getPathWithoutPrefixSuffixSlash(final String path) {
        String pathTmp = path;

        if (path == null || path.isEmpty() || path.equals("/")) {
            return "";
        }

        if (path.startsWith("/")) {
            pathTmp = pathTmp.substring(1);
        }
        if (path.endsWith("/")) {
            pathTmp = pathTmp.substring(0, pathTmp.length() - 1);
        }
        pathTmp.replaceAll("\\s+", "");

        return pathTmp;
    }

    /**
     * Get headers from http javax servlet request.
     *
     * @param request
     * @return
     */
    public static HeaderPojo getRequestHeaders(HttpServletRequest request) {

        HeaderPojo headerPojo;
        Map<String, List<String>> map = new LinkedHashMap<>();

        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            List<String> elements = new LinkedList<>();
            String key = (String) headerNames.nextElement();
            Enumeration<String> values = request.getHeaders(key);
            while (values.hasMoreElements()) {
                elements.add(values.nextElement());
            }
            map.put(key, elements);
        }
        headerPojo = new HeaderPojo(map);

        return headerPojo;
    }

    public static URI getServerURI(HttpServletRequest req) {
        String protocol = req.getScheme();
        String hostname = req.getServerName();
        int port = req.getServerPort();
        URI serverURI = null;
        try {
            serverURI = new URI(protocol + "://" + hostname + ":" + port);
        } catch (URISyntaxException ex) {
            LOGGER.error("Cannot parse server URI.");
        }

        return serverURI;
    }

}