Revision 42175
Added by Sandro La Bruzzo about 8 years ago
modules/dnet-data-services/trunk/src/main/java/eu/dnetlib/data/objectstore/DownloadServiceFeeder.java | ||
---|---|---|
104 | 104 |
if (regularExpression != null) { |
105 | 105 |
downloadPlugin.setRegularExpression(regularExpression); |
106 | 106 |
} |
107 |
final Function<String, DownloadItem> applyDowunloadPlugin = input -> { |
|
108 |
if (input == null) { |
|
109 |
log.error("Input is null"); |
|
110 |
return null; |
|
111 |
} |
|
112 |
if (input.equals(DownloadIntoObjectStoreAction.END_QUEUE_STRING)) return DownloadIntoObjectStoreAction.END_QUEUE; |
|
107 | 113 |
|
108 |
for (int i = 0; i < numberOfThreads; i++) { |
|
109 |
final Function<String, DownloadItem> applyDowunloadPlugin = input -> { |
|
110 |
if (input == null) { |
|
111 |
log.error("Input is null"); |
|
112 |
return null; |
|
114 |
DownloadItem di = null; |
|
115 |
try { |
|
116 |
di = DownloadItem.newObjectfromJSON(input); |
|
117 |
|
|
118 |
if (downloadPlugin.retrieveUrl(di) == null) { |
|
119 |
di.setUrl(null); |
|
120 |
di.setOriginalUrl(null); |
|
113 | 121 |
} |
114 |
if (input.equals(DownloadIntoObjectStoreAction.END_QUEUE_STRING)) return DownloadIntoObjectStoreAction.END_QUEUE; |
|
122 |
return di; |
|
123 |
} catch (Throwable e) { |
|
124 |
reportException(pluginReport, di, e); |
|
125 |
log.error("Exception on transform item :" + input, e); |
|
126 |
return null; |
|
127 |
} |
|
128 |
}; |
|
115 | 129 |
|
116 |
DownloadItem di = null; |
|
117 |
try { |
|
118 |
di = DownloadItem.newObjectfromJSON(input); |
|
119 |
|
|
120 |
if (downloadPlugin.retrieveUrl(di) == null) { |
|
121 |
di.setUrl(null); |
|
122 |
di.setOriginalUrl(null); |
|
123 |
} |
|
124 |
return di; |
|
125 |
} catch (Throwable e) { |
|
126 |
reportException(pluginReport, di, e); |
|
127 |
log.error("Exception on transform item :" + input, e); |
|
128 |
return null; |
|
129 |
} |
|
130 |
}; |
|
130 |
for (int i = 0; i < numberOfThreads; i++) { |
|
131 | 131 |
responses.add(executor |
132 | 132 |
.submit(new DownloadWorker(itemsQueue, objStore, Protocols.valueOf(protocol), mimeType, connectTimeoutMs, readTimeoutMs, sleepTimeMs, |
133 | 133 |
applyDowunloadPlugin |
modules/dnet-efg/trunk/src/main/java/eu/dnetlib/efg/workflows/nodes/thumbnail/GenerateThumbnailJobNode.java | ||
---|---|---|
1 |
package eu.dnetlib.efg.workflows.nodes.thumbnail; |
|
2 |
|
|
3 |
import java.util.ArrayList; |
|
4 |
import java.util.List; |
|
5 |
import java.util.concurrent.*; |
|
6 |
|
|
7 |
import eu.dnetlib.data.objectstore.connector.ObjectStore; |
|
8 |
import eu.dnetlib.data.objectstore.connector.ObjectStoreDao; |
|
9 |
import eu.dnetlib.enabling.resultset.client.ResultSetClient; |
|
10 |
import eu.dnetlib.enabling.resultset.listener.ResultSetListener; |
|
11 |
import eu.dnetlib.msro.workflows.graph.Arc; |
|
12 |
import eu.dnetlib.msro.workflows.nodes.SimpleJobNode; |
|
13 |
import eu.dnetlib.msro.workflows.procs.Env; |
|
14 |
import eu.dnetlib.msro.workflows.util.ProgressProvider; |
|
15 |
import eu.dnetlib.rmi.data.ObjectStoreFile; |
|
16 |
import org.apache.commons.logging.Log; |
|
17 |
import org.apache.commons.logging.LogFactory; |
|
18 |
import org.springframework.beans.factory.annotation.Autowired; |
|
19 |
|
|
20 |
/** |
|
21 |
* Created by sandro on 4/8/16. |
|
22 |
*/ |
|
23 |
public class GenerateThumbnailJobNode extends SimpleJobNode implements ProgressProvider { |
|
24 |
|
|
25 |
private static final Log log = LogFactory.getLog(GenerateThumbnailJobNode.class); |
|
26 |
|
|
27 |
public static ObjectStoreFile END_QUEUE = new ObjectStoreFile(); |
|
28 |
@Autowired |
|
29 |
ResultSetClient resultSetClient; |
|
30 |
private String nativeObjectStore; |
|
31 |
private String storeThumb250; |
|
32 |
private String storeThumb96; |
|
33 |
private int numberOfThreads = 4; |
|
34 |
@Autowired |
|
35 |
private ObjectStoreDao objectStoreDao; |
|
36 |
private int counter = -1; |
|
37 |
|
|
38 |
private int total = -1; |
|
39 |
|
|
40 |
@Override |
|
41 |
protected String execute(final Env env) throws Exception { |
|
42 |
|
|
43 |
final ObjectStore objectStore = objectStoreDao.getObjectStore(nativeObjectStore); |
|
44 |
|
|
45 |
total = objectStore.getSize(); |
|
46 |
|
|
47 |
final ObjectStore objectStore250 = objectStoreDao.getObjectStore(env.getAttribute(storeThumb250, String.class)); |
|
48 |
|
|
49 |
final ObjectStore objectStore96 = objectStoreDao.getObjectStore(env.getAttribute(storeThumb96, String.class)); |
|
50 |
|
|
51 |
final ResultSetListener<ObjectStoreFile> deliver = objectStore.deliver(0L, System.currentTimeMillis()); |
|
52 |
|
|
53 |
final BlockingQueue<ObjectStoreFile> queue = new ArrayBlockingQueue<>(10); |
|
54 |
|
|
55 |
final ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads); |
|
56 |
|
|
57 |
final List<Future<Boolean>> responses = new ArrayList<>(); |
|
58 |
|
|
59 |
responses.add(executor.submit(new WorkerMap(objectStore, objectStore250, objectStore96, queue))); |
|
60 |
counter = 0; |
|
61 |
|
|
62 |
while (deliver.hasNext()) { |
|
63 |
counter++; |
|
64 |
queue.put(deliver.next()); |
|
65 |
} |
|
66 |
queue.put(END_QUEUE); |
|
67 |
|
|
68 |
for (final Future<Boolean> currentResponse : responses) { |
|
69 |
if (currentResponse.get() == false) { |
|
70 |
log.error("Some response fail"); |
|
71 |
} |
|
72 |
|
|
73 |
} |
|
74 |
return Arc.DEFAULT_ARC; |
|
75 |
} |
|
76 |
|
|
77 |
public String getNativeObjectStore() { |
|
78 |
return nativeObjectStore; |
|
79 |
} |
|
80 |
|
|
81 |
public void setNativeObjectStore(final String nativeObjectStore) { |
|
82 |
this.nativeObjectStore = nativeObjectStore; |
|
83 |
} |
|
84 |
|
|
85 |
public int getNumberOfThreads() { |
|
86 |
return numberOfThreads; |
|
87 |
} |
|
88 |
|
|
89 |
public void setNumberOfThreads(final int numberOfThreads) { |
|
90 |
this.numberOfThreads = numberOfThreads; |
|
91 |
} |
|
92 |
|
|
93 |
public String getStoreThumb250() { |
|
94 |
return storeThumb250; |
|
95 |
} |
|
96 |
|
|
97 |
public void setStoreThumb250(final String storeThumb250) { |
|
98 |
this.storeThumb250 = storeThumb250; |
|
99 |
} |
|
100 |
|
|
101 |
public String getStoreThumb96() { |
|
102 |
return storeThumb96; |
|
103 |
} |
|
104 |
|
|
105 |
public void setStoreThumb96(final String storeThumb96) { |
|
106 |
this.storeThumb96 = storeThumb96; |
|
107 |
} |
|
108 |
|
|
109 |
@Override |
|
110 |
public String asString() { |
|
111 |
if (counter < 0) { |
|
112 |
return "-"; |
|
113 |
} |
|
114 |
return String.format("%d / %d", counter, total); |
|
115 |
|
|
116 |
} |
|
117 |
} |
modules/dnet-efg/trunk/src/main/java/eu/dnetlib/efg/workflows/nodes/thumbnail/WorkerMap.java | ||
---|---|---|
1 |
package eu.dnetlib.efg.workflows.nodes.thumbnail; |
|
2 |
|
|
3 |
import java.io.IOException; |
|
4 |
import java.io.InputStream; |
|
5 |
import java.util.concurrent.BlockingQueue; |
|
6 |
import java.util.concurrent.Callable; |
|
7 |
|
|
8 |
import eu.dnetlib.data.objectstore.ObjectStoreRecord; |
|
9 |
import eu.dnetlib.data.objectstore.connector.ObjectStore; |
|
10 |
import eu.dnetlib.rmi.data.ObjectStoreFile; |
|
11 |
import org.apache.commons.logging.Log; |
|
12 |
import org.apache.commons.logging.LogFactory; |
|
13 |
|
|
14 |
/** |
|
15 |
* Created by sandro on 4/8/16. |
|
16 |
*/ |
|
17 |
public class WorkerMap implements Callable<Boolean> { |
|
18 |
|
|
19 |
private static final Log log = LogFactory.getLog(WorkerMap.class); |
|
20 |
|
|
21 |
private final ObjectStore thumb256; |
|
22 |
|
|
23 |
private final ObjectStore thumb96; |
|
24 |
|
|
25 |
private final ObjectStore nativeObjectStore; |
|
26 |
|
|
27 |
private final BlockingQueue<ObjectStoreFile> queue; |
|
28 |
|
|
29 |
private final ThumbnailGenerator thumbnailGenerator; |
|
30 |
|
|
31 |
public WorkerMap(final ObjectStore nativeObjectStore, final ObjectStore thumb256, final ObjectStore thumb96, final BlockingQueue<ObjectStoreFile> queue) |
|
32 |
throws IOException { |
|
33 |
this.thumb96 = thumb96; |
|
34 |
this.thumb256 = thumb256; |
|
35 |
this.queue = queue; |
|
36 |
this.nativeObjectStore = nativeObjectStore; |
|
37 |
this.thumbnailGenerator = new ThumbnailGenerator(); |
|
38 |
} |
|
39 |
|
|
40 |
@Override |
|
41 |
public Boolean call() throws Exception { |
|
42 |
ObjectStoreFile currentFile = queue.take(); |
|
43 |
while (currentFile != GenerateThumbnailJobNode.END_QUEUE) { |
|
44 |
try { |
|
45 |
final ObjectStoreRecord record = new ObjectStoreRecord(); |
|
46 |
if (!thumb96.alreadyExist(currentFile.getObjectID())) { |
|
47 |
final InputStream convert = thumbnailGenerator.convert(nativeObjectStore.deliverStream(currentFile.getObjectID()), 150, 96, "96", true); |
|
48 |
|
|
49 |
record.setFileMetadata(currentFile); |
|
50 |
record.setInputStream(convert); |
|
51 |
thumb96.feedObjectRecord(record); |
|
52 |
} |
|
53 |
if (!thumb256.alreadyExist(currentFile.getObjectID())) { |
|
54 |
record.setInputStream(thumbnailGenerator.convert(nativeObjectStore.deliverStream(currentFile.getObjectID()), 600, 250, "250", false)); |
|
55 |
thumb256.feedObjectRecord(record); |
|
56 |
} |
|
57 |
currentFile = queue.take(); |
|
58 |
} catch (Throwable e) { |
|
59 |
log.error("Error on generating thumbnail", e); |
|
60 |
} |
|
61 |
} |
|
62 |
|
|
63 |
if (currentFile == GenerateThumbnailJobNode.END_QUEUE) |
|
64 |
queue.put(currentFile); |
|
65 |
|
|
66 |
return true; |
|
67 |
} |
|
68 |
} |
modules/dnet-efg/trunk/src/main/java/eu/dnetlib/efg/workflows/nodes/thumbnail/ThumbnailGenerator.java | ||
---|---|---|
1 |
package eu.dnetlib.efg.workflows.nodes.thumbnail; |
|
2 |
|
|
3 |
import java.io.File; |
|
4 |
import java.io.FileNotFoundException; |
|
5 |
import java.io.IOException; |
|
6 |
import java.io.InputStream; |
|
7 |
import java.nio.file.FileSystems; |
|
8 |
import java.nio.file.Files; |
|
9 |
import java.nio.file.Path; |
|
10 |
import java.nio.file.StandardCopyOption; |
|
11 |
import java.util.UUID; |
|
12 |
|
|
13 |
import org.apache.tika.Tika; |
|
14 |
import org.im4java.core.ConvertCmd; |
|
15 |
import org.im4java.core.IMOperation; |
|
16 |
|
|
17 |
/** |
|
18 |
* Created by sandro on 4/8/16. |
|
19 |
*/ |
|
20 |
public class ThumbnailGenerator { |
|
21 |
|
|
22 |
private Path baseDirPath; |
|
23 |
|
|
24 |
private String dirName; |
|
25 |
|
|
26 |
public ThumbnailGenerator() throws IOException { |
|
27 |
dirName = UUID.randomUUID().toString(); |
|
28 |
baseDirPath = Files.createTempDirectory(dirName); |
|
29 |
} |
|
30 |
|
|
31 |
public static boolean deleteRecursive(File path) throws FileNotFoundException { |
|
32 |
if (!path.exists()) throw new FileNotFoundException(path.getAbsolutePath()); |
|
33 |
boolean ret = true; |
|
34 |
if (path.isDirectory()) { |
|
35 |
for (File f : path.listFiles()) { |
|
36 |
ret = ret && deleteRecursive(f); |
|
37 |
} |
|
38 |
} |
|
39 |
return ret && path.delete(); |
|
40 |
} |
|
41 |
|
|
42 |
public InputStream convert(final InputStream input, int width, int height, final String name, boolean deleteBeforeConver) { |
|
43 |
try { |
|
44 |
destroyFolder(); |
|
45 |
baseDirPath = Files.createTempDirectory(dirName); |
|
46 |
final Path tempFile = baseDirPath.resolve(name + "_orig"); |
|
47 |
Files.copy(input, tempFile, StandardCopyOption.REPLACE_EXISTING); |
|
48 |
final String inputType = guessMimeType(tempFile.toAbsolutePath().toString()); |
|
49 |
|
|
50 |
String inputPath = tempFile.toAbsolutePath().toString(); |
|
51 |
if (inputType != null && inputType.contains("pdf")) { |
|
52 |
inputPath += "[0]"; |
|
53 |
} |
|
54 |
ConvertCmd cmd = new ConvertCmd(); |
|
55 |
IMOperation op = new IMOperation(); |
|
56 |
op.addImage(inputPath); |
|
57 |
op.define(String.format("jpeg:size=%dx%d", width * 2, height * 2)); |
|
58 |
op.thumbnail(width, height); |
|
59 |
op.unsharp(0.5); |
|
60 |
op.background("transparent"); |
|
61 |
op.gravity("center"); |
|
62 |
op.extent(width, height); |
|
63 |
op.colors(256); |
|
64 |
op.addImage(tempFile.toAbsolutePath().toString().replace("orig", "conv.png")); |
|
65 |
cmd.run(op); |
|
66 |
final Path path = FileSystems.getDefault().getPath(tempFile.toAbsolutePath().toString().replace("orig", "conv.png")); |
|
67 |
return Files.newInputStream(path); |
|
68 |
} catch (Throwable e) { |
|
69 |
System.out.println("Error on convert file" + e.toString()); |
|
70 |
return null; |
|
71 |
} |
|
72 |
} |
|
73 |
|
|
74 |
private String guessMimeType(final String inputPath) throws IOException { |
|
75 |
Tika tika = new Tika(); |
|
76 |
return tika.detect(new File(inputPath)); |
|
77 |
} |
|
78 |
|
|
79 |
public boolean destroyFolder() throws FileNotFoundException { |
|
80 |
return deleteRecursive(baseDirPath.toFile()); |
|
81 |
|
|
82 |
} |
|
83 |
|
|
84 |
} |
modules/dnet-efg/trunk/src/main/resources/eu/dnetlib/efg/workflows/applicationContext-nodes.xml | ||
---|---|---|
10 | 10 |
scope="prototype"/> |
11 | 11 |
|
12 | 12 |
|
13 |
<bean id="wfNodeGenerateThumbnail" |
|
14 |
class="eu.dnetlib.efg.workflows.nodes.thumbnail.GenerateThumbnailJobNode" |
|
15 |
scope="prototype"/> |
|
16 |
|
|
13 | 17 |
<bean id="EFGDownloadPlugin" class="eu.dnetlib.efg.download.plugin.EFGDownloadPlugin"/> |
14 | 18 |
|
15 | 19 |
</beans> |
modules/dnet-efg/trunk/src/main/resources/eu/dnetlib/bootstrap/profiles/workflows/efg_thumbnail_generation.xml | ||
---|---|---|
82 | 82 |
<PARAM name="objectStoreIdParam" ref="nativeObjectStoreId"/> |
83 | 83 |
</PARAMETERS> |
84 | 84 |
<ARCS> |
85 |
<ARC to="generateThumbnail"/> |
|
86 |
</ARCS> |
|
87 |
</NODE> |
|
88 |
|
|
89 |
<NODE name="generateThumbnail" type="GenerateThumbnail"> |
|
90 |
<DESCRIPTION>Generate Thumbnail for EFG</DESCRIPTION> |
|
91 |
<PARAMETERS> |
|
92 |
<PARAM name="nativeObjectStore" ref="nativeObjectStoreId"/> |
|
93 |
<PARAM name="storeThumb250" value="thumb256_id"/> |
|
94 |
<PARAM name="storeThumb96" value="thumb96_id"/> |
|
95 |
|
|
96 |
|
|
97 |
</PARAMETERS> |
|
98 |
<ARCS> |
|
85 | 99 |
<ARC to="success"/> |
86 | 100 |
</ARCS> |
87 | 101 |
</NODE> |
88 | 102 |
|
103 |
|
|
89 | 104 |
</WORKFLOW> |
90 | 105 |
</CONFIGURATION> |
91 | 106 |
</BODY> |
modules/dnet-efg/trunk/pom.xml | ||
---|---|---|
24 | 24 |
</dependency> |
25 | 25 |
|
26 | 26 |
<dependency> |
27 |
<groupId>org.apache.commons</groupId> |
|
28 |
<artifactId>commons-compress</artifactId> |
|
29 |
<version>1.11</version> |
|
30 |
</dependency> |
|
31 |
|
|
32 |
|
|
33 |
<dependency> |
|
27 | 34 |
<groupId>eu.dnetlib</groupId> |
28 | 35 |
<artifactId>dnet-data-services</artifactId> |
29 | 36 |
<version>1.0.0-SNAPSHOT</version> |
30 | 37 |
</dependency> |
31 | 38 |
|
39 |
<dependency> |
|
40 |
<groupId>org.im4java</groupId> |
|
41 |
<artifactId>im4java</artifactId> |
|
42 |
<version>1.4.0</version> |
|
43 |
</dependency> |
|
32 | 44 |
|
45 |
<dependency> |
|
46 |
<groupId>org.apache.tika</groupId> |
|
47 |
<artifactId>tika-core</artifactId> |
|
48 |
<version>1.12</version> |
|
49 |
</dependency> |
|
50 |
|
|
51 |
|
|
33 | 52 |
</dependencies> |
34 | 53 |
</project> |
Also available in: Unified diff
implemented generation of thumbnail