Project

General

Profile

1
/**
2
 *
3
 */
4
package eu.dnetlib.data.objectstore.filesystem;
5

    
6

    
7

    
8
import java.io.ByteArrayInputStream;
9
import java.io.FileInputStream;
10
import java.io.FileNotFoundException;
11
import java.io.IOException;
12
import java.io.InputStream;
13
import java.io.UnsupportedEncodingException;
14
import java.net.URLEncoder;
15
import java.nio.file.FileSystems;
16
import java.nio.file.Files;
17
import java.nio.file.Path;
18
import java.util.regex.Pattern;
19

    
20
import org.apache.commons.lang.StringUtils;
21
import org.apache.commons.logging.Log;
22
import org.apache.commons.logging.LogFactory;
23

    
24
import com.google.common.collect.Lists;
25
import com.google.gson.Gson;
26
import com.mongodb.BasicDBObject;
27
import com.mongodb.DBCollection;
28
import com.mongodb.DBObject;
29
import com.mongodb.QueryBuilder;
30

    
31
import eu.dnetlib.data.objectstore.modular.ObjectStoreRecord;
32
import eu.dnetlib.data.objectstore.modular.connector.ObjectStore;
33
import eu.dnetlib.data.objectstore.rmi.MetadataObjectRecord;
34
import eu.dnetlib.data.objectstore.rmi.ObjectStoreFile;
35
import eu.dnetlib.data.objectstore.rmi.ObjectStoreFileNotFoundException;
36
import eu.dnetlib.data.objectstore.rmi.ObjectStoreServiceException;
37
import eu.dnetlib.enabling.resultset.ResultSetListener;
38
import eu.dnetlib.miscutils.collections.Pair;
39
import eu.dnetlib.miscutils.functional.xml.DnetXsltFunctions;
40

    
41

    
42
/**
43
 * The Class FileSystemObjectStore.
44
 *
45
 * @author sandro
46
 */
47
public class FileSystemObjectStore implements ObjectStore{
48

    
49
	/**
50
	 *
51
	 */
52
	private static final String URI_FIELD = "uri";
53

    
54

    
55
	/**
56
	 *
57
	 */
58
	private static final String FS_PATH_FIELD = "fsPath";
59

    
60

    
61
	/** The Constant log. */
62
	private static final Log log = LogFactory.getLog(FileSystemObjectStore.class); // NOPMD by marko on 11/24/08 5:02 PM
63

    
64

    
65
	/** The id. */
66
	private final String id;
67

    
68
	/** The interpretation. */
69
	private final String interpretation;
70

    
71
	/** The base path. */
72
	private final String basePath;
73

    
74
	/** The base uri. */
75
	private  final String baseURI;
76

    
77
	/** The mongo metadata. */
78
	private final DBCollection mongoMetadata;
79

    
80

    
81

    
82
	/**
83
	 * Instantiates a new file system object store.
84
	 *
85
	 * @param identifier the identifier
86
	 * @param interpretation the interpretation
87
	 * @param basePath the base path
88
	 * @param mongoMetadata the mongo metadata
89
	 * @param baseURI the base uri
90
	 */
91
	public FileSystemObjectStore(final String identifier, final String interpretation, final String basePath,final DBCollection mongoMetadata, final String baseURI) {
92
		this.id = identifier;
93
		this.basePath = basePath;
94
		this.interpretation = interpretation;
95
		this.mongoMetadata = mongoMetadata;
96
		this.baseURI = baseURI;
97
	}
98

    
99

    
100
	/**
101
	 * {@inheritDoc}
102
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#getId()
103
	 */
104
	@Override
105
	public String getId() {
106
		return this.id;
107
	}
108

    
109
	/**
110
	 * {@inheritDoc}
111
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#getInterpretation()
112
	 */
113
	@Override
114
	public String getInterpretation() {
115
		return this.interpretation;
116
	}
117

    
118
	/**
119
	 * {@inheritDoc}
120
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#feed(java.lang.Iterable, boolean)
121
	 */
122
	@Override
123
	public int feed(final Iterable<ObjectStoreRecord> records, final boolean incremental) throws ObjectStoreServiceException {
124

    
125
		if (records== null)
126
			return 0;
127

    
128
		Path baseDirPath = FileSystems.getDefault().getPath(basePath).resolve(id);
129

    
130
		if (!Files.exists(baseDirPath))
131
			throw new ObjectStoreServiceException("Error can't feed objects because the folder "+baseDirPath +" does not exist");
132

    
133
		int addedCounter = 0 ;
134
		for (ObjectStoreRecord record: records) {
135

    
136
			String objectIdentifier = record.getFileMetadata().getObjectID();
137
			if (!StringUtils.isEmpty(objectIdentifier)){
138
				final String md5id = DnetXsltFunctions.md5(objectIdentifier);
139
				final String firstLevel 	=  	StringUtils.substring(md5id, 0, 2);
140
				final String secondLevel 	=  	StringUtils.substring(md5id, 2, 4);
141
				final String thirdLevel		= 	StringUtils.substring(md5id, 4);
142
				Path objectStoreFilePath =baseDirPath.resolve(firstLevel).resolve(secondLevel);
143

    
144
				if (Files.notExists(objectStoreFilePath))
145
				{
146

    
147
					log.debug("The folder "+objectStoreFilePath.toString()+" doesn't exist! It should be created");
148

    
149
					try {
150
						Files.createDirectories(objectStoreFilePath);
151
						log.debug("Creation of folder "+objectStoreFilePath+ " Done!");
152

    
153
						String md5Sum = null;
154
						Integer size = 0;
155

    
156
						if((record.getInputStream()!= null)){
157
							Pair<String, Integer> infos = FileSystemUtility.saveAndGenerateMD5(record.getInputStream(), objectStoreFilePath.resolve(thirdLevel+".obj"));
158
							md5Sum = infos.getKey();
159
							size = infos.getValue();
160
						}
161
						if(!StringUtils.isEmpty(md5Sum)){
162
							double timestamp = System.currentTimeMillis();
163
							BasicDBObject metadata = new BasicDBObject();
164
							metadata.put("id", record.getFileMetadata().getObjectID());
165
							metadata.put("mime", record.getFileMetadata().getMimeType());
166
							metadata.put("originalObject", record.getFileMetadata().toJSON());
167
							metadata.put("timestamp", timestamp);
168
							metadata.put("md5Sum", md5Sum);
169
							metadata.put("size", size);
170

    
171
							metadata.put(FS_PATH_FIELD, objectStoreFilePath.resolve(thirdLevel+".obj").toAbsolutePath().toString());
172
							String URI = getBaseURI() + "?objectStore=" + URLEncoder.encode(id, "UTF-8") + "&objectId="
173
									+ URLEncoder.encode(record.getFileMetadata().getObjectID(), "UTF-8");
174
							metadata.put(URI_FIELD, URI);
175
							log.debug("saving metadata object to the collection: "+metadata.toString());
176
							mongoMetadata.insert(metadata);
177
							addedCounter ++;
178
						}
179
					} catch (Exception e) {
180
						log.error("Something bad happen on inserting Record", e);
181
						log.error("Record: "+new Gson().toJson(record.getFileMetadata()));
182
					}
183
				} else {
184
					log.debug("The File in the path"+objectStoreFilePath+ "exists ");
185
				}
186
			}
187
		}
188
		return addedCounter;
189
	}
190

    
191
	/**
192
	 * {@inheritDoc}
193
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#feedMetadataRecord(java.lang.Iterable, boolean)
194
	 */
195
	@Override
196
	public int feedMetadataRecord(final Iterable<MetadataObjectRecord> records, final boolean incremental) throws ObjectStoreServiceException {
197
		long timestamp = System.currentTimeMillis();
198
		Path baseDirPath = FileSystems.getDefault().getPath(basePath).resolve(id);
199

    
200
		if (!Files.exists(baseDirPath))
201
			throw new ObjectStoreServiceException("Error can't feed objects because the folder "+baseDirPath +" does not exist");
202

    
203
		int addedCounter =0;
204
		for (MetadataObjectRecord o : records) {
205
			if ((o == null) || (o.getRecord() == null)) {
206
				log.debug("Null object metadata record");
207
				continue;
208
			}
209
			String objectIdentifier = o.getId();
210
			if (!StringUtils.isEmpty(objectIdentifier)){
211
				final String md5id = DnetXsltFunctions.md5(objectIdentifier);
212
				final String firstLevel 	=  	StringUtils.substring(md5id, 0, 2);
213
				final String secondLevel 	=  	StringUtils.substring(md5id, 2, 4);
214
				final String thirdLevel		= 	StringUtils.substring(md5id, 4);
215
				Path objectStoreFilePath =baseDirPath.resolve(firstLevel).resolve(secondLevel);
216

    
217
				if (Files.notExists(objectStoreFilePath))
218
				{
219

    
220

    
221
					InputStream is = new ByteArrayInputStream(o.getRecord().getBytes());
222
					String md5Sum = null;
223
					Integer size = 0;
224
					if((is!= null)){
225
						Pair<String, Integer> info = FileSystemUtility.saveAndGenerateMD5(is, objectStoreFilePath.resolve(thirdLevel+".obj"));
226
						md5Sum = info.getKey();
227
						size = info.getValue();
228
					}
229
					if(!StringUtils.isEmpty(md5Sum)){
230
						BasicDBObject metadata = new BasicDBObject();
231
						metadata.put("id", o.getId());
232
						metadata.put("mime", o.getMime());
233
						metadata.put("timestamp", timestamp);
234
						metadata.put("size", size);
235
						try {
236
							String URI = baseURI + "?objectStore=" + URLEncoder.encode(id, "UTF-8") + "&objectId=" + URLEncoder.encode(o.getId(), "UTF-8");
237
							metadata.put(URI_FIELD, URI);
238

    
239
						} catch (UnsupportedEncodingException e) {
240
							log.error("Got an exception during the feed ", e);
241
						}
242
						metadata.put("md5Sum", md5Sum);
243
						log.debug("saving metadata object to the collection: "+metadata.toString());
244
						mongoMetadata.insert(metadata);
245
						addedCounter ++;
246
					}
247
				}
248
			}
249

    
250

    
251
		}
252
		return addedCounter;
253
	}
254

    
255
	/**
256
	 * {@inheritDoc}
257
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#feedObjectRecord(eu.dnetlib.data.objectstore.modular.ObjectStoreRecord)
258
	 */
259
	@Override
260
	public String feedObjectRecord(final ObjectStoreRecord record) throws ObjectStoreServiceException {
261
		if (record== null)
262
			return null;
263

    
264
		Path baseDirPath = FileSystems.getDefault().getPath(basePath).resolve(id);
265

    
266
		if (!Files.exists(baseDirPath))
267
			throw new ObjectStoreServiceException("Error can't feed objects because the folder "+baseDirPath +" does not exist");
268

    
269
		String url = null;
270

    
271
		String objectIdentifier = record.getFileMetadata().getObjectID();
272
		if (!StringUtils.isEmpty(objectIdentifier)){
273
			final String md5id = DnetXsltFunctions.md5(objectIdentifier);
274
			final String firstLevel 	=  	StringUtils.substring(md5id, 0, 2);
275
			final String secondLevel 	=  	StringUtils.substring(md5id, 2, 4);
276
			final String thirdLevel		= 	StringUtils.substring(md5id, 4);
277
			Path objectStoreFilePath =baseDirPath.resolve(firstLevel).resolve(secondLevel);
278

    
279
			if (Files.notExists(objectStoreFilePath.resolve(thirdLevel+".obj")))
280
			{
281

    
282
				log.debug("The folder "+objectStoreFilePath.toString()+" doesn't exist! It should be created");
283

    
284
				url = insertFileAndMetadata(record, url, thirdLevel, objectStoreFilePath);
285
			}
286
		}
287
		return url;
288
	}
289

    
290

    
291
	/**
292
	 * @param record
293
	 * @param url
294
	 * @param thirdLevel
295
	 * @param objectStoreFilePath
296
	 * @return
297
	 */
298
	private String insertFileAndMetadata(final ObjectStoreRecord record, String url, final String thirdLevel, final Path objectStoreFilePath) {
299
		try {
300
			Files.createDirectories(objectStoreFilePath);
301
			log.debug("Creation of folder "+objectStoreFilePath+ " Done!");
302

    
303
			String md5Sum = null;
304
			Integer size = 0;
305

    
306
			if((record.getInputStream()!= null)){
307
				Pair<String, Integer> info = FileSystemUtility.saveAndGenerateMD5(record.getInputStream(), objectStoreFilePath.resolve(thirdLevel+".obj"));
308
				md5Sum = info.getKey();
309
				size = info.getValue();
310
			}
311
			if(!StringUtils.isEmpty(md5Sum)){
312
				double timestamp = System.currentTimeMillis();
313
				BasicDBObject metadata = new BasicDBObject();
314
				metadata.put("id", record.getFileMetadata().getObjectID());
315
				metadata.put("mime", record.getFileMetadata().getMimeType());
316
				metadata.put("originalObject", record.getFileMetadata().toJSON());
317
				metadata.put("timestamp", timestamp);
318
				metadata.put("md5Sum", md5Sum);
319

    
320
				metadata.put(FS_PATH_FIELD, objectStoreFilePath.resolve(thirdLevel+".obj").toAbsolutePath().toString());
321
				String URI = getBaseURI() + "?objectStore=" + URLEncoder.encode(id, "UTF-8") + "&objectId="
322
						+ URLEncoder.encode(record.getFileMetadata().getObjectID(), "UTF-8");
323
				metadata.put(URI_FIELD, URI);
324
				metadata.put("size", size);
325

    
326
				url = URI;
327
				log.debug("saving metadata object to the collection: "+metadata.toString());
328
				mongoMetadata.insert(metadata);
329

    
330
			}
331
		} catch (Exception e) {
332
			log.error("Something bad happen on inserting Record", e);
333
			log.error("Record: "+new Gson().toJson(record.getFileMetadata()));
334
		}
335
		return url;
336
	}
337

    
338
	/**
339
	 * {@inheritDoc}
340
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#deliver(java.lang.Long, java.lang.Long)
341
	 */
342
	@Override
343
	public ResultSetListener deliver(final Long from, final Long until) throws ObjectStoreServiceException {
344
		FileSystemObjectStoreResultSetListener resutlSet = new FileSystemObjectStoreResultSetListener();
345
		resutlSet.setBaseURI(baseURI);
346
		resutlSet.setMongoCollection(mongoMetadata);
347
		resutlSet.setObjectStoreID(id);
348
		resutlSet.setFromDate(from);
349
		resutlSet.setUntilDate(until);
350
		return resutlSet;
351
	}
352

    
353
	/**
354
	 * {@inheritDoc}
355
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#deliverIds(java.lang.Iterable)
356
	 */
357
	@Override
358
	public ResultSetListener deliverIds(final Iterable<String> ids) throws ObjectStoreServiceException {
359
		FileSystemObjectStoreResultSetListener resutlSet = new FileSystemObjectStoreResultSetListener();
360
		resutlSet.setBaseURI(baseURI);
361
		resutlSet.setMongoCollection(mongoMetadata);
362
		resutlSet.setObjectStoreID(id);
363
		resutlSet.setRecords(Lists.newArrayList(ids));
364
		return resutlSet;
365
	}
366

    
367
	/**
368
	 * {@inheritDoc}
369
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#deliverObject(java.lang.String)
370
	 */
371
	@Override
372
	public ObjectStoreFile deliverObject(final String objectId) throws ObjectStoreServiceException {
373
		DBObject query = QueryBuilder.start("id").is(objectId).get();
374
		DBObject resultQuery = mongoMetadata.findOne(query);
375

    
376
		if ((resultQuery == null) || !resultQuery.containsField(FS_PATH_FIELD))
377
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found");
378

    
379
		String pathStr = (String) resultQuery.get(FS_PATH_FIELD);
380
		if (StringUtils.isEmpty(pathStr))
381
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found the path metadata is empty! ");
382
		return ObjectStoreFileUtility.build(resultQuery, baseURI, objectId);
383
	}
384

    
385
	/**
386
	 * {@inheritDoc}
387
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#deliverStream(java.lang.String)
388
	 */
389
	@Override
390
	public InputStream deliverStream(final String objectId) throws ObjectStoreServiceException {
391
		DBObject query = QueryBuilder.start("id").is(objectId).get();
392
		DBObject resultQuery = mongoMetadata.findOne(query);
393

    
394
		if ((resultQuery == null) || !resultQuery.containsField(FS_PATH_FIELD))
395
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found");
396

    
397
		String pathStr = (String) resultQuery.get(FS_PATH_FIELD);
398
		if (StringUtils.isEmpty(pathStr))
399
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found the path metadata is empty! ");
400

    
401
		Path path = FileSystems.getDefault().getPath(pathStr);
402

    
403
		if (!Files.exists(path))
404
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found the in the path: "+path);
405

    
406

    
407
		try {
408
			FileInputStream is = new FileInputStream(path.toFile());
409
			return is;
410
		} catch (FileNotFoundException e) {
411

    
412
			throw new ObjectStoreServiceException("something wrong happened on getting data stream ",e);
413
		}
414

    
415
	}
416

    
417
	/**
418
	 * {@inheritDoc}
419
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#getSize()
420
	 */
421
	@Override
422
	public int getSize() throws ObjectStoreServiceException {
423
		return (int) mongoMetadata.getCount();
424
	}
425

    
426
	/**
427
	 * {@inheritDoc}
428
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#deleteObject(java.lang.String)
429
	 */
430
	@Override
431
	public void deleteObject(final String objectId) throws ObjectStoreServiceException {
432
		DBObject query = QueryBuilder.start("id").is(objectId).get();
433
		DBObject response = mongoMetadata.findOne(query);
434
		if ((response== null) || !response.containsField(FS_PATH_FIELD))
435
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found in the metadata db");
436
		Path path =FileSystems.getDefault().getPath((String) response.get(FS_PATH_FIELD));
437
		if(Files.notExists(path))
438
			throw new ObjectStoreFileNotFoundException("Object with identifier :"+objectId+" not found in the assigned path "+path);
439

    
440
		try {
441
			Files.delete(path);
442
		} catch (IOException e) {
443
			throw new ObjectStoreServiceException("An error occurs on delete file ",e);
444
		}
445
		mongoMetadata.remove(query);
446
	}
447

    
448
	/**
449
	 * {@inheritDoc}
450
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#getObject(java.lang.String)
451
	 */
452
	@Override
453
	public String getObject(final String recordId) throws ObjectStoreServiceException {
454
		DBObject query = QueryBuilder.start("id").is(recordId).get();
455
		DBObject response = mongoMetadata.findOne(query);
456
		if ((response== null) || !response.containsField(URI_FIELD))
457
			return null;
458
		return  (String) response.get(URI_FIELD);
459
	}
460

    
461
	/**
462
	 * {@inheritDoc}
463
	 * @see eu.dnetlib.data.objectstore.modular.connector.ObjectStore#existIDStartsWith(java.lang.String)
464
	 */
465
	@Override
466
	public boolean existIDStartsWith(final String startId) throws ObjectStoreServiceException {
467
		DBObject query = QueryBuilder.start("id").regex(Pattern.compile(startId)).get();
468
		return  mongoMetadata.count(query)> 0;
469
	}
470

    
471

    
472
	/**
473
	 * Gets the base uri.
474
	 *
475
	 * @return the baseURI
476
	 */
477
	public String getBaseURI() {
478
		return baseURI;
479
	}
480

    
481

    
482
}
(1-1/6)