Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11/XDataTransferer.java
41159 views
1
/*
2
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.awt.X11;
27
28
import java.awt.Image;
29
30
import java.awt.datatransfer.DataFlavor;
31
import java.awt.datatransfer.Transferable;
32
33
import java.awt.image.BufferedImage;
34
import java.awt.image.ColorModel;
35
import java.awt.image.WritableRaster;
36
37
import java.io.BufferedReader;
38
import java.io.InputStream;
39
import java.io.InputStreamReader;
40
import java.io.IOException;
41
42
import java.net.URI;
43
import java.net.URISyntaxException;
44
45
import java.util.ArrayList;
46
import java.util.Iterator;
47
import java.util.LinkedHashSet;
48
49
import javax.imageio.ImageIO;
50
import javax.imageio.ImageReader;
51
import javax.imageio.ImageTypeSpecifier;
52
import javax.imageio.ImageWriter;
53
import javax.imageio.spi.ImageWriterSpi;
54
55
import sun.datatransfer.DataFlavorUtil;
56
import sun.awt.datatransfer.DataTransferer;
57
import sun.awt.datatransfer.ToolkitThreadBlockedHandler;
58
59
import java.io.ByteArrayOutputStream;
60
61
/**
62
* Platform-specific support for the data transfer subsystem.
63
*/
64
public class XDataTransferer extends DataTransferer {
65
static final XAtom FILE_NAME_ATOM = XAtom.get("FILE_NAME");
66
static final XAtom DT_NET_FILE_ATOM = XAtom.get("_DT_NETFILE");
67
static final XAtom PNG_ATOM = XAtom.get("PNG");
68
static final XAtom JFIF_ATOM = XAtom.get("JFIF");
69
static final XAtom TARGETS_ATOM = XAtom.get("TARGETS");
70
static final XAtom INCR_ATOM = XAtom.get("INCR");
71
static final XAtom MULTIPLE_ATOM = XAtom.get("MULTIPLE");
72
73
/**
74
* Singleton constructor
75
*/
76
private XDataTransferer() {
77
}
78
79
private static XDataTransferer transferer;
80
81
static synchronized XDataTransferer getInstanceImpl() {
82
if (transferer == null) {
83
transferer = new XDataTransferer();
84
}
85
return transferer;
86
}
87
88
@Override
89
public String getDefaultUnicodeEncoding() {
90
return "iso-10646-ucs-2";
91
}
92
93
@Override
94
public boolean isLocaleDependentTextFormat(long format) {
95
return false;
96
}
97
98
@Override
99
public boolean isTextFormat(long format) {
100
return super.isTextFormat(format)
101
|| isMimeFormat(format, "text");
102
}
103
104
@Override
105
protected String getCharsetForTextFormat(Long lFormat) {
106
if (isMimeFormat(lFormat, "text")) {
107
String nat = getNativeForFormat(lFormat);
108
DataFlavor df = new DataFlavor(nat, null);
109
// Ignore the charset parameter of the MIME type if the subtype
110
// doesn't support charset.
111
if (!DataFlavorUtil.doesSubtypeSupportCharset(df)) {
112
return null;
113
}
114
String charset = df.getParameter("charset");
115
if (charset != null) {
116
return charset;
117
}
118
}
119
return super.getCharsetForTextFormat(lFormat);
120
}
121
122
@Override
123
protected boolean isURIListFormat(long format) {
124
String nat = getNativeForFormat(format);
125
if (nat == null) {
126
return false;
127
}
128
try {
129
DataFlavor df = new DataFlavor(nat);
130
if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) {
131
return true;
132
}
133
} catch (Exception e) {
134
// Not a MIME format.
135
}
136
return false;
137
}
138
139
@Override
140
public boolean isFileFormat(long format) {
141
return format == FILE_NAME_ATOM.getAtom() ||
142
format == DT_NET_FILE_ATOM.getAtom();
143
}
144
145
@Override
146
public boolean isImageFormat(long format) {
147
return format == PNG_ATOM.getAtom() ||
148
format == JFIF_ATOM.getAtom() ||
149
isMimeFormat(format, "image");
150
}
151
152
@Override
153
protected Long getFormatForNativeAsLong(String str) {
154
// Just get the atom. If it has already been retrived
155
// once, we'll get a copy so this should be very fast.
156
return XAtom.get(str).getAtom();
157
}
158
159
@Override
160
protected String getNativeForFormat(long format) {
161
return getTargetNameForAtom(format);
162
}
163
164
public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
165
return XToolkitThreadBlockedHandler.getToolkitThreadBlockedHandler();
166
}
167
168
/**
169
* Gets an format name for a given format (atom)
170
*/
171
private String getTargetNameForAtom(long atom) {
172
return XAtom.get(atom).getName();
173
}
174
175
@Override
176
protected byte[] imageToPlatformBytes(Image image, long format)
177
throws IOException {
178
String mimeType = null;
179
if (format == PNG_ATOM.getAtom()) {
180
mimeType = "image/png";
181
} else if (format == JFIF_ATOM.getAtom()) {
182
mimeType = "image/jpeg";
183
} else {
184
// Check if an image MIME format.
185
try {
186
String nat = getNativeForFormat(format);
187
DataFlavor df = new DataFlavor(nat);
188
String primaryType = df.getPrimaryType();
189
if ("image".equals(primaryType)) {
190
mimeType = df.getPrimaryType() + "/" + df.getSubType();
191
}
192
} catch (Exception e) {
193
// Not an image MIME format.
194
}
195
}
196
if (mimeType != null) {
197
return imageToStandardBytes(image, mimeType);
198
} else {
199
String nativeFormat = getNativeForFormat(format);
200
throw new IOException("Translation to " + nativeFormat +
201
" is not supported.");
202
}
203
}
204
205
@Override
206
protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList)
207
throws IOException
208
{
209
ByteArrayOutputStream bos = new ByteArrayOutputStream();
210
for (int i = 0; i < fileList.size(); i++)
211
{
212
byte[] bytes = fileList.get(i).getBytes();
213
if (i != 0) bos.write(0);
214
bos.write(bytes, 0, bytes.length);
215
}
216
return bos;
217
}
218
219
/**
220
* Translates either a byte array or an input stream which contain
221
* platform-specific image data in the given format into an Image.
222
*/
223
@Override
224
protected Image platformImageBytesToImage(
225
byte[] bytes, long format) throws IOException
226
{
227
String mimeType = null;
228
if (format == PNG_ATOM.getAtom()) {
229
mimeType = "image/png";
230
} else if (format == JFIF_ATOM.getAtom()) {
231
mimeType = "image/jpeg";
232
} else {
233
// Check if an image MIME format.
234
try {
235
String nat = getNativeForFormat(format);
236
DataFlavor df = new DataFlavor(nat);
237
String primaryType = df.getPrimaryType();
238
if ("image".equals(primaryType)) {
239
mimeType = df.getPrimaryType() + "/" + df.getSubType();
240
}
241
} catch (Exception e) {
242
// Not an image MIME format.
243
}
244
}
245
if (mimeType != null) {
246
return standardImageBytesToImage(bytes, mimeType);
247
} else {
248
String nativeFormat = getNativeForFormat(format);
249
throw new IOException("Translation from " + nativeFormat +
250
" is not supported.");
251
}
252
}
253
254
@Override
255
protected String[] dragQueryFile(byte[] bytes) {
256
XToolkit.awtLock();
257
try {
258
return XlibWrapper.XTextPropertyToStringList(bytes,
259
XAtom.get("STRING").getAtom());
260
} finally {
261
XToolkit.awtUnlock();
262
}
263
}
264
265
@Override
266
protected URI[] dragQueryURIs(InputStream stream,
267
long format,
268
Transferable localeTransferable)
269
throws IOException {
270
271
String charset = getBestCharsetForTextFormat(format, localeTransferable);
272
try (InputStreamReader isr = new InputStreamReader(stream, charset);
273
BufferedReader reader = new BufferedReader(isr)) {
274
String line;
275
ArrayList<URI> uriList = new ArrayList<>();
276
URI uri;
277
while ((line = reader.readLine()) != null) {
278
try {
279
uri = new URI(line);
280
} catch (URISyntaxException uriSyntaxException) {
281
throw new IOException(uriSyntaxException);
282
}
283
uriList.add(uri);
284
}
285
return uriList.toArray(new URI[uriList.size()]);
286
}
287
}
288
289
/**
290
* Returns true if and only if the name of the specified format Atom
291
* constitutes a valid MIME type with the specified primary type.
292
*/
293
private boolean isMimeFormat(long format, String primaryType) {
294
String nat = getNativeForFormat(format);
295
296
if (nat == null) {
297
return false;
298
}
299
300
try {
301
DataFlavor df = new DataFlavor(nat);
302
if (primaryType.equals(df.getPrimaryType())) {
303
return true;
304
}
305
} catch (Exception e) {
306
// Not a MIME format.
307
}
308
309
return false;
310
}
311
312
/*
313
* The XDnD protocol prescribes that the Atoms used as targets for data
314
* transfer should have string names that represent the corresponding MIME
315
* types.
316
* To meet this requirement we check if the passed native format constitutes
317
* a valid MIME and return a list of flavors to which the data in this MIME
318
* type can be translated by the Data Transfer subsystem.
319
*/
320
@Override
321
public LinkedHashSet<DataFlavor> getPlatformMappingsForNative(String nat) {
322
LinkedHashSet<DataFlavor> flavors = new LinkedHashSet<>();
323
324
if (nat == null) {
325
return flavors;
326
}
327
328
DataFlavor df;
329
try {
330
df = new DataFlavor(nat);
331
} catch (Exception e) {
332
// The string doesn't constitute a valid MIME type.
333
return flavors;
334
}
335
336
DataFlavor value = df;
337
final String primaryType = df.getPrimaryType();
338
final String baseType = primaryType + "/" + df.getSubType();
339
340
// For text formats we map natives to MIME strings instead of data
341
// flavors to enable dynamic text native-to-flavor mapping generation.
342
// See SystemFlavorMap.getFlavorsForNative() for details.
343
if ("image".equals(primaryType)) {
344
Iterator<ImageReader> readers = ImageIO.getImageReadersByMIMEType(baseType);
345
if (readers.hasNext()) {
346
flavors.add(DataFlavor.imageFlavor);
347
}
348
}
349
350
flavors.add(value);
351
352
return flavors;
353
}
354
355
private static ImageTypeSpecifier defaultSpecifier = null;
356
357
private ImageTypeSpecifier getDefaultImageTypeSpecifier() {
358
if (defaultSpecifier == null) {
359
ColorModel model = ColorModel.getRGBdefault();
360
WritableRaster raster =
361
model.createCompatibleWritableRaster(10, 10);
362
363
BufferedImage bufferedImage =
364
new BufferedImage(model, raster, model.isAlphaPremultiplied(),
365
null);
366
367
defaultSpecifier = new ImageTypeSpecifier(bufferedImage);
368
}
369
370
return defaultSpecifier;
371
}
372
373
/*
374
* The XDnD protocol prescribes that the Atoms used as targets for data
375
* transfer should have string names that represent the corresponding MIME
376
* types.
377
* To meet this requirement we return a list of formats that represent
378
* MIME types to which the data in this flavor can be translated by the Data
379
* Transfer subsystem.
380
*/
381
@Override
382
public LinkedHashSet<String> getPlatformMappingsForFlavor(DataFlavor df) {
383
LinkedHashSet<String> natives = new LinkedHashSet<>(1);
384
385
if (df == null) {
386
return natives;
387
}
388
389
String charset = df.getParameter("charset");
390
String baseType = df.getPrimaryType() + "/" + df.getSubType();
391
String mimeType = baseType;
392
393
if (charset != null && DataFlavorUtil.isFlavorCharsetTextType(df)) {
394
mimeType += ";charset=" + charset;
395
}
396
397
// Add a mapping to the MIME native whenever the representation class
398
// doesn't require translation.
399
if (df.getRepresentationClass() != null &&
400
(df.isRepresentationClassInputStream() ||
401
df.isRepresentationClassByteBuffer() ||
402
byte[].class.equals(df.getRepresentationClass()))) {
403
natives.add(mimeType);
404
}
405
406
if (DataFlavor.imageFlavor.equals(df)) {
407
String[] mimeTypes = ImageIO.getWriterMIMETypes();
408
if (mimeTypes != null) {
409
for (String mime : mimeTypes) {
410
Iterator<ImageWriter> writers = ImageIO.getImageWritersByMIMEType(mime);
411
while (writers.hasNext()) {
412
ImageWriter imageWriter = writers.next();
413
ImageWriterSpi writerSpi = imageWriter.getOriginatingProvider();
414
415
if (writerSpi != null &&
416
writerSpi.canEncodeImage(getDefaultImageTypeSpecifier())) {
417
natives.add(mime);
418
break;
419
}
420
}
421
}
422
}
423
} else if (DataFlavorUtil.isFlavorCharsetTextType(df)) {
424
// stringFlavor is semantically equivalent to the standard
425
// "text/plain" MIME type.
426
if (DataFlavor.stringFlavor.equals(df)) {
427
baseType = "text/plain";
428
}
429
430
for (String encoding : DataFlavorUtil.standardEncodings()) {
431
if (!encoding.equals(charset)) {
432
natives.add(baseType + ";charset=" + encoding);
433
}
434
}
435
436
// Add a MIME format without specified charset.
437
if (!natives.contains(baseType)) {
438
natives.add(baseType);
439
}
440
}
441
442
return natives;
443
}
444
}
445
446