Project

General

Profile

« Previous | Next » 

Revision 42175

implemented generation of thumbnail

View differences:

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