martes, 13 de agosto de 2019

Utilizar SAMBA con Java (I). Librería smbj

0. Introducción

Si tenemos ya montado un directorio compartido mediante SAMBA en un sistema Windows, tal como se dice un post anterior (donde se comentan las dificultades que hay),  debería ser una cosa fácil el poder acceder a un recurso remoto, dándole la ruta de montaje sobre el sistema local

/mnt/carpeta_montaje_compartida


O por contra acceder al


smb://miusuario:mipassword@192.168.xxx.xxx/micarpeta 


Pero tenemos  algunos problemas:



Si utilizamos la primera opción (la de la ruta de montaje), de momento solo he podido tener acceso a lectura pero no a escritura.


La segunda opción no he podido hacerla funcionar en Java. Por tanto recurro a la librería smbj que parece ser compatible con SMB2/SMB3.


Para ello los pasos a seguir son:

1. Crear un recurso (carpeta) compartido en un servidor windows. 
2. Conocer:
  2.1 IP del servidor Windows (por ejemplo 192.168.2.2)
  2.2 Nombre del recurso compartido (por ejemplo micarpeta)
  2.3 Nombre del dominio (por ejemplo CORPORACION)
  2.4 Usuario y contraseña ara acceder al recurso (por ejemplo miusuario y micontraseña)
  2.5 Una carpeta dentro de esa carpeta compartida (por ejemplo misubcarpeta)
3. Incluir las dependencias de Maven
4. Crear los siguientes objetos de tipo:
  4.1 SmbConfig donde se puede dar los parámetros de tiempo de conexion.
  4.2 Connection para acceder a la IP del servidor
  4.3 AuthenticationContext donde se le indica usuario, contraseña y dominio.
  4.4 Session para abrir sesión
  4.5 DiskShare para conectarse a la carpeta compartida
5. Utilizar los métodos de DiskShare para abrir ficheros ("openFile()") y otro tipo de manipulaciones de fichero o carpeta ("list()"
6. Cerrar los "Streams" utilizados y también el objeto SmbClient



1. Incluir las dependencias de Maven

Basta con añadir al pom.xml :


1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.hierynomus/smbj -->
    <dependency>
      <groupId>com.hierynomus</groupId>
      <artifactId>smbj</artifactId>
      <version>0.9.1</version>
    </dependency>

2. Ejemplo de programa simple



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
package utils;

import java.io.OutputStream;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
 
import com.hierynomus.msdtyp.AccessMask;
import com.hierynomus.msfscc.FileAttributes;
import com.hierynomus.msfscc.fileinformation.FileIdBothDirectoryInformation;
import com.hierynomus.mssmb2.SMB2CreateDisposition;
import com.hierynomus.mssmb2.SMB2CreateOptions;
import com.hierynomus.mssmb2.SMB2ShareAccess;
import com.hierynomus.mssmb2.SMBApiException;
import com.hierynomus.smbj.SMBClient;
import com.hierynomus.smbj.SmbConfig;
import com.hierynomus.smbj.auth.AuthenticationContext;
import com.hierynomus.smbj.connection.Connection;
import com.hierynomus.smbj.session.Session;
import com.hierynomus.smbj.share.DiskShare;
import com.hierynomus.smbj.share.File;

public class SambaUtils2 {
 
  // ONLY FOR TESTS -------------------------------------------------------
 private static final String SHARE_DOMAIN = "CORPORACION";
 private static final String SERVER_IP = "192.168.2.2";
 private static final String SHARE_USER = "miusuario";
 private static final String SHARE_PASSWORD = "micontraseña";
 private static final String SHARE_SRC_DIR = "micarpeta";
 private static final String FOLDER = "misubcarpeta";
 
 /**
  * SMB2 connection example
  *
  */

 public static void main(String[] args) {
  // Set the timeout (optional)
  SmbConfig config = SmbConfig.builder().withTimeout(120, TimeUnit.SECONDS)
   .withTimeout(120, TimeUnit.SECONDS) // Timeout sets read, write and Transact timeouts (default is 60 seconds)
   .withSoTimeout(180, TimeUnit.SECONDS) // Socket timeout (default is 0 seconds)
         .build();
  
  // If you do not set the timeout period SMBClient client = new SMBClient();
  SMBClient client = new SMBClient(config);
 
  try {
   Connection connection = client.connect(SERVER_IP); 
   AuthenticationContext ac = new AuthenticationContext(SHARE_USER, SHARE_PASSWORD.toCharArray(), SHARE_DOMAIN);
   Session session = connection.authenticate(ac);
 
   // Connect to a shared folder
   DiskShare share = (DiskShare) session.connectShare(SHARE_SRC_DIR);
   
   // List the pdf files of 
   for (FileIdBothDirectoryInformation f : share.list(FOLDER, "*.pdf")) {
                           System.out.println("File : " + f.getFileName());
                        }
   
   // Write file. Verify if exists or not
   boolean isFileAlreadyExist = false;
   File f = null;
   try {
    f = share.openFile(
     FOLDER+"/Ximo.txt", 
     new HashSet<AccessMask>(Arrays.asList(new AccessMask[]{AccessMask.MAXIMUM_ALLOWED})), 
     (Set<FileAttributes>)null, 
     SMB2ShareAccess.ALL, 
     SMB2CreateDisposition.FILE_CREATE, 
     (Set<SMB2CreateOptions>)null);
   } catch (SMBApiException var12) {
    isFileAlreadyExist = true;
    //var12.printStackTrace();
   }

   if(isFileAlreadyExist) {
    try {
     f = share.openFile(
      FOLDER+"/Ximo.txt", 
      new HashSet<AccessMask>(Arrays.asList(new AccessMask[]{AccessMask.MAXIMUM_ALLOWED})), 
      (Set<FileAttributes>)null, 
      SMB2ShareAccess.ALL, 
      SMB2CreateDisposition.FILE_OVERWRITE, 
      (Set<SMB2CreateOptions>)null);
    } catch (SMBApiException var11) {
     throw new Exception("Could not open file for write.");
    }
   }

   OutputStream outputStream = null;
   String str = "Hello World Champions";
   if(f != null) {
   outputStream = f.getOutputStream();
   outputStream .write(str.getBytes());
   outputStream .flush();
   outputStream .close();
   }
   
   
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if (client != null) {
    client.close();
   }
  }
 }
}


Cosas a tener en cuenta:

1. Es importante cerrar los recursos abiertos.
2. Para poder escribir en un fichero abierto hay que darle la opción "SMB2ShareAccess.ALL".
3. Hay que detectar si el fichero es nuevo o si existía previamente.
4. Completar los parámetros de las máscaras de acceso.
5 ......

Hay muchos pequeños detalles que puede que te compliquen la vida. Pero de momento a mi este programita me funciona. Espero que os funcione también a vosotros.


En fin, que os sea leve!


No hay comentarios :

Publicar un comentario