View Javadoc
1   /*
2    * Copyright (c) 2002-2017, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  
35  package fr.paris.lutece.plugins.myfiles.service.storage.impl;
36  
37  import fr.paris.lutece.plugins.myfiles.business.MyFileData;
38  import fr.paris.lutece.plugins.myfiles.business.MyFileLink;
39  import fr.paris.lutece.plugins.myfiles.service.storage.FileStorage;
40  import fr.paris.lutece.plugins.myfiles.service.storage.NoStorageException;
41  import fr.paris.lutece.plugins.myfiles.service.storage.StorageException;
42  import fr.paris.lutece.portal.service.util.AppLogService;
43  import fr.paris.lutece.portal.service.util.AppPropertiesService;
44  import fr.paris.lutece.util.url.UrlItem;
45  import io.minio.MinioClient;
46  import io.minio.ObjectStat;
47  import io.minio.Result;
48  import io.minio.errors.ErrorResponseException;
49  import io.minio.errors.InsufficientDataException;
50  import io.minio.errors.InternalException;
51  import io.minio.errors.InvalidArgumentException;
52  import io.minio.errors.InvalidBucketNameException;
53  import io.minio.errors.InvalidEndpointException;
54  import io.minio.errors.InvalidPortException;
55  import io.minio.errors.NoResponseException;
56  import io.minio.messages.Item;
57  import java.io.IOException;
58  import java.io.InputStream;
59  import java.security.InvalidKeyException;
60  import java.security.NoSuchAlgorithmException;
61  import java.util.ArrayList;
62  import java.util.List;
63  import org.xmlpull.v1.XmlPullParserException;
64  
65  /**
66   * MinioFileStorage
67   */
68  public class MinioFileStorage implements FileStorage
69  {
70  
71      private static final String PROPERTY_SERVER_URL = "myfiles.minio.server.url";
72      private static final String PROPERTY_ACCESS_KEY = "myfiles.minio.server.access_key";
73      private static final String PROPERTY_SECRET_KEY = "myfiles.minio.server.secret_key";
74  
75      private static final String PATH_SERVLET_DOWNLOAD = "servlet/plugins/myfiles/download";
76  
77      private static final String PARAMETER_FILENAME = "filename";
78  
79      private static MinioClient _client;
80  
81      /**
82       * Constructor
83       */
84      public MinioFileStorage( )
85      {
86          try
87          {
88              String strServerUrl = AppPropertiesService.getProperty( PROPERTY_SERVER_URL );
89              String strAccessKey = AppPropertiesService.getProperty( PROPERTY_ACCESS_KEY );
90              String strSecretKey = AppPropertiesService.getProperty( PROPERTY_SECRET_KEY );
91              _client = new MinioClient( strServerUrl, strAccessKey, strSecretKey );
92          }
93          catch( InvalidEndpointException | InvalidPortException ex )
94          {
95              AppLogService.error( "FileStorageService : error creating minio client : " + ex.getMessage( ), ex );
96          }
97  
98      }
99  
100     /**
101      * {@inheritDoc }
102      */
103     @Override
104     public List<MyFileLink> getFiles( String strUserId ) throws NoStorageException, StorageException
105     {
106         List<MyFileLink> listFiles = new ArrayList<>( );
107         try
108         {
109             String strBucketName = strUserId.toLowerCase( );
110             UrlItem urlItem = new UrlItem( PATH_SERVLET_DOWNLOAD );
111             boolean bExist = _client.bucketExists( strBucketName );
112             if ( bExist )
113             {
114                 for ( Result<Item> result : _client.listObjects( strBucketName ) )
115                 {
116                     Item item = result.get( );
117                     MyFileLink myFile = new MyFileLink( );
118                     myFile.setName( item.objectName( ) );
119                     ObjectStat stat = _client.statObject( strBucketName, item.objectName( ) );
120                     myFile.setContentType( stat.contentType( ) );
121                     myFile.setSize( stat.length( ) );
122                     urlItem.addParameter( PARAMETER_FILENAME, item.objectName( ) );
123                     String strUrl = urlItem.getUrl( );
124                     myFile.setUrl( strUrl );
125                     listFiles.add( myFile );
126                 }
127             }
128             else
129             {
130                 throw new NoStorageException( );
131             }
132         }
133         catch( InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | NoResponseException
134                 | XmlPullParserException | ErrorResponseException | InternalException ex )
135         {
136             throw new StorageException( "Error getting files : " + ex.getMessage( ), ex );
137         }
138 
139         return listFiles;
140     }
141 
142     /**
143      * {@inheritDoc }
144      */
145     @Override
146     public MyFileData getFile( String strUserId, String strFilename ) throws NoStorageException, StorageException
147     {
148         MyFileData myFile = null;
149 
150         try
151         {
152             String strBucketName = strUserId;
153             boolean bExist = _client.bucketExists( strBucketName );
154             if ( bExist )
155             {
156                 myFile = new MyFileData( );
157                 ObjectStat stat = _client.statObject( strBucketName, strFilename );
158                 myFile.setName( strFilename );
159                 myFile.setContentType( stat.contentType( ) );
160                 myFile.setSize( stat.length( ) );
161                 InputStream inputStream = _client.getObject( strBucketName, strFilename );
162                 myFile.setInputstream( inputStream );
163             }
164             else
165             {
166                 throw new NoStorageException( );
167             }
168         }
169         catch( InvalidArgumentException | InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException
170                 | NoResponseException | XmlPullParserException | ErrorResponseException | InternalException ex )
171         {
172             throw new StorageException( "Error getting file : " + ex.getMessage( ), ex );
173         }
174 
175         return myFile;
176     }
177 
178     /**
179      * {@inheritDoc }
180      */
181     @Override
182     public void createStorage( String strNameId ) throws StorageException
183     {
184         try
185         {
186             _client.makeBucket( strNameId.toLowerCase( ) );
187         }
188         catch( InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | NoResponseException
189                 | XmlPullParserException | ErrorResponseException | InternalException ex )
190         {
191             throw new StorageException( "Error getting files : " + ex.getMessage( ), ex );
192         }
193     }
194 
195     /**
196      * {@inheritDoc }
197      */
198     @Override
199     public void addFile( String strUserId, MyFileData myFileData ) throws StorageException
200     {
201         try
202         {
203             String strBucketName = strUserId.toLowerCase( );
204             _client.putObject( strBucketName, myFileData.getName( ), myFileData.getInputstream( ), myFileData.getSize( ), myFileData.getContentType( ) );
205         }
206         catch( InvalidArgumentException | InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException
207                 | NoResponseException | XmlPullParserException | ErrorResponseException | InternalException ex )
208         {
209             throw new StorageException( "Error getting files : " + ex.getMessage( ), ex );
210         }
211     }
212 
213     /**
214      * {@inheritDoc }
215      */
216     @Override
217     public void removeFile( String strUserId, String strFilename ) throws StorageException
218     {
219         try
220         {
221             String strBucketName = strUserId.toLowerCase( );
222             _client.removeObject( strBucketName, strFilename );
223         }
224         catch( InvalidBucketNameException | NoSuchAlgorithmException | InsufficientDataException | IOException | InvalidKeyException | NoResponseException
225                 | XmlPullParserException | ErrorResponseException | InternalException ex )
226         {
227             throw new StorageException( "Error removing file : " + ex.getMessage( ), ex );
228         }
229 
230     }
231 
232 }