]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.eclipse.swt.win32.win32.x86_64/src/org/eclipse/swt/dnd/ByteArrayTransfer.java
3dee95c0ebab0eb27683dacc4d15473a3b054ddb
[simantics/platform.git] / bundles / org.eclipse.swt.win32.win32.x86_64 / src / org / eclipse / swt / dnd / ByteArrayTransfer.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2012 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.swt.dnd;
15
16 import org.eclipse.swt.internal.ole.win32.*;
17 import org.eclipse.swt.internal.win32.*;
18
19 /**
20  * The class <code>ByteArrayTransfer</code> provides a platform specific
21  * mechanism for converting a java <code>byte[]</code> to a platform
22  * specific representation of the byte array and vice versa.
23  *
24  * <p><code>ByteArrayTransfer</code> is never used directly but is sub-classed
25  * by transfer agents that convert between data in a java format such as a
26  * <code>String</code> and a platform specific byte array.
27  *
28  * <p>If the data you are converting <b>does not</b> map to a
29  * <code>byte[]</code>, you should sub-class <code>Transfer</code> directly
30  * and do your own mapping to a platform data type.</p>
31  *
32  * <p>The following snippet shows a subclass of ByteArrayTransfer that transfers
33  * data defined by the class <code>MyType</code>.</p>
34  *
35  * <pre><code>
36  * public class MyType {
37  *      public String fileName;
38  *      public long fileLength;
39  *      public long lastModified;
40  * }
41  * </code></pre>
42  *
43  * <pre><code>
44  * public class MyTypeTransfer extends ByteArrayTransfer {
45  *
46  *      private static final String MYTYPENAME = "my_type_name";
47  *      private static final int MYTYPEID = registerType(MYTYPENAME);
48  *      private static MyTypeTransfer _instance = new MyTypeTransfer();
49  *
50  * private MyTypeTransfer() {}
51  *
52  * public static MyTypeTransfer getInstance () {
53  *      return _instance;
54  * }
55  * public void javaToNative (Object object, TransferData transferData) {
56  *      if (object == null || !(object instanceof MyType[])) return;
57  *
58  *      if (isSupportedType(transferData)) {
59  *              MyType[] myTypes = (MyType[]) object;
60  *              try {
61  *                      // write data to a byte array and then ask super to convert to pMedium
62  *                      ByteArrayOutputStream out = new ByteArrayOutputStream();
63  *                      DataOutputStream writeOut = new DataOutputStream(out);
64  *                      for (int i = 0, length = myTypes.length; i &lt; length;  i++){
65  *                              byte[] buffer = myTypes[i].fileName.getBytes();
66  *                              writeOut.writeInt(buffer.length);
67  *                              writeOut.write(buffer);
68  *                              writeOut.writeLong(myTypes[i].fileLength);
69  *                              writeOut.writeLong(myTypes[i].lastModified);
70  *                      }
71  *                      byte[] buffer = out.toByteArray();
72  *                      writeOut.close();
73  *
74  *                      super.javaToNative(buffer, transferData);
75  *
76  *              } catch (IOException e) {
77  *              }
78  *      }
79  * }
80  * public Object nativeToJava(TransferData transferData){
81  *
82  *      if (isSupportedType(transferData)) {
83  *
84  *              byte[] buffer = (byte[])super.nativeToJava(transferData);
85  *              if (buffer == null) return null;
86  *
87  *              MyType[] myData = new MyType[0];
88  *              try {
89  *                      ByteArrayInputStream in = new ByteArrayInputStream(buffer);
90  *                      DataInputStream readIn = new DataInputStream(in);
91  *                      while(readIn.available() &gt; 20) {
92  *                              MyType datum = new MyType();
93  *                              int size = readIn.readInt();
94  *                              byte[] name = new byte[size];
95  *                              readIn.read(name);
96  *                              datum.fileName = new String(name);
97  *                              datum.fileLength = readIn.readLong();
98  *                              datum.lastModified = readIn.readLong();
99  *                              MyType[] newMyData = new MyType[myData.length + 1];
100  *                              System.arraycopy(myData, 0, newMyData, 0, myData.length);
101  *                              newMyData[myData.length] = datum;
102  *                              myData = newMyData;
103  *                      }
104  *                      readIn.close();
105  *              } catch (IOException ex) {
106  *                      return null;
107  *              }
108  *              return myData;
109  *      }
110  *
111  *      return null;
112  * }
113  * protected String[] getTypeNames(){
114  *      return new String[]{MYTYPENAME};
115  * }
116  * protected int[] getTypeIds(){
117  *      return new int[] {MYTYPEID};
118  * }
119  * }
120  * </code></pre>
121  *
122  * @see Transfer
123  */
124 public abstract class ByteArrayTransfer extends Transfer {
125
126 @Override
127 public TransferData[] getSupportedTypes() {
128         int[] types = getTypeIds();
129         TransferData[] data = new TransferData[types.length];
130         for (int i = 0; i < types.length; i++) {
131                 data[i] = new TransferData();
132                 data[i].type = types[i];
133                 data[i].formatetc = new FORMATETC();
134                 data[i].formatetc.cfFormat = types[i];
135                 data[i].formatetc.dwAspect = COM.DVASPECT_CONTENT;
136                 data[i].formatetc.lindex = -1;
137                 data[i].formatetc.tymed = COM.TYMED_HGLOBAL;
138         }
139         return data;
140 }
141
142 @Override
143 public boolean isSupportedType(TransferData transferData){
144         if (transferData == null) return false;
145         int[] types = getTypeIds();
146         for (int i = 0; i < types.length; i++) {
147                 FORMATETC format = transferData.formatetc;
148                 if (format.cfFormat == types[i] &&
149                         (format.dwAspect & COM.DVASPECT_CONTENT) == COM.DVASPECT_CONTENT &&
150                         (format.tymed & COM.TYMED_HGLOBAL) == COM.TYMED_HGLOBAL  )
151                         return true;
152         }
153         return false;
154 }
155
156 /**
157  * This implementation of <code>javaToNative</code> converts a java
158  * <code>byte[]</code> to a platform specific representation.
159  *
160  * @param object a java <code>byte[]</code> containing the data to be converted
161  * @param transferData an empty <code>TransferData</code> object that will
162  *      be filled in on return with the platform specific format of the data
163  *
164  * @see Transfer#nativeToJava
165  */
166 @Override
167 protected void javaToNative (Object object, TransferData transferData) {
168         if (!checkByteArray(object) || !isSupportedType(transferData)) {
169                 DND.error(DND.ERROR_INVALID_DATA);
170         }
171         // Allocate the memory because the caller (DropTarget) has not handed it in
172         // The caller of this method must release the data when it is done with it.
173         byte[] data = (byte[])object;
174         int size = data.length;
175         long newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
176         OS.MoveMemory(newPtr, data, size);
177         transferData.stgmedium = new STGMEDIUM();
178         transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
179         transferData.stgmedium.unionField = newPtr;
180         transferData.stgmedium.pUnkForRelease = 0;
181         transferData.result = COM.S_OK;
182 }
183
184 /**
185  * This implementation of <code>nativeToJava</code> converts a platform specific
186  * representation of a byte array to a java <code>byte[]</code>.
187  *
188  * @param transferData the platform specific representation of the data to be converted
189  * @return a java <code>byte[]</code> containing the converted data if the conversion was
190  *              successful; otherwise null
191  *
192  * @see Transfer#javaToNative
193  */
194 @Override
195 protected Object nativeToJava(TransferData transferData) {
196         if (!isSupportedType(transferData) || transferData.pIDataObject == 0)  return null;
197
198         IDataObject data = new IDataObject(transferData.pIDataObject);
199         data.AddRef();
200         FORMATETC formatetc = transferData.formatetc;
201         STGMEDIUM stgmedium = new STGMEDIUM();
202         stgmedium.tymed = COM.TYMED_HGLOBAL;
203         transferData.result = getData(data, formatetc, stgmedium);
204         data.Release();
205         if (transferData.result != COM.S_OK) return null;
206         long hMem = stgmedium.unionField;
207         int size = OS.GlobalSize(hMem);
208         byte[] buffer = new byte[size];
209         long ptr = OS.GlobalLock(hMem);
210         OS.MoveMemory(buffer, ptr, size);
211         OS.GlobalUnlock(hMem);
212         OS.GlobalFree(hMem);
213         return buffer;
214 }
215
216 boolean checkByteArray(Object object) {
217         return (object != null && object instanceof byte[] && ((byte[])object).length > 0);
218 }
219 }