View Javadoc

1   /*
2    * Copyright (c) 2002-2014, 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  package fr.paris.lutece.plugins.blobstore.service;
35  
36  import net.sf.json.JSONException;
37  import net.sf.json.JSONObject;
38  
39  import org.apache.commons.fileupload.FileItem;
40  
41  import org.apache.log4j.Logger;
42  
43  import java.io.File;
44  import java.io.IOException;
45  import java.io.InputStream;
46  import java.io.OutputStream;
47  import java.io.UnsupportedEncodingException;
48  
49  
50  /**
51   * Builds a fileItem from blobstore implementing {@link FileItem}. <br>
52   * Metadata is stored in one blob, and content in another one.
53   * get() method is lazy preventing blob to be stored in-memory.
54   * Use {@link #buildFileMetadata(String, long, String)} to build the
55   * FileMetadata.
56   * @see #buildFileMetadata(String, long, String)
57   * @see #BlobStoreFileItem(String, IBlobStoreService)
58   *
59   */
60  public class BlobStoreFileItem implements FileItem
61  {
62      public static final String JSON_KEY_FILE_SIZE = "fileSize";
63      public static final String JSON_KEY_FILE_NAME = "fileName";
64      public static final String JSON_KEY_FILE_CONTENT_TYPE = "fileContentType";
65      public static final String JSON_KEY_FILE_BLOB_ID = "fileBlobId";
66      public static final String JSON_KEY_FILE_METADATA_BLOB_ID = "fileMetadata";
67      private static final long serialVersionUID = 1L;
68      private static Logger _logger = Logger.getLogger( "lutece.blobstore" );
69      private final IBlobStoreService _blobstoreService;
70      private final String _strBlobId;
71      private String _strFileName;
72      private long _lFileSize;
73      private String _strFileBlobId;
74      private String _strContentType;
75  
76      /**
77       * Builds a fileItem from blobstore. get() method is lazy.
78       * The {@link IBlobStoreService} is here to prevent specific usage for the
79       * fileItem so it can be used as any other FileItem.
80       * @param strBlobId the blob id
81       * @param blobstoreService the blob service
82       * @throws NoSuchBlobException if blob cannot be parsed
83       */
84      public BlobStoreFileItem( String strBlobId, IBlobStoreService blobstoreService )
85          throws NoSuchBlobException
86      {
87          _strBlobId = strBlobId;
88          _blobstoreService = blobstoreService;
89  
90          // first, get the metadata
91          byte[] blob = _blobstoreService.getBlob( _strBlobId );
92  
93          if ( blob == null )
94          {
95              throw new NoSuchBlobException( "No blob found for id " + strBlobId );
96          }
97  
98          JSONObject jsonObject = parseBlob( blob );
99  
100         if ( jsonObject != null )
101         {
102             String strSize = (String) jsonObject.get( JSON_KEY_FILE_SIZE );
103             _lFileSize = Long.parseLong( strSize );
104             _strFileName = (String) jsonObject.get( JSON_KEY_FILE_NAME );
105             // store the real blob id - file will be fetch on demand (#get)
106             _strFileBlobId = (String) jsonObject.get( JSON_KEY_FILE_BLOB_ID );
107             _strContentType = jsonObject.getString( JSON_KEY_FILE_CONTENT_TYPE );
108         }
109         else
110         {
111             throw new NoSuchBlobException( strBlobId );
112         }
113     }
114 
115     /**
116      * Gets the metadata blob id
117      * @return the metadata blob id
118      */
119     public String getBlobId(  )
120     {
121         return _strBlobId;
122     }
123 
124     /**
125      * Gets the file blob id
126      * @return the file blob id
127      */
128     public String getFileBlobId(  )
129     {
130         return _strFileBlobId;
131     }
132 
133     /**
134      * Deletes both blobs : metadata <strong>AND</strong> content.
135      */
136     @Override
137     public void delete(  )
138     {
139         _blobstoreService.delete( _strFileBlobId );
140         _blobstoreService.delete( _strBlobId );
141     }
142 
143     /**
144      * {@inheritDoc}
145      */
146     @Override
147     public byte[] get(  )
148     {
149         return _blobstoreService.getBlob( _strFileBlobId );
150     }
151 
152     /**
153      * {@inheritDoc}
154      */
155     @Override
156     public String getContentType(  )
157     {
158         return _strContentType;
159     }
160 
161     /**
162      * Not supported
163      * @return null
164      */
165     @Override
166     public String getFieldName(  )
167     {
168         return null;
169     }
170 
171     /**
172      * {@inheritDoc}
173      * @throws IOException ioexception
174      */
175     @Override
176     public InputStream getInputStream(  ) throws IOException
177     {
178         return _blobstoreService.getBlobInputStream( _strFileBlobId );
179     }
180 
181     /**
182      * {@inheritDoc}
183      */
184     @Override
185     public String getName(  )
186     {
187         return _strFileName;
188     }
189 
190     /**
191      * Not supported - throws UnsupportedOperationException exception
192      * @return nothing
193      * @throws IOException ioe
194      */
195     @Override
196     public OutputStream getOutputStream(  ) throws IOException
197     {
198         throw new UnsupportedOperationException(  );
199     }
200 
201     /**
202      * {@inheritDoc}
203      */
204     @Override
205     public long getSize(  )
206     {
207         return _lFileSize;
208     }
209 
210     /**
211      * {@inheritDoc}
212      */
213     @Override
214     public String getString(  )
215     {
216         return new String( get(  ) );
217     }
218 
219     /**
220      * {@inheritDoc}
221      */
222     @Override
223     public String getString( String encoding ) throws UnsupportedEncodingException
224     {
225         return new String( get(  ), encoding );
226     }
227 
228     /**
229      * Not supported
230      * @return false
231      */
232     @Override
233     public boolean isFormField(  )
234     {
235         return false;
236     }
237 
238     /**
239      * Always false.
240      * @return false
241      */
242     @Override
243     public boolean isInMemory(  )
244     {
245         return false;
246     }
247 
248     /**
249      * Not supported
250      * @param name -
251      */
252     @Override
253     public void setFieldName( String name )
254     {
255         // nothing
256     }
257 
258     /**
259      * Not supported
260      * @param state -
261      */
262     @Override
263     public void setFormField( boolean state )
264     {
265         // nothing
266     }
267 
268     /**
269      * Not supported
270      * @param file -
271      * @throws Exception ex
272      */
273     @Override
274     public void write( File file ) throws Exception
275     {
276         throw new UnsupportedOperationException(  );
277     }
278 
279     /**
280      * {@inheritDoc}
281      */
282     @Override
283     public String toString(  )
284     {
285         return "BlobId:" + _strBlobId + " FileBlobId:" + _strFileBlobId + " FileName:" + _strFileName;
286     }
287 
288     /**
289      * Parses a blob to a JSONObject
290      * @param blob the blob
291      * @return the {@link JSONObject}, <code>null</code> if blob is null or an
292      *         exception occur
293      */
294     private static JSONObject parseBlob( byte[] blob )
295     {
296         if ( blob == null )
297         {
298             return null;
299         }
300 
301         try
302         {
303             return JSONObject.fromObject( new String( blob ) );
304         }
305         catch ( JSONException je )
306         {
307             _logger.error( je.getMessage(  ), je );
308         }
309 
310         return null;
311     }
312 
313     /**
314      * Builds the json value of a file metadata.
315      * @param strFileName filename
316      * @param lSize size
317      * @param strFileBlobId the blob id
318      * @param strContentType the content type
319      * @return the json of the fileMetadata to store in BlobStore
320      */
321     public static final String buildFileMetadata( String strFileName, long lSize, String strFileBlobId,
322         String strContentType )
323     {
324         JSONObject json = new JSONObject(  );
325         json.accumulate( BlobStoreFileItem.JSON_KEY_FILE_SIZE, Long.toString( lSize ) );
326         json.accumulate( BlobStoreFileItem.JSON_KEY_FILE_NAME, strFileName );
327         json.accumulate( BlobStoreFileItem.JSON_KEY_FILE_BLOB_ID, strFileBlobId );
328         json.accumulate( BlobStoreFileItem.JSON_KEY_FILE_CONTENT_TYPE, strContentType );
329 
330         return json.toString(  );
331     }
332 }