viernes, 3 de enero de 2014

Tratamiento de URLs largas en el protocolo Sharepoint de Alfresco

Una de las funcionalidades más apreciadas por los usuarios de Alfresco Share es la posibilidad de editar ficheros de MS Office directamente desde la aplicación sin necesidad de descargarse el fichero en local. Alfresco ofrece esta funcionalidad mediante el protocolo Sharepoint incluido en el módulo vti. A pesar de su buena funcionalidad, el módulo no está exento de problemas y uno de ellos es el tratamiento de URLs demasiado largas.

Las URLs utilizadas por Alfresco para invocar la edición online de documentos tienen la siguiente forma:

{protocol}://{host}:{vti_port}/{alfresco_context}/{site}/{path_to_file}/{filename}

Todos estos elementos tienen una longitud más o menos acotada excepto que representa toda la ruta de carpetas desde la raíz del Sitio hasta el fichero. El protocolo Sharepoint tiene un problema cuando esta ruta es demasiado larga y el resultado puede ser que el fichero no se pueda abrir para su edición online. Hasta ahora la única solución era acortar estos paths cambiando el nombre de las carpetas que lo forman, pero esto puede ser una solución que no todos los usuarios de Alfresco estén dispuestos a aceptar.

Buscando una solución a este problema se me ocurrió la posibilidad de trabajar con los indentificadores de fichero de Alfresco en lugar del path. La ventaja de usar identificadores es que su longitud es fija y no excede el límite fijado por el protocolo. Con este enfoque la URL a construir sería del siguiente estilo:

{protocol}://{host}:{vti_port}/{alfresco_context}/{site}/__ID/{content_uuid}/{filename}

En esta nueva URL he usado una partícula (__ID) que me permite identificar que se trata de una URL que contiene un identificador de contenido y he añadido el UUID del contenido que quiero editar. Una vez definida la URL adecuada es hora de construirla y para ello hay que modificar la librería JavaScript que se utiliza en Alfresco para generar estas URLs. En concreto hay que buscar el fichero documentlibrary-actions.js (o su versión minificada para ser más exactos) y buscar el siguiente trozo de código:

var onlineEditUrl = this.doclistMetadata.custom.vtiServer.host + ":" + this.doclistMetadata.custom.vtiServer.port + "/" + $combine("alfresco", loc.site.name, loc.container.name, loc.path, loc.file);

Aquí se puede ver como la URL se compone a partir del site, el path y el nombre del fichero. Hay que sustituir dicho código por el siguiente:

var onlineEditUrl = this.doclistMetadata.custom.vtiServer.host + ":" + this.doclistMetadata.custom.vtiServer.port + "/" + $combine("alfresco", loc.site.name, "__ID", record.jsNode.nodeRef.uri.substring(record.jsNode.nodeRef.uri.lastIndexOf("/")+1), loc.file);

En este nuevo código se utiliza el site, el UUID (calculado a partir del nodeRef del documento) y el nombre del fichero.

El siguiente paso consiste en tratar estas URLs. Hay varias opciones para ello pero yo he optado por modificar una clase del módulo vti de Alfresco que se utiliza para realizar operaciones con el path de los ficheros. La clase en cuestión es:

org.alfresco.module.vti.handler.alfresco.VtiPathHelper

y el código de esta clase se puede obtener del repositotio público de svn de Alfresco (por ejemplo de aquí: /alfresco/COMMUNITYTAGS/V4.0e/root/modules/sharepoint/amp/source/java/org/alfresco/module/vti/handler/alfresco). También se puede obtener del repositorio enterprise si se tiene acceso.

En esta clase hay un método que devuelve la información del fichero a partir del path que le llega por la URL. Este método se utiliza en varias operaciones del protocolo por lo que hay que tener cuidado a la hora de cambiar el código para que no se vea alterado el correcto funcionamiento del módulo. El método que hay que modificar es: resolvePathFileInfo. En el código original del método aparecen las siguientes líneas:

           List splitPath = Arrays.asList(initialURL.split("/"));
           fileInfo = fileFolderService.resolveNamePath(rootNodeRef, splitPath);

Estas líneas hay que sustituirlas por estas otras para poder tratar las nuevas URLs:

List splitPath = Arrays.asList(initialURL.split("/"));
if(splitPath.contains("__ID")){
  if(splitPath.size()==4){
    NodeRef fileNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE

                                   , splitPath.get(2));
    fileInfo = fileFolderService.getFileInfo(fileNodeRef);
  } else if (splitPath.size()==3) {
    NodeRef fileNodeRef = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE

                                   , splitPath.get(2));
    NodeRef parentNodeRef = nodeService.getPrimaryParent(fileNodeRef)

                                       .getParentRef();
    fileInfo = fileFolderService.getFileInfo(parentNodeRef);                 
  }

}else{
  fileInfo = fileFolderService.resolveNamePath(rootNodeRef, splitPath);
}


El nuevo código permite tratar tanto las nuevas URLs como las antiguas, manteniendo así la compatibilidad con el módulo de Alfresco. La primera parte del condicional (cuando el path contiene cuantro elementos) sirve para localizar la información del fichero que se quiere editar en el momento que se abre el fichero por primera vez. La segunda parte del condicional (cuando el path contiene 3 elementos) se usa cuando se guardan los cambios en el documento y se necesita recuperar la carpeta que lo contiene.

Con este cambio se puede generar un nuevo fichero JAR que contenga la implementación del protocolo vti y desplegarlo en el servidor de aplicaciones.

Este problema afecta a todas las versiones del módulo vti y en Alfresco están trabajando en una solución que estará disponibles en futuras versiones del módulo.

No hay comentarios: