0c93fc32772a6112d7f12540ad6bda89fa946c19
[jFCPlib.git] / src / main / java / net / pterodactylus / fcp / quelaton / ClientGetCommandImpl.java
1 package net.pterodactylus.fcp.quelaton;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.util.Optional;
6 import java.util.concurrent.ExecutionException;
7 import java.util.concurrent.ExecutorService;
8 import java.util.concurrent.atomic.AtomicBoolean;
9
10 import net.pterodactylus.fcp.AllData;
11 import net.pterodactylus.fcp.ClientGet;
12 import net.pterodactylus.fcp.FcpUtils.TempInputStream;
13 import net.pterodactylus.fcp.GetFailed;
14 import net.pterodactylus.fcp.Priority;
15 import net.pterodactylus.fcp.ReturnType;
16
17 import com.google.common.util.concurrent.ListeningExecutorService;
18 import com.google.common.util.concurrent.MoreExecutors;
19
20 /**
21  * Implementation of the {@link ClientGetCommand}.
22  *
23  * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
24  */
25 class ClientGetCommandImpl implements ClientGetCommand {
26
27         private final ListeningExecutorService threadPool;
28         private final ConnectionSupplier connectionSupplier;
29
30         private boolean ignoreDataStore;
31         private boolean dataStoreOnly;
32         private Long maxSize;
33         private Priority priority;
34         private boolean realTime;
35         private boolean global;
36
37         public ClientGetCommandImpl(ExecutorService threadPool, ConnectionSupplier connectionSupplier) {
38                 this.threadPool = MoreExecutors.listeningDecorator(threadPool);
39                 this.connectionSupplier = connectionSupplier;
40         }
41
42         @Override
43         public ClientGetCommand ignoreDataStore() {
44                 ignoreDataStore = true;
45                 return this;
46         }
47
48         @Override
49         public ClientGetCommand dataStoreOnly() {
50                 dataStoreOnly = true;
51                 return this;
52         }
53
54         @Override
55         public ClientGetCommand maxSize(long maxSize) {
56                 this.maxSize = maxSize;
57                 return this;
58         }
59
60         @Override
61         public ClientGetCommand priority(Priority priority) {
62                 this.priority = priority;
63                 return this;
64         }
65
66         @Override
67         public ClientGetCommand realTime() {
68                 realTime = true;
69                 return this;
70         }
71
72         @Override
73         public ClientGetCommand global() {
74                 global = true;
75                 return this;
76         }
77
78         @Override
79         public Executable<Optional<Data>> uri(String uri) {
80                 return () -> threadPool.submit(() -> execute(uri));
81         }
82
83         private Optional<Data> execute(String uri) throws InterruptedException, ExecutionException, IOException {
84                 ClientGet clientGet = createClientGetCommand(uri);
85                 try (ClientGetDialog clientGetDialog = new ClientGetDialog()) {
86                         return clientGetDialog.send(clientGet).get();
87                 }
88         }
89
90         private ClientGet createClientGetCommand(String uri) {
91                 String identifier = new RandomIdentifierGenerator().generate();
92                 ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct);
93                 if (ignoreDataStore) {
94                         clientGet.setIgnoreDataStore(true);
95                 }
96                 if (dataStoreOnly) {
97                         clientGet.setDataStoreOnly(true);
98                 }
99                 if (maxSize != null) {
100                         clientGet.setMaxSize(maxSize);
101                 }
102                 if (priority != null) {
103                         clientGet.setPriority(priority);
104                 }
105                 if (realTime) {
106                         clientGet.setRealTimeFlag(true);
107                 }
108                 if (global) {
109                         clientGet.setGlobal(true);
110                 }
111                 return clientGet;
112         }
113
114         private class ClientGetDialog extends FcpDialog<Optional<Data>> {
115
116                 private final AtomicBoolean finished = new AtomicBoolean();
117                 private final AtomicBoolean failed = new AtomicBoolean();
118
119                 private String contentType;
120                 private long dataLength;
121                 private InputStream payload;
122
123                 public ClientGetDialog() throws IOException {
124                         super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get());
125                 }
126
127                 @Override
128                 protected boolean isFinished() {
129                         return finished.get() || failed.get();
130                 }
131
132                 @Override
133                 protected Optional<Data> getResult() {
134                         return failed.get() ? Optional.empty() : Optional.of(new Data() {
135                                 @Override
136                                 public String getMimeType() {
137                                         return contentType;
138                                 }
139
140                                 @Override
141                                 public long size() {
142                                         return dataLength;
143                                 }
144
145                                 @Override
146                                 public InputStream getInputStream() {
147                                         return payload;
148                                 }
149                         });
150                 }
151
152                 @Override
153                 protected void consumeAllData(AllData allData) {
154                         synchronized (this) {
155                                 contentType = allData.getContentType();
156                                 dataLength = allData.getDataLength();
157                                 try {
158                                         payload = new TempInputStream(allData.getPayloadInputStream(), dataLength);
159                                         finished.set(true);
160                                 } catch (IOException e) {
161                                         // TODO – logging
162                                         failed.set(true);
163                                 }
164                         }
165                 }
166
167                 @Override
168                 protected void consumeGetFailed(GetFailed getFailed) {
169                         failed.set(true);
170                 }
171
172         }
173
174 }