ec.edu.chyc.manejopersonal.util.ServerUtils.java Source code

Java tutorial

Introduction

Here is the source code for ec.edu.chyc.manejopersonal.util.ServerUtils.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ec.edu.chyc.manejopersonal.util;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import java.util.Base64;
import java.util.Random;
import java.util.UUID;
import org.apache.commons.codec.digest.DigestUtils;

/**
 *
 * @author marcelocaj
 */
public class ServerUtils {
    /***
     * Tamao de buffer, utilizado para descarga o subida de archivos
     */
    public static final int BUFFER_SIZE = 6124;

    /***
     *
     * @return Path donde se almacenan los artculos
     */
    public static Path getPathArticulos() {
        return getDocRootPath().resolve("articulos");
    }

    public static Path getPathAcuerdosConfidenciales() {
        return getDocRootPath().resolve("acuerdosConfidenciales");
    }

    /***
     *
     * @return Path donde se almacenan los contratos
     */
    public static Path getPathContratos() {
        return getDocRootPath().resolve("contratos");
    }

    /***
     * 
     * @return Path donde se almacenan las actas de aprobacin de las tesis
     */
    public static Path getPathActasAprobacionTesis() {
        return getDocRootPath().resolve("actasAprobacionTesis");
    }

    /**
     * 
     * @return Path donde se almacenan los convenios
     */
    public static Path getPathConvenios() {
        return getDocRootPath().resolve("convenios");
    }

    /**
     * *
     * Devuelve el path para archivos temporales
     *
     * @return Path de archivos temporales
     */
    public static Path getPathTemp() {
        return getDocRootPath().resolve("tmp");
    }

    /***
     *
     * @return Ruta del docroot de glassfish
     */
    public static Path getDocRootPath() {
        return Paths.get("").toAbsolutePath().getParent().resolve("docroot").normalize();
    }

    /***
     *
     * @return Ruta en formato String del docroot de gflassfish
     */
    public static String getDocRoot() {
        return getDocRootPath().normalize().toString();
    }

    /***
     * Devuelve un UUID generado y codificado en Base64
     *
     * @return Uuid codificado en Base64
     */
    public static String generateB64Uuid() {
        UUID uuid = UUID.randomUUID();
        ByteBuffer uuidBytes = ByteBuffer.wrap(new byte[16]);
        uuidBytes.putLong(uuid.getMostSignificantBits()).putLong(uuid.getLeastSignificantBits());
        String asB64 = Base64.getEncoder().encodeToString(uuidBytes.array());
        return asB64;
    }

    /***
     * Muestra el tamao de un archivo en una forma amigable (B, KB, MB, GB, TB,
     * PB, EB. Obtenido y modificado para quitar los formatos con "i" (KiB, MiB,
     * KiB, etc):
     * https://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java
     *
     * @param bytes Tamao en bytes.
     * @return Texto indicando el tamao en formato amigable.
     */
    public static String humanReadableByteCount(long bytes) {
        int unit = 1024;
        if (bytes < unit) {
            return bytes + " B";
        }
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        String pre = ("KMGTPE").charAt(exp - 1) + "";
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }

    /***
     * Reemplaza caracteres invlidos de nombre de archivo a un nombre vlido
     * Obtenido y modificado para que sea una funcin independiente e incluir
     * acentos como vlidos y reemplazar el espacio por _:
     * http://grepcode.com/file/repository.springsource.com/org.apache.activemq/com.springsource.org.apache.kahadb/5.3.0/org/apache/kahadb/util/IOHelper.java
     *
     * @param name Nombre del archivo a convertir.
     * @param dirSeparators Si es true, mantiene los separadores de path ("/" 
     * "\"), si es false se reemplazan.
     * @param maxFileLength Mxima cantidad de caracteres, si el nombre generado
     * es mayor a esta cantidad, ser truncado.
     * @return Nombre convertido.
     */
    public static String toFileSystemSafeName(String name, boolean dirSeparators, int maxFileLength) {
        int size = name.length();
        StringBuilder rc = new StringBuilder(size * 2);
        for (int i = 0; i < size; i++) {
            char c = name.charAt(i);
            boolean valid = c >= 'a' && c <= 'z';
            valid = valid || (c >= 'A' && c <= 'Z');
            valid = valid || (c >= '0' && c <= '9');
            valid = valid || (c == '_') || (c == '-') || (c == '.') || (c == '#')
                    || (dirSeparators && ((c == '/') || (c == '\\')));

            int indexAccent = "??".indexOf(c);

            if (valid) {
                rc.append(c);
            } else if (indexAccent >= 0) {
                String replacement = "aeiouAEOIOUnNuU";
                rc.append(replacement.charAt(indexAccent));
            } else if (c == ' ') {
                rc.append("_");
            } else {
                // Encode the character using hex notation
                rc.append('#');
                rc.append(Integer.toHexString(c));
            }
        }
        String result = rc.toString();
        if (result.length() > maxFileLength) {
            result = result.substring(result.length() - maxFileLength, result.length());
        }
        return result;
    }

    /***
     * Convierte el nombre a un nombre de archivo vlido (reemplazando caracteres invlidos por vlidos)
     * @param nombreOriginal Nombre del archivo que se quiere transformar
     * @return Nombre de archivo transformado y vlido
     */
    public static String convertirNombreArchivo(String nombreOriginal) {
        return toFileSystemSafeName(nombreOriginal, false, 255);
    }

    /***
     * Convertir el nombre del archivo a uno vlido por el sistema
     * @param nombreOriginal Nombre original del archivo, includo extension.
     * @param extension Extensin del archivo.
     * @param caracteres Nmero de caracteres mximo permitido en el nombre del archivo.
     * @return Nombre del archivo convertido a una versin vlida para ser guardado. 
     */
    public static String convertirNombreArchivo(String nombreOriginal, String extension, int caracteres) {
        String nombre = nombreOriginal;
        if (nombre.length() - extension.length() - 1 > caracteres) {
            nombre = nombre.substring(0, caracteres);
        }
        nombre = ServerUtils.convertirNombreArchivo(nombre + "." + extension);
        return nombre;
    }

    /**
     * Mueve los archivos subidos de acuerdo al nombre del archivo que ha tenido antes y ahora. Si son diferentes,
     * entonces se mueve el anterior y se lo trata como "eliminado", posteriormente si el nombre del archivo nuevo
     * existe, se mueve del temporal al directorio destino. Si los dos nombres de archivos son iguales, no se realiza ninguna accin.
     * @param nombreArchivoAntiguo Nombre del archivo antiguo ya almacenado y que se debe encontrar en pathDestino, 
     * se lo tratar como eliminado (llevar el prefijo 'eliminado_' si este nombre es diferente al nombreArchivoNuevo.
     * @param nombreArchivoNuevo Nombre del archivo nuevo que se encuentra en el Path Temporal. Si el nombre no est vaco,
     * se mover el archivo del directorio temporal al pathDestino.
     * @param pathDestino Ruta destino donde se almacenar el nombreArchivoNuevo.
     * @throws IOException En caso de que no se pueda mover ya sea el archivo antiguo o el archivo nuevo.
     */
    public static void procesarAntiguoNuevoArchivo(String nombreArchivoAntiguo, String nombreArchivoNuevo,
            Path pathDestino) throws IOException {

        //si no se ha cambiado el nombre del archivo, es porque el archivo subido no se ha modificado            
        boolean archivoSeMantiene = false;
        if (!nombreArchivoAntiguo.isEmpty() && nombreArchivoAntiguo.equals(nombreArchivoNuevo)) {
            archivoSeMantiene = true;
        }

        if (!nombreArchivoAntiguo.isEmpty() && !archivoSeMantiene) {
            //en caso de que existi un archivo almacenado anteriormente, se elimina, pero solo en caso de que se haya modificado el archivo original
            Path pathArchivoAntiguo = pathDestino.resolve(nombreArchivoAntiguo).normalize();
            if (Files.exists(pathArchivoAntiguo) && Files.isRegularFile(pathArchivoAntiguo)) {
                Path pathNuevoDestino = ServerUtils.getPathTemp().resolve("eliminado_" + nombreArchivoAntiguo);
                Files.move(pathArchivoAntiguo, pathNuevoDestino, REPLACE_EXISTING);
            }
        }

        if (!nombreArchivoNuevo.isEmpty() && !archivoSeMantiene) {
            //si se subi el nuevo archivo, copiar del directorio de temporales al original de destino, despus eliminar el archivo temporal
            // solo realizarlo si se modific el archivo original
            Path origen = ServerUtils.getPathTemp().resolve(nombreArchivoNuevo);
            Path destino = pathDestino.resolve(nombreArchivoNuevo).normalize();

            //FileUtils.copyFile(origen, destino);
            Files.move(origen, destino, REPLACE_EXISTING);
        }
    }

    /***
     * Genera un nombre de archivo vlido que no exista, se usa UUID para la generacin del archivo
     * @param extension Extensin del archivo.
     * @return Nombre del archivo generado. El archivo no existe, debe ser creado.
     */
    public static String generarNombreValidoArchivo(String extension) {
        String nombreArchivo = ServerUtils.generateB64Uuid().replace("=", "")
                + ((new Random()).nextInt(8999) + 1000) + "." + extension;
        return ServerUtils.convertirNombreArchivo(nombreArchivo);
    }

    /***
     * Devolver el hash SHA-256 del texto 
     * @param input Texto a codificar en hash
     * @return Hash del input
     */
    static public String sha256(String input) {
        return DigestUtils.sha256Hex(input);
    }

    /**
     * Devuelve el tamao de un archivo en un formato legible (por ejemplo 23KB, 23MB, 2B, etc)
     *  en caso de no poder obtener el tamao (puede darse en caso de que el archivo no exista o se trate de 
     *  un directorio, o algn error I/O) se devuelve una cadena vaca.
     *  tenga permiso
     * @param pathArchivoSubido Path del archivo que se desea obtener el tamao.
     * @return Tamao del archivo en formato amigable.
     */
    static public String tamanoArchivo(Path pathArchivoSubido) {
        if (Files.isRegularFile(pathArchivoSubido) && Files.exists(pathArchivoSubido)) {
            try {
                Long size = Files.size(pathArchivoSubido);
                return ServerUtils.humanReadableByteCount(size);
            } catch (IOException ex) {
                return "";
                //Logger.getLogger(ServerUtils.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return "";
    }
}