1 /*
2 * Copyright (c) 2011, 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.lwawt.macosx;
27
28 import java.awt.*;
29
30 import java.io.*;
31 import java.net.URL;
32 import java.nio.charset.Charset;
33 import java.text.Normalizer;
34 import java.text.Normalizer.Form;
35 import java.util.*;
36 import java.util.regex.*;
37
38 import java.awt.datatransfer.*;
39 import sun.awt.datatransfer.*;
40
41 public class CDataTransferer extends DataTransferer {
42 private static final Map<String, Long> predefinedClipboardNameMap;
43 private static final Map<Long, String> predefinedClipboardFormatMap;
44
45 // See SystemFlavorMap, or the flavormap.properties file:
46 // We should define a few more types in flavormap.properties, it's rather slim now.
47 private static final String[] predefinedClipboardNames = {
48 "",
49 "STRING",
50 "FILE_NAME",
51 "TIFF",
52 "RICH_TEXT",
53 "HTML",
54 "PDF",
55 "URL",
56 "PNG",
108
109 @Override
110 public boolean isImageFormat(long format) {
111 int ifmt = (int)format;
112 switch(ifmt) {
113 case CF_TIFF:
114 case CF_PDF:
115 case CF_PNG:
116 case CF_JPEG:
117 return true;
118 default:
119 return false;
120 }
121 }
122
123 @Override
124 public Object translateBytes(byte[] bytes, DataFlavor flavor,
125 long format, Transferable transferable) throws IOException {
126
127 if (format == CF_URL && URL.class.equals(flavor.getRepresentationClass())) {
128 String charset = Charset.defaultCharset().name();
129 if (transferable != null && transferable.isDataFlavorSupported(javaTextEncodingFlavor)) {
130 try {
131 charset = new String((byte[]) transferable.getTransferData(javaTextEncodingFlavor), "UTF-8");
132 } catch (UnsupportedFlavorException cannotHappen) {
133 }
134 }
135 String xml = new String(bytes, charset);
136 // macosx pasteboard returns a property list that consists of one URL
137 // let's extract it.
138 return new URL(extractURL(xml));
139 }
140
141 if (format == CF_STRING) {
142 bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8");
143 }
144
145 return super.translateBytes(bytes, flavor, format, transferable);
146 }
147
148 /**
149 * Macosx pasteboard returns xml document that contains one URL, for exmple:
150 * <pre>
151 * {@code
152 * <?xml version=\"1.0\" encoding=\"UTF-8\"?>
153 * <!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
154 * <plist version=\"1.0\">
155 * <array>
156 * <string>file:///path_to_file</string>
157 * <string></string>
158 * </array>
159 * </plist>
160 * }
161 * </pre>
162 */
163 private String extractURL(String xml) {
164 Pattern urlExtractorPattern = Pattern.compile("<string>(.*)</string>");
165 Matcher matcher = urlExtractorPattern.matcher(xml);
166 if (matcher.find()) {
167 return matcher.group(1);
168 } else {
169 return null;
170 }
171 }
172
173 @Override
174 synchronized protected Long getFormatForNativeAsLong(String str) {
175 Long format = predefinedClipboardNameMap.get(str);
176
177 if (format == null) {
178 if (java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance()) {
179 // Do not try to access native system for the unknown format
180 return -1L;
181 }
182 format = registerFormatWithPasteboard(str);
183 predefinedClipboardNameMap.put(str, format);
184 predefinedClipboardFormatMap.put(format, str);
185 }
186
187 return format;
188 }
189
190 /*
191 * Adds type to native mapping NSDictionary.
192 */
228 private final ToolkitThreadBlockedHandler handler = new CToolkitThreadBlockedHandler();
229
230 @Override
231 public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
232 return handler;
233 }
234
235 @Override
236 protected byte[] imageToPlatformBytes(Image image, long format) {
237 return CImage.getCreator().getPlatformImageBytes(image);
238 }
239
240 private static native String[] nativeDragQueryFile(final byte[] bytes);
241 @Override
242 protected String[] dragQueryFile(final byte[] bytes) {
243 if (bytes == null) return null;
244 if (new String(bytes).startsWith("Unsupported type")) return null;
245 return nativeDragQueryFile(bytes);
246 }
247
248 @Override
249 protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException {
250 return CImage.getCreator().createImageFromPlatformImageBytes(bytes);
251 }
252
253 @Override
254 protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException {
255 ByteArrayOutputStream bos = new ByteArrayOutputStream();
256 for (String file : fileList) {
257 byte[] bytes = file.getBytes();
258 bos.write(bytes, 0, bytes.length);
259 bos.write(0);
260 }
261 return bos;
262 }
263
264 @Override
265 protected boolean isURIListFormat(long format) {
266 String nat = getNativeForFormat(format);
267 if (nat == null) {
268 return false;
269 }
270 try {
271 DataFlavor df = new DataFlavor(nat);
272 if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) {
273 return true;
274 }
275 } catch (Exception e) {
276 // Not a MIME format.
277 }
278 return false;
279 }
280 }
|
1
2 /*
3 * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation. Oracle designates this
9 * particular file as subject to the "Classpath" exception as provided
10 * by Oracle in the LICENSE file that accompanied this code.
11 *
12 * This code is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * version 2 for more details (a copy is included in the LICENSE file that
16 * accompanied this code).
17 *
18 * You should have received a copy of the GNU General Public License version
19 * 2 along with this work; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23 * or visit www.oracle.com if you need additional information or have any
24 * questions.
25 */
26
27 package sun.lwawt.macosx;
28
29 import java.awt.*;
30
31 import java.io.*;
32 import java.net.URI;
33 import java.net.URISyntaxException;
34 import java.net.URL;
35 import java.nio.charset.Charset;
36 import java.text.Normalizer;
37 import java.text.Normalizer.Form;
38 import java.util.*;
39
40 import java.awt.datatransfer.*;
41 import sun.awt.datatransfer.*;
42
43 public class CDataTransferer extends DataTransferer {
44 private static final Map<String, Long> predefinedClipboardNameMap;
45 private static final Map<Long, String> predefinedClipboardFormatMap;
46
47 // See SystemFlavorMap, or the flavormap.properties file:
48 // We should define a few more types in flavormap.properties, it's rather slim now.
49 private static final String[] predefinedClipboardNames = {
50 "",
51 "STRING",
52 "FILE_NAME",
53 "TIFF",
54 "RICH_TEXT",
55 "HTML",
56 "PDF",
57 "URL",
58 "PNG",
110
111 @Override
112 public boolean isImageFormat(long format) {
113 int ifmt = (int)format;
114 switch(ifmt) {
115 case CF_TIFF:
116 case CF_PDF:
117 case CF_PNG:
118 case CF_JPEG:
119 return true;
120 default:
121 return false;
122 }
123 }
124
125 @Override
126 public Object translateBytes(byte[] bytes, DataFlavor flavor,
127 long format, Transferable transferable) throws IOException {
128
129 if (format == CF_URL && URL.class.equals(flavor.getRepresentationClass())) {
130 String[] strings = dragQueryFile(bytes);
131 if(strings.length == 0) {
132 return null;
133 }
134 return new URL(strings[0]);
135 } else if(isUriListFlavor(flavor)) {
136 // dragQueryFile works fine with files and url,
137 // it parses and extracts values from property list.
138 // maxosx always returens property list for
139 // CF_URL and CF_FILE
140 String[] strings = dragQueryFile(bytes);
141 bytes = String.join(System.getProperty("line.separator"),
142 strings).getBytes();
143 // now we extracted uri from xml, now we should treat it as
144 // regular string that allows to translate data to target represantation
145 // class by base method
146 format = CF_STRING;
147 } else if (format == CF_STRING) {
148 bytes = Normalizer.normalize(new String(bytes, "UTF8"), Form.NFC).getBytes("UTF8");
149 }
150
151 return super.translateBytes(bytes, flavor, format, transferable);
152 }
153
154 @Override
155 synchronized protected Long getFormatForNativeAsLong(String str) {
156 Long format = predefinedClipboardNameMap.get(str);
157
158 if (format == null) {
159 if (java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().isHeadlessInstance()) {
160 // Do not try to access native system for the unknown format
161 return -1L;
162 }
163 format = registerFormatWithPasteboard(str);
164 predefinedClipboardNameMap.put(str, format);
165 predefinedClipboardFormatMap.put(format, str);
166 }
167
168 return format;
169 }
170
171 /*
172 * Adds type to native mapping NSDictionary.
173 */
209 private final ToolkitThreadBlockedHandler handler = new CToolkitThreadBlockedHandler();
210
211 @Override
212 public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
213 return handler;
214 }
215
216 @Override
217 protected byte[] imageToPlatformBytes(Image image, long format) {
218 return CImage.getCreator().getPlatformImageBytes(image);
219 }
220
221 private static native String[] nativeDragQueryFile(final byte[] bytes);
222 @Override
223 protected String[] dragQueryFile(final byte[] bytes) {
224 if (bytes == null) return null;
225 if (new String(bytes).startsWith("Unsupported type")) return null;
226 return nativeDragQueryFile(bytes);
227 }
228
229
230 @Override
231 protected Image platformImageBytesToImage(byte[] bytes, long format) throws IOException {
232 return CImage.getCreator().createImageFromPlatformImageBytes(bytes);
233 }
234
235 @Override
236 protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList) throws IOException {
237 ByteArrayOutputStream bos = new ByteArrayOutputStream();
238 for (String file : fileList) {
239 byte[] bytes = file.getBytes();
240 bos.write(bytes, 0, bytes.length);
241 bos.write(0);
242 }
243 return bos;
244 }
245
246 @Override
247 protected boolean isURIListFormat(long format) {
248 String nat = getNativeForFormat(format);
249 if (nat == null) {
250 return false;
251 }
252 try {
253 DataFlavor df = new DataFlavor(nat);
254 if (isUriListFlavor(df)) {
255 return true;
256 }
257 } catch (Exception e) {
258 // Not a MIME format.
259 }
260 return false;
261 }
262
263 private boolean isUriListFlavor(DataFlavor df) {
264 if (df.getPrimaryType().equals("text") && df.getSubType().equals("uri-list")) {
265 return true;
266 }
267 return false;
268 }
269 }
|