Java 2 Platform Standard Edition 5.0 의 드래그＆드롭 하부조직 - xrath.com 에서 번역됨

## JavaTM 2 Platform Standard Edition 5.0 의 드래그＆드롭 하부조직

이 문서에는 다음의 마디가 있습니다.

- 1.0 요건
- 2.0 API
- 2.1 개요
- 2.2 드래그 제스처(gesture)의 인식
  - 2.2. 1 DragGestureRecognizer
- 2.3 드래그 소스
  - 2.3. 1 DragSource 의 정의
  - 2.3. 2 DragSourceContext 의 정의
  - 2.3. 3 DragSourceListener 의 정의
  - 2.3. 4 DragSourceEvent 의 정의
  - 2.3. 5 DragSourceDragEvent 의 정의
  - 2.3. 6 DragSourceDropEvent 의 정의
- 2.4 드롭 타겟
  - 2.4. 1 DropTarget 의 등록 및 등록 해제를 위한 java.awt.Component 의 추가
  - 2.4. 2 DropTarget 의 정의
  - 2.4. 3 DropTargetContext 의 정의
  - 2.4. 4 DropTargetListener 의 정의
  - 2.4. 5 DropTargetDragEvent 및 DropTargetDropEvent 의 정의
  - 2.4. 6 자동 스크롤의 지원
- 2.5 데이터 전송 단계
  - 2.5. 1 FlavorMap 및 SystemFlavorMap
  - 2.5. 2 JVM 경계를 넘는 데이터의 전송
  - 2.5. 3 JVM 경계를 넘는 파일 리스트의 전송
  - 2.5. 4 JVM 경계를 넘는 java.rmi.Remote 참조의 전송
- 3.0 문제점
  - 3.0. 1 다양한 플랫폼 프로토콜 엔진에 관한 문제점
  - 3.0. 2 VM 간의 전송인가, 그렇지 않으면 VM 내의 전송인가
  - 3.0. 3 Transferable 의 라이프 타임
  - 3.0. 4 Transferable 를 개입시켜 공개되는 전송원객체의 ACTION_MOVE 시멘틱스
  - 3.0. 5 ACTION_REFERENCE 조작의 시멘틱스
- 부록 A:DropTargetPeer 의 정의
- 부록 B:DragSourceContextPeer 의 정의
- 부록 C:DropTargetContextPeer 의 정의

## 1.0 요건

이 스펙에서는, Java 2 플랫폼의 드래그＆드롭 기능의 API 를 정의합니다.

이 스펙으로 규정하는 주된 요건은, 다음과 같습니다.

1. AWT 및 Swing 클래스에 의해 구현되는 Java GUI 클라이언트에 대해서, 플랫폼에 의존하지 않는 드래그＆드롭 기능을 제공한다
2. 플랫폼에 의존하는 드래그＆드롭 기능을 통합해, 다음과 같은 기능을 사용하는 네이티브 어플리케이션간에 행해지는 드래그＆드롭 조작에 Java 클라이언트를 참가할 수 있도록(듯이) 한다
   - OLE (Win32) 드래그＆드롭
   - XDND 프로토콜
   - CDE/Motif 동적 프로토콜
   - MacOS
   - OS/2
3. 100% Pure JavaOS/Java 의 구현 지원
4. 기존의 `java.awt.datatransfer. *` 패키지를 활용해, MIME 표준 베이스의 확장 가능한 데이터형 시스템에 기술되고 있는, 데이터의 전송을 사용 가능하게 한다
5. 사용자 보조 기능을 이용할 수 있는 경우에, 그 기능의 사용을 제외하지 않는 것
6. 다양한 입력 디바이스의 지원가 가능한 확장성

이 스펙은, 위에서 언급한 이전의 연구로부터 파생하고 있습니다만, JavaBeansTM 이벤트 모델이나 경량 (Swing) 컴퍼넌트가 출현해, 크로스 플랫폼의 통합과 상호 운용성의 문제의 이해가 깊어져 온 결과, 원의 연구와는 꽤 다른 스펙이 집어 넣어져 있습니다.

## 2.0 API

이후시에에서는, 드래그＆드롭 API 에 대해 설명합니다.

### 2.1 개요

드래그＆드롭은, 많은 그래피컬 사용자 인터페이스 (GUI) 시스템에 보여지는 직접적인 조작의 제스처(gesture)로, GUI 내의 표현 요소에 논리적으로 관련지을 수 있었던 2 개의 원가요소간에 정보를 전송하기 위한 기구를 제공합니다. 일반적으로, 드래그＆드롭은, 사용자가 적절한 입력 디바이스를 사용해 실시하는 물리적인 제스처(gesture)에 의해 생깁니다. 드래그＆드롭은, GUI 의 표현 요소상에서 데이터 전송의 결과를 알 수 있도록(듯이), 네비게이션중에, 사용자에게 계속적으로 피드백하는 기구와 계속되어 행해지는 데이터의 협상 및 전송을 용이하게 하는 기능을 제공합니다.

일반적인 드래그＆드롭 조작은, 다음과 같이 몇개의 상태로 나눌 수가 있습니다 (이 차례 대로 행해지는 것은 아니다).

- `Transferable` (전송 가능하게 될 수 있는) 데이터의 드래그＆드롭을 개시하기 위해서, GUI 의 표현 요소 (`Component`)에 관련지을 수 있었던 `DragSource` (드래그 소스)가 작성된다
- GUI 의 표현 요소 (`Component`)에 관련지을 수 있어`Transferable` 데이터형을 소비할 가능성이 있는 1 개 이상의 `DropTarget` (드롭 타겟)가 작성 또는 삭제된다
- `Component` 에 대해서 사용자가 개시한 드래그 제스처(gesture)의 추적 및 식별을 실시하기 위해서(때문에),`DragGestureRecognizer` 이 `DragSource` 로부터 취득되어`Component` 에 관련지을 수 있다
- 사용자는,`Component` 에 대해서 드래그 제스처(gesture)를 실시한다. 등록된 `DragGestureRecognizer`가 그것을 검출해,`DragGestureListener` 에 통지한다

  주:이 문서에서는, 드래그＆드롭 조작의 개시 요인이, 인간인 사용자에 의한 물리적인 제스처(gesture)인 것을 반복 언급하고 있습니다만, 이것에는,`DragSource` 가 적절히 구현되고 있는 경우의, 프로그램에 의한 드래그＆드롭 조작도 포함되어 있습니다.

- `DragGestureListener` 로부터의 지시에 의해, GUI `Cursor` (커서)를 애니메이션화하거나 조작의 대상이 되는 아이템의 `Image` (화상)를 draw 하는 등 해,`DragSource` 가 사용자에 대신해 드래그＆드롭 조작을 개시한다
- 사용자의 제스처(gesture)가, 관련하는 `DropTarget` 를 가지는 GUI 의 `Component` 를 통과할 때,`DragSource` 는, 통지를 받아 Drag Over 피드백 효과를 제공해,`DropTarget` 는, 통지를 받아 지원되는 조작 및 관계하는 데이터형에 근거해 Drag Under 피드백 효과를 제공한다

  제스처(gesture) 자체는, 논리 커서를 GUI 계층을 넘어 움직여, GUI `Component` 의 지오메트리와 교차합니다. 이 결과, 논리 Drag 커서는 `Component` 및 관련하는 `DropTarget` 내에 접어들어, 그것들을 횡단하고 나서 나갑니다.

  `DragSource` 객체는, 일반적으로의 경우는, 논리 커서에 관련지을 수 있었던 GUI `Cursor` 를 애니메이션화하는 것에 의해, 사용자에게 「Drag Over」피드백을 명시합니다.

  `DropTarget` 객체는, 일반적으로의 경우는, GUI `Cursor` 아래에 있는 관련지을 수 있었던 GUI `Component` 에 애니메이션을 draw 하는 것에 의해, 사용자에게 Drag Under 피드백을 명시합니다.

- 피드백 효과의 결정, 및 데이터 전송을 하는 경우는 그 조작이 최종적으로 성공했는지 어떠했는지가, 다음과 같이 파라미터화 된다:
- 사용자가 선택해,`DragSource` 및 `DropTarget` 로 지원되는 전송 「조작」(카피, 이동 또는 참조 (링크))에 의해(카피, 이동 또는 참조 (링크)) 마다
- `DragSource` 에 의해 제공되는 데이터형세트와 `DropTarget` 로 인식할 수 있는 데이터형 세트와의 공통 부분에 의한다
- 사용자가 드래그 조작을 종료하면(자), 일반적으로은 드롭이 성공하지만, 이 때 `DragSource` 와 `DropTarget` 의 양쪽 모두에,`Transferable` 객체를 개입시켜 `DragSource` 에 관련지을 수 있었던 정보를 포함한 통지가 건네받아 형태 협상 및 결과 정보의 전송을 한다

이 문서의 이후의 부분에서는, 이 모델을 지원하기 위해서 제안된 API 의 변경의 상세한 것에 대하여 설명합니다.

### 2.2 드래그 제스처(gesture)의 인식

드래그＆드롭 조작을 개시할 수 있는 제스처(gesture)는, 플랫폼,`Component`, 및 디바이스 마다 다릅니다. 이 때문에, 조작의 의존성을 캡슐화하기 위한 기구가 필요합니다. 이 기구가 있으면, 드래그＆드롭 조작을 개시하는``컴퍼넌트의 작성이 간단하게 됩니다.

#### 2.2. 1 DragGestureRecognizer

`DragGestureRecognizer` 는, 모든 디바이스, 플랫폼, 및 `Component`고유의 드래그＆드롭 제스처(gesture) recognizer용의 추상 base class로, 다음과 같이 정의되고 있습니다.

    public abstract DragGestureRecognizer {
        protected DragGestureRecognizer(
            DragSource  ds,
            Component c,
            int  srcActions,
            DragGestureListener dgl
        );
        public Component getComponent();
        public void      setComponent(Component c);
        public int  getSourceActions();
        public void setSourceActions(int actions);
        public java.awt.InputEvent getTriggerEvent();
        public void resetRecognizer();
        public void addDragGestureListener(
            DragGestureListener dgl
        ) throws TooManyListenerExceptions;
        public void removeDragGestureListener(
           DragGestureListener dgl
        );
        protected abstract void registerListeners();
        protected abstract void unregisterListeners();
        protected void fireDragGestureRecognized(
           int dragAction
        );
        protected void appendEvent(InputEvent awtie);
    }

`DragGestureRecognizer` 에 적절한 특정의 구상 서브 클래스는,`DragSource` 인스턴스,`Toolkit` 등, 다양한 방법으로 취득할 수 있습니다. 구상 구현 서브 클래스는,`Class` 참조를 추상 `DragGestureRecognizer` 슈퍼 클래스로 지정하는 것에 의해, 표준 API 로부터 취득할 수 있습니다. 이 열매 파라미터의 구상 서브 클래스는, 인스턴스화 되어 요구 바탕으로 돌려주어집니다.

`DragGestureRecognizer` 인스턴스가 `Component` 및 `DragSource` 에 관련지을 수 있으면(자), 그 인스턴스의 특정의 `EventListener` 세트가 타겟 `Component` 와 함께 등록되어, 그 `Component` 에 제공된 이벤트의 몇개인가가 감시되어 개시 제스처(gesture)가 검출됩니다. `registerListeners` 및 `unregisterListeners` 를 사용해, 이러한 감시 `EventListener` 의 추가 및 삭제를 실시할 수가 있습니다.

지정된 `Component` 또는 `DragSource` 가, 그 `DragGestureRecognizer` 에 대해서 올바른 상태에 없는지, 그 `DragGestureRecognizer` 와 상호 운용성이 없는 경우는,`DragGestureRecognizer` 에 의해,`IllegalStateException` 또는 `IllegalArgumentException` 가 throw 될 가능성이 있습니다.

`DragGestureRecognizer` 의 구상 인스턴스에 의해, 관련하는 `Component` 상에서 드래그를 개시하는 사용자 제스처(gesture)가 검출되었을 때는,`DragGestureListener` 이벤트의 uni-cast 이벤트 소스상에 등록되어 있는 `DragGestureListener` 에 대해서 `DragGestureEvent` 가 발생합니다. 이 `DragGestureListener` 에 의해, 관련하는 `DragSource` 에 대한 드래그＆드롭 조작의 개시가 지시받습니다 (적절한 경우).

구현은, 마우스 디바이스 제스처(gesture)를 인식하기 위해서 (적어도) 추상 서브 클래스 `MouseDragGestureRecognizer` 를 제공합니다. 그 외의 입력 디바이스 또는 특정의 Component 클래스의 시멘틱스를 지원하기 위해서, 그 외의 추상 서브 클래스가 플랫폼으로부터 제공되는 일도 있습니다. 이 `MouseDragGestureRecognizer` 의 구상 슈퍼 클래스에서는, 플랫폼에 의존하는 마우스 베이스의 제스처(gesture)가 캡슐화됩니다. 이 구상 슈퍼 클래스는,`createDragGestureRecognizer (Class adgrc, DragSource ds, Component c, int sa, DragGestureListener dgl)` 메소드를 개입시켜 `Toolkit` 객체로부터 취득할 수 있습니다. 이 `Toolkit` 의 API 로부터, 플랫폼에 의존하는 구상 구현이 제공됩니다. 이 구현은, 플랫폼에 의존하지 않는 특정의 추상 정의 (클래스)가 상속되고 있습니다.

`MouseDragGestureRecognizer` 추상 클래스는, 다음과 같이 정의되고 있습니다.

    public abstract   MouseDragGestureRecognizer
           extends    DragGestureRecognizer
    	  implements MouseListener, MouseMotionListener {

        public MouseDragGestureRecognizer(
            DragSource  ds,
            Component   c,
            int  sa,
            DragGestureListener dsl
        );
        //...
    }

`DragGestureListener` 는, 다음과 같이 정의되고 있습니다.

    public interface DragGestureListener extends EventListener {
        void dragGestureRecognized(DragGestureEvent dge);
    }

일반적으로,`dragGestureRecognized()` 메소드는 단지,`DragGestureEvent` 의 간이 API `startDrag` 를 사용해, 관련하는 `DragSource` 상에서 드래그＆드롭 조작을 개시합니다.

개시 제스처(gesture)에 영향을 주는 각 `Component` (클래스 또는 인스턴스)의 동작은, 일반적으로, 이 `DragGestureListener` 메소드에 구현되는지, 적절 또는 가능한 경우는 `DragGestureRecognizer` 서브 클래스에 구현됩니다.

`DragGestureEvent` 는, 다음과 같이 정의되고 있습니다.

    publc class DragGestureEvent extends EventObject {
    	public DragGestureEvent(DragGestureRecognizer dgr,
                 int  dragAction,
                 java.util.List  events
         );
        public DragGestureRecognizer getSourceAsDragGestureRecognizer();
        public Component  getComponent();
        public DragSource getDragSource();
        public java.util.Iterator iterator();
        public Object[] toArray();
        public Object[] toArray(Object[] array);
        public int getDragAction();
        public startDrag(Cursor             dragCursor,
                         Transferable       t,
                         DragSourceListener dsl
        );
        public startDrag(Cursor             dragCursor,
                         Image              dragImage,
                         Point              imageOffset,
                         Transferable       t,
                         DragSourceListener dsl
        );
        //...
    }

`DragGestureEvent` 에 의해, 직전에 인식된 제스처(gesture)의 특성에 관한 정보가 모두 캡슐화됩니다. 다음의 정보가 캡슐화됩니다.

- 제스처(gesture)를 인식한 `DragGestureRecognizer`
- 제스처(gesture)가 발생한 `Component`
- 조작을 처리하는 `DragSource`
- 제스처(gesture)를 포함한 `InputEvent` 객체의 리스트
- 사용자 제스처(gesture)에 의해 선택된 액션 (ACTION_COPY, ACTION_MOVE, 또는 ACTION_LINK)

### 2.3 드래그 소스

`DragSource` (드래그원래)는, 드래그＆드롭 조작을 개시하는 원가요소입니다.

#### 2.3. 1 DragSource 의 정의

`DragSource` 및 관련지을 수 있었던 정수의 인터페이스는, 다음과 같이 정의되고 있습니다.

`DnDConstants` 클래스는, 전송 대상으로 적용될 가능성이 있는 조작을 정의하고 있습니다.

    public final class java.awt.dnd.DnDConstants {
         public static int ACTION_NONE = 0x0;
         public static int ACTION_COPY = 0x1;
         public static int ACTION_MOVE = 0x2;
         public static int ACTION_COPY_OR_MOVE= ACTION_COPY | ACTION_MOVE;
         public static int ACTION_REFERENCE = 0x40000000;
    }

    public class java.awt.dnd.DragSource {
         public static Cursor     DefaultCopyDrop;
         public static Cursor     DefaultMoveDrop;
         public static Cursor     DefaultLinkDrop;
         public static Cursor     DefaultCopyNoDrop;
         public static Cursor     DefaultMoveNoDrop;
         public static Cursor     DefaultLinkNoDrop;
         public static DragSource getDefaultDragSource();
         public static boolean isDragImageSupported();
         public void startDrag(DragGestureEvent trigger,
    			Cursor             dragCursor,
    			Image	           dragImage,
    			Point	           dragImageOffset,
    			Transferable       transferable,
    			DragSourceListener dsl,
    			FlavorMap          fm)
    		  throws InvalidDnDOperationException;
         protected DragSourceContext  createDragSourceContext(
    			DragSourceContextPeer dscp,
    			DragGestureEvent      trigger,
    			Cursor                dragCursor,
    			Image                 dragImage,
      			Point                 dragImageOffset,
    			Transferable          transferable,
    			DragSourceListener    dsl
          );
          public FlavorMap getFlavorMap();
          public DragGestureRecongizer createDragGestureRecognizer(
                  Class               abstractRecognizerClass,
                  Component           c,
                  int                 srcActions,
                  DragGestureListener dgl
         );
         public DragGestureRecongizer createDefaultDragGestureRecognizer(
                  Component           c,
                  int                 srcActions,
                  DragGestureListener dgl
         );
         //...
    }

`DragSource` 는, 수많은 상황으로 사용될 가능성이 있습니다.

- JVM 의 라이프 타임의 사이, 그 JVM 에 대해 1 개의 디폴트 인스턴스(이 스펙으로 정의)
- `TextField` 등의, 드래그 이니씨에이터 객체가 될 수 있는 클래스에 대해 1 개의 인스턴스[구현에 의존]
- 특정의 `Component` 의 인스턴스에 대해 1 개. 또는, GUI 의 `Component` 의 인스턴스에 관련지을 수 있었던 어플리케이션 고유의 객체에 대해 1 개[구현에 의존]
- 그 외의 임의가 관련짓고[구현에 의존]

제어 객체는, 드래그 조작을 처리하기 위해서, 사용자의 제스처(gesture)의 전에 `DragSource` 의 인스턴스를 취득해, 관련하는 `Component` 를 유효하게 합니다. 인스턴스를 취득하면(자),`DragGestureRecognizer` 를 취득해,`DragSource` 를 `Component` 에 관련지을 필요가 있습니다.

사용자의 제스처(gesture)의 최초의 해석, 및 거기에 계속되는 드래그 조작의 개시는,`Component` 의 구현에 의해 행해집니다. 일반적으로 이것은,`DragGestureRecognizer` 에 의해 구현됩니다.

제스처(gesture)가 발생하면(자), 사용자에 의한 조작 제스처(gesture)를 처리해, 드래그＆드롭 프로토콜의 통지를 배포하기 위해서,`DragSource` 의 `startDrag` 메소드가 불려 갑니다. `DragSource` 에서는, 어느 시점에서도 복수의 드래그＆드롭 조작을 경향으로 할 수 없습니다. 현재의 조작이 완료할 때까지는,`startDrag` 요구를 추가하려고 하면(자),`IllegalDnDOperationException` 가 throw 되어 거부됩니다.

드래그 조작을 개시하기 위해서,`startDrag` 메소드의 호출원래는, 다음의 파라미터를 제공합니다.

- 제스처(gesture)의 `DragGestureEvent`

- 지정된 조작에 대해서 초기의 Drag Over 피드백을 나타내는 `Cursor`(사용자에 대해서 No Drop 의 시각적인 피드백을 제공하는 `Cursor`).

- 조작 대상의 1 개 또는 복수의 아이템을 시각적으로 표현하는 `Image` (생략 가능)

이 기능을 지원 가능한 플랫폼상에서는, 드래그 이미지를 조작에 관련지어, 보다 충실히 Drag Over 를 피드백할 수 있습니다. 이 이미지는, 일반적으로은, 드래그 되는 1 개(살) 또는 복수의 객체의 작은 「아이콘」의 표시로, 배후의 시스템은, Cursor 애니메이션의 움직임을 추적하면서 이 이미지를 읽어들입니다. 이미지는,`Cursor` 애니메이션과 동시에 움직입니다만, 일반적으로은, Cursor 애니메이션과는 다른 것입니다.

이 기능을 이용할 수 없는 개소, 또는 배후의 시스템이 draw 하는데 적절하지 않은 종류의 이미지의 경우, 이 파라미터는 무시되어 결과적으로 `Cursor` 의 「Drag Over」애니메이션만으로 되므로, 어플리케이션은, 이 기능에 의존하지 않습니다. 특정의 플랫폼상에 이 기능이 존재할지 어떨지는, static 메소드 `isDragImageSupported` 를 호출하는 것에 의해 테스트할 수 있습니다.

- `Image` 가 건네받았을 경우에는 `Point` (`Component` 의 좌표 공간내)는, 드래그 「Cursor」의 「핫 스포트」의 좌표에 대한 상대 위치에서 `Image` 의 기점이 지정된다. `Component` 의 좌표 공간내에 있어, 최초의 제스처(gesture)의 시점에서, 그 「핫 스포트」에 대한 상대 위치에,`Image` 의 「Drag Over」애니메이션을 적절히 배치해 개시하기 위해서 있다

- 드롭의 성공에 의해, 거기에 계속되는 데이터 전송의 대상이 되는 다양한 `DataFlavor` (데이터의 형태)을 기술한,`Transferable` 의 인스턴스

  `Transferable` 의 인스턴스는, 드래그 조작의 개시시에 `DragSource`에 관련지을 수 있어 드래그＆드롭의 오퍼랜드 또는 대상인, 객체 또는 데이터를 나타내고 있습니다. 이것은, 드래그 조작뒤,`DropTarget` 에 관련지을 수 있었던 `Component` 상에서 드롭이 성공한 결과적으로,`DragSource` 로부터 `DropTarget` 에게 건네지는 정보입니다.

  컨테이너 객체를 작성해, 전송의 대상으로 해 `Transferable` 를 구현하는 것에 의해, 같은 종류 또는 다른 종류의 객체의 복수 컬렉션을 드래그＆드롭 조작의 대상으로 하는 일도 가능합니다. 다만, 타겟이 되는 어느 네이티브 플랫폼 시스템에서도, 이러한 컬렉션을 기술 및 전송 하는 기구는 표준에서는 지원되고 있지 않습니다. 그 때문에, 투과적이고 플랫폼 이식성의 높은 방법에서는, 이러한 전송을 구현할 수 없습니다.

- 사용자에게 Drag Over 피드백을 제공하기 위해(때문에), 진행중의 조작 상태의 변경을 통지하는 이벤트를 그 후에 받는 `DragSourceListener` 의 인스턴스

전술한 것처럼,`startDrag` 메소드의 주된 역할은, 사용자를 위해서(때문에) 드래그를 개시하는 것입니다. 이 때문에는,`startDrag` 메소드는, 조작 그 자체를 추적하기 위한 `DragSourceContext` 의 인스턴스를 작성할 필요가 있습니다. 한층 더 중요한 (일)것은, 이 메소드는, 기본적인 플랫폼 구현내에서, 조작을 그것을 개시해야 하는 것입니다. 이것을 실시하기 위해서(때문에),`DragSource` 는, 우선 기본적인 시스템으로부터 (일반적으로은 `java.awt.Toolkit.createDragSourceContextPeer` 메소드의 호출에 의해) `DragSourceContextPeer` 를 취득하고 나서, 새롭게 작성된 `DragSourceContextPeer` (기본적인 시스템의 기능에 대해서 플랫폼에 의존하지 않는 인터페이스를 제공한다)를 `DragSourceContext` 에 관련지을 필요가 있습니다. `startDrag` 메소드는,`createDragSourceContext` 메소드를 호출해, 적절한 `DragSourceContext` 의 인스턴스를 생성해,`DragSourceContextPeer` 를 관련짓습니다.

드래그＆드롭 시스템이, 어떠한 이유로써 드래그 조작을 개시할 수 없는 경우는,`startDrag` 메소드는,`java.awt.dnd.InvalidDnDOperationException` 를 throw 해 그 상태를 나타냅니다. 일반적으로, 이 예외는, 기본적인 플랫폼 시스템이 드래그를 개시하는 상태에 없는 경우인가, 또는 지정된 파라미터가 무효인 경우에 throw 됩니다.

드래그 조작중에는, 소스가 드래그 조작의 개시시에 공개한 조작세트는, 변경할 수 없는 것에 주의해 주세요. 즉, 드래그 조작중은,`DragSource` 에 관한 조작이 일정할 필요가 있습니다.

`getFlavorMap` 메소드는,`Transferable` 에 의해 공개된 `DataFlavors` 를, 기반의 드래그＆드롭 플랫폼의 데이터형명에 맵 하기 위해서, 기본적인 시스템에 의한 `FlavorMap` 객체의 취득에 사용됩니다 [`FlavorMap` 의 자세한 것은, 이후를 참조].

「private」 `FlavorMap` 는,`DragSource` 의 `startDrag()` 메소드에 건네줄 수가 있습니다. null 도 건네줄 수가 있습니다만, 이 경우는,`DragSource` 클래스 또는 인스턴스의 「디폴트」의 `FlavorMap` 가 사용됩니다.

#### 2.3. 2 DragSourceContext 의 정의

`DragSource` 의 `startDrag` 메소드가 정상적으로 불려 간 결과,`DragSourceContext` 클래스의 인스턴스가 작성됩니다. 이 인스턴스는,`DragSource` 를 위해서(때문에) 조작 상태를 추적해, 상태의 변화를 `DragSourceListener` 에 배포하는 역할을 완수합니다.

`DragSourceContext` 클래스는, 다음과 같이 정의되고 있습니다.

    public class DragSourceContext implements DragSourceListener {
    	public DragSourceContext(
    		DragSourceContextPeer dscp,
    		DragGestureEvent  trigger,
    		Cursor  dragCursor,
    		Image  dragImage,
    		Point  dragOffset,
    		Transferable  transferable,
    		DragSourceListener  dsl
    	);
            public DragSource  getDragSource();
            public Component  getComponent();
            public DragGestureEvent	getTrigger();
            public Image	 getDragImage();
            public Point	 getDragImageOffset();
            public void transferablesFlavorsChanged();
            public int getSourceActions();
            public Cursor getCursor();
            pbulic void   setCursor(Cursor Cursor)
    		    throws InvalidDnDOperationException;
            public void addDragSourceListener(DragSourceListener dsl)
    		    throws TooManyListenersException;
            public void removeDragSourceListener(DragSourceListener dsl);
            protected updateCurrentCursor(int dropOperation,
                                       int targetActions,
                                       int status
            );
            // values for status parameter above.
            protected static final int DEFAULT = 0;
            protected static final int ENTER   = 1;
            protected static final int OVER    = 2;
            protected static final int CHANGED = 3;

            //...
    }

`DragSourceContext` 자체가 `DragSourceListener` 를 구현하는 것에 주목해 주세요. 이것에 의해,`DragSource` 에 의해 작성된 플랫폼의 피어인 `DragSourceContextPeer` 의 인스턴스는,`DragSourceContext` 에 진행중의 조작 상태의 변화에 대해 통지할 수 있게 됩니다. 따라서 `DragSourceContext` 은, 플랫폼과 조작의 이니씨에이터에 의해 제공된 `DragSourceListener` 의 사이에 끼어들 수가 있게 됩니다.

전송원, 또는 드래그＆드롭 조작의 이니씨에이터에 관해서 플랫폼이 공개하는 상태의 변화의 자세한 것은, 다음과 같습니다.

드래그＆드롭 조작중의 이니씨에이터에 관한 상태의 변화의 통지는, 위에 나타낸 것처럼,`DragSourceContextPeer` 로부터 적절한 `DragSourceContext` 에 배포됩니다. `DragSourceContext` 은 통지를, uni-cast JavaBeans 에 준거한 `EventListener` 서브 인터페이스를 개입시켜,`startDrag` 로 `DragSource` 에 등록된 `DragSourceListener` 를 구현하는 임의의 객체에 위양 합니다.

`DragSourceListener` 의 주된 역할은, 드래그＆드롭 조작중에 사용자 조작의 진행을 감시해, Drag-Over 효과를 사용자에게 피드백하는 것입니다. 일반적으로, 피드백은, Drag Cursor 를 변경하는 것으로 행해집니다.

각 드래그 조작에는, 다음의 2 종류의 논리 커서 (드래그 커서) 상태를 관련지을 수 있고 있습니다.

- Drop `Cursor`. 유효한 `DropTarget` 상에 드래그 하고 있을 때 표시되는 커서
- NoDrop `Cursor`. 그 이외의 물건 위에 드래그 하고 있을 때 표시되는 커서 (드래그 개시시의 커서의 초기 상태)

`Cursor` 상태는,`DragSourceContext` 의 `setCursor` 메소드를 호출하는 것에 의해 변경할 수 있습니다.

#### 2.3. 3 DragSourceListener 의 정의

`DragSourceListener` 인터페이스는, 다음과 같이 정의됩니다.

    public interface java.awt.dnd.DragSourceListener
    	extends java.util.EventListener {
    	void dragEnter	(DragSourceDragEvent dsde);
    	void dragOver	(DragSourceDragEvent dsde);
    	void dropActionChanged (DragSourceDragEvent dsde);
    	void dragExit	(DragSourceEvent     dse);
    	void dragDropEnd  (DragSourceDropEvent dsde);
    }

드래그 조작이 진행하는에 따라,`DragSourceListener` 의 `dragEnter`,`dragOver`, 및 `dragExit` 메소드가 불려 갑니다. 이것은,`DropTarget` 를 관련지을 수 있고 있는 GUI `Component` 의 지오메트리에 교차하도록(듯이), 논리 「Drag」커서의 위치를 사용자가 안내한 결과입니다 (`DropTarget` 의 프로토콜의 상호작용에 관한 자세한 것은 다음을 참조).

`DragSourceListener` 의 `dragEnter` 메소드는, 다음의 조건이 채워졌을 때에 불려 갑니다.

- 논리 커서의 핫 스포트가, 어느 GUI `Component` 의 가시 지오메트리에 최초로 사귀었다
- 그 `Component` 에, 액티브한 `DropTarget` 를 관련지을 수 있고 있다

  `DropTarget` 에 등록된 `DropTargetListener` 의 `dragEnter` 메소드가 불려 가 정상적으로 처리를 돌려줍니다.

  등록된 `DropTargetListener` 가,`DropTargetDragEvent` 의 `acceptDrag` 메소드를 호출해, 전송원이 실행할 가능성이 있는 드롭 동작, 및 이용 가능한 데이터형 (`DataFlavors`)을 조사한 다음, 드래그를 받아들입니다.

  `DragSourceListener` 의 `dragOver` 메소드는, 다음의 조건이 채워졌을 때에 불려 갑니다.

  - 커서의 논리 핫 스포트가 이동했지만, 직전의 `dragEnter` 의 호출에 관련지을 수 있었던 `Component` 의 가시 지오메트리에, 아직 교차하고 있다
  - 그 `Component` 에, `DropTarget` 를 관련지을 수 있고 있다
  - 그 `DropTarget` 가 아직 액티브하다
  - `DropTarget` 에 등록된 `DropTargetListener` 의 `dragOver` 메소드가 불려 가 정상적으로 처리를 돌려주었다
  - `DropTarget` 이,`rejectDrag` 를 개입시켜 드래그 거부하지 않는다

  `DragSourceListener` 의 `dragExit` 메소드는, 다음의 조건 가운데 1 개가 채워졌을 때에 불려 갑니다.

  - 커서의 논리 핫 스포트가, 직전의 `dragEnter` 의 호출에 관련지을 수 있었던 `Component` 의 가시 지오메트리와 이미 교차하고 있지 않다

    또는

  - 논리 커서의 핫 스포트가 교차한 `Component` (이것이 직전의 `dragEnter` 의 호출로 연결되는 것)에, 액티브한 `DropTarget` (또는 `DropTargetListener`)를 관련지을 수 있지 않았다

    또는

  - `dragEnter` 또는 `dragOver` 가 마지막에 불려 가고 나서, 현재의 `DropTarget` 의 `DropTargetListener` 가 `rejectDrag` 를 호출했다

  `DragSourceListener` 의 `dropActionChanged()` 메소드는, 드래그 조작을 실행하기 위해서 사용자가 사용하고 있는, mouse button나 키보드의 키등의 입력 디바이스 상태가 바뀌었을 때에 불려 갑니다.

  `dragDropEnd()` 메소드는, 조작이 완료한 것을 나타내기 위해서(때문에) 불려 갑니다. `DragSourceDropEvent` 의 `getDropSuccess` 메소드는, 종료 상태를 확인하기 위해서 사용됩니다. `getDropAction` 메소드는,`DropTarget` 가 `DropTargetDropEvent` 의 `acceptDrop` 파라미터를 개입시켜 드롭 조작에 적용하기 위해서 선택한 조작을 돌려줍니다.

  이 메소드가 완료하면(자), 현재의 `DragSourceContext` 및 관련지을 수 있었던 자원이 무효가 됩니다.

  #### 2.3. 4 DragSourceEvent 의 정의

  `DragSourceEvent` 클래스는,`DragSource` 에 속하는 모든 이벤트의 루트 `Event` 클래스에서, 다음과 같이 정의되고 있습니다.

      public class   java.awt.dnd.DragSourceEvent extends java.util.EventObject {
              public DragSourceEvent(DragSourceContext dsc);
              public DragSourceContext getDragSourceContext();
              //...
      };

  이 이벤트의 인스턴스는,`DragSourceListener` 의 `dragExit` 메소드에게 건네집니다.

  #### 2.3. 5 DragSourceDragEvent 의 정의

  `DragSourceDragEvent` 클래스는, 다음과 같이 정의되고 있습니다.

      public class java.awt.dnd.DragSourceDragEvent extends DragSourceEvent {
              public int getTargetActions();
              public int getUserAction();
              public int getGestureModifiers();
              public int getGestureModifiersEx();
              public int getDropAction();
      }

  이 클래스의 인스턴스는,`DragSourceListener` 의 `dragEnter`,`dragOver`, 및 `dragGestureChanged` 의 각 메소드에게 건네집니다.

  `getDragSourceContext` 메소드는, 현재의 드래그＆드롭 조작에 관련지을 수 있었던 `DragSourceContext` 를 돌려줍니다.

  `getUserAction` 메소드는, 사용자 제스처(gesture)에 의해 현재 선택되고 있는 액션을 돌려줍니다.

  The `getTargetActions` 메소드는, 드롭 액션이 드래그 소스에 의해 지원되고 있는 경우에는, 현재의 드롭 타겟으로로부터 선택되고 있는 드롭 액션을 돌려주어, 드롭 액션이 드래그 소스에 의해 지원되어 있지 않은 경우에는 `DnDConstants.ACTION_NONE` 를 돌려줍니다.

  이것들 2 개의 결과와 드래그 소스에 의해 지원되는 일련의 드롭 액션의 논리적인 상호작용이, 드롭에 의한 실제의 효과를 정의해,`getDropAction` 를 개입시켜 돌려주어집니다.

  `getGestureModifiers` 메소드는, 입력 디바이스의 수식자의 현재 상태를 돌려줍니다. 일반적으로, 입력 디바이스의 수식자는, 사용자의 제스처(gesture)에 관련지을 수 있었던 mouse button 및 키보드의 키입니다.

  `getGestureModifiersEx` 메소드는, 사용자의 제스처(gesture)에 관련지을 수 있었던 입력 디바이스의 확장 수식자의 현재 상태를 돌려줍니다.

  #### 2.3. 6 DragSourceDropEvent 의 정의

  `DragSourceDropEvent` 클래스는, 다음과 같이 정의되고 있습니다.

      public public class java.awt.dnd.DragSourceDropEvent
                              extends java.util.EventObject {
             public DragSourceDropEvent(DragSourceContext dsc);
             public DragSourceDropEvent(DragSourceContext dsc,
      				int  action,
      				boolean success);
             public boolean getDropSuccess();
             public int getDropAction();
      }

  이 클래스의 인스턴스는,`DragSourceListener` 의 `dragDropEnd` 메소드에게 건네집니다. 이 이벤트는 드래그＆드롭 조작의 종료 상태를 `DragSource` 를 위해서(때문에) 캡슐화합니다.

  드롭이 발생해, 드롭에 관계한 `DropTarget` 가 `DropTargetContext` 의 `dropComplete` 메소드를 개입시켜 데이터 전송의 성공 또는 실패를 나타내, 이니씨에이터는 `getDropSuccess` 메소드를 개입시켜 이 상태를 취득할 수 있습니다. 드롭처인 `DropTarget` 가 드래그의 대상에 대해서 실행하는 조작은, (`DropTarget` 의 `acceptDrop` 메소드에 의해 건네받은) `getDropAction` 메소드를 개입시켜 돌려주어집니다.

  사용자가 `DropTarget` 의 외부에서 제스처(gesture)를 종료하는지,`DropTarget` 이 `rejectDrop` 를 호출했을 경우 등, 어떠한 이유로써 드롭이 발생하기 전에 드래그 조작이 중지되었을 경우는,`getDropSuccess` 메소드는 false 를 돌려줍니다. 그렇지 않은 경우는 true 를 돌려줍니다.

  ### 2.4 드롭 타겟

  #### 2.4. 1 DropTarget 의 등록 및 등록 해제를 위한 java.awt.Component 의 추가

  `java.awt.Component` 클래스에는,`DropTarget` 와의 관련짓고 및 관련짓고 해제를 가능하게 하기 위해서, 2 개의 메소드가 추가되었습니다. 특히 다음의 점이 중요합니다.

      public class java.awt.Component /* ... */ {
      	//...
      	public synchronized void setDropTarget(DropTarget dt);
      	public synchronized DropTarget getDropTarget(DropTarget df);
      	//...
      }

  `DropTarget` 를 `Component` 에 관련지으려면 ,`DropTarget.setCompononent` 또는 `Component.setDropTarget` 의 어느 쪽의 메소드를 호출할 수도 있습니다. 이 때문에, 상호 재귀 호출을 막기 위해서(때문에), 양쪽 모두의 메소드의 구현에 준거할 필요가 있습니다.

  `DropTarget` 와 `Component` 가 관련짓고를 해제하는데는,`DropTarget.setCompononent(null)` 또는 `Component.setDropTarget(null)` 의 어느 쪽의 메소드를 호출할 수도 있습니다.

  `DropTarget` 와 `Component` 의 양쪽 모두의 설정 메소드의 스펙에 준거하는 구현은, 서로의 상황을 적절히 관리하도록(듯이) 구현할 필요가 있습니다.

  `DropTarget` 의 열매 파라미터가 `Component` 의, 이 클래스 또는 인스턴스와 함께 사용하는 것이 올바르지 않은 경우는,`setDropTarget` 메소드는,`IllegalArgumentException` 를 throw 합니다. 또,`Component` 가 `DropTarget` 의 외부 설정을 지원하고 있지 않는 경우등도, 이 메소드는 `UnsupportedOperationException` 를 발행합니다.

  #### 2.4. 2 DropTarget 의 정의

  `DropTarget` 는, 조작의 접수측 또는 발송지의 역할에 관련하는, 드래그＆드롭 프로토콜의 플랫폼 고유의 처리를 모두 캡슐화합니다.

  일반적으로, 단일의 `DropTarget` 인스턴스를,`java.awt.Component` 의 임의의 인스턴스에 관련지을 수가 있습니다. 이러한 관계를 확립하면(자), 관련지을 수 있었던 `Component` 의 가시 지오메트리에 논리 커서의 좌표가 교차했을 때에, 드래그＆드롭 조작의 수취가 가능하다라고 해, 이 지오메트리궕쿠라이안트의 데스크탑에 export 됩니다.

  `DropTarget` 클래스는, 다음과 같이 정의되고 있습니다.

      public class java.awt.dnd.DropTarget
             implements DropTargetListener, Serializable {

              public DropTarget(Component          c,
                             int                actions,
                             DropTargetListener dsl,
                             boolean            isActive,
                             FlavorMap          fm
              );
              public DropTarget();
              public DropTarget(Component c);
              public DropTarget(Component c, DropTargetListener dsl);
              public Component getComponent();
              public void      setComponent(Component c);
              public DropTargetContext getDropTargetContext();
              public void addDropTargetListener(DropTargetListener dte)
      		  throws TooManyListenersException;
              public void removeDropTargetListener(DropTargetListener dte);
              public void setActive(boolean active);
              public boolean isActive();
              public FlavorMap getFlavorMap();
              public void      setFlavorMap(FlavorMap fm);
              public void setDefaultActions(int actions);
              public int  getDefaultActions();
              protected DropTargetContext createDropTargetContext();
              public void addNotify(ComponentPeer cp);
              public void removeNotify(ComponentPeer cp);
              // ...
      }

  `Component` 의 열매 파라미터가 `DropTarget` 의, 이 클래스 또는 인스턴스와 함께 사용하는 것이 올바르지 않은 경우는,`setComponent` 메소드는,`IllegalArgumentException` 를 throw 합니다. 또, 이 메소드는,`Component` 로,`DropTarget` 의 외부 설정을 허가하지 않게 지정되고 있는 경우에는,`UnsupportedOperationException` 를 throw 합니다.

  `addDropTargetListener` 및 `removeDropTargetListener` 메소드를 사용해, uni-cast `DropTargetListener` 를 변경할 수 있습니다.

  `setActive` 및 `isActive` 메소드를 사용해,`DropTarget` 를 액티브 또는 비액티브하게 할 수가 있어 한층 더 `DropTarget` 의 현재 상태를 알 수 있습니다.

  `getFlavorMap` 메소드는, 플랫폼에 의존한 형명과 거기에 대응하는 플랫폼에 의존하지 않는 `DataFlavors` 와의 사이의 매핑을 실시하는 목적으로, 이 `DropTarget` 에 관련지을 수 있었던 `FlavorMap` 를 취득하기 위해서 사용합니다.

  `setFlavorMap` 메소드는, 새로운 `FlavorMap` 를 `DropTarget` 에 할당합니다. 파라미터에 null 가 지정되었을 경우는, 「디폴트」의 `FlavorMap` 를 `DropTarget` 에 인스톨 합니다.

  `createDropTargetContext` 메소드는, 드래그 조작으로 최초로 `DropTarget` 에 관련지을 수 있었던 `Component` 를 검출했을 때에, 배후의 플랫폼에 의존한 피어에, 새로운 `DropTargetContext` 의 인스턴스를 제공하기 위해(때문에)인 만큼 불려 갑니다. 현재 `DropTarget` 에 관련지을 수 있고 있는 `DropTargetContext` 가 없는 경우는,`getDropTargetContext` 의 호출에 허가되고 있는 부작용에 의해, 새로운 `DropTargetContext` 의 인스턴스가 생성됩니다.

  `addNotify` 및 `removeNotify` 메소드는,`Component` 의 `ComponentPeer` 에의 관련짓고 ( 및 관련짓고의 해제)를 `DropTarget` 에 통지하기 위해(때문에)인 만큼,`Component` 로부터 불려 갑니다.

  `DropTarget` 자체가 `DropTargetListener` 를 구현하는 것에 주목해 주세요. 이것에 의해, 플랫폼에 의해 작성된 플랫폼의 피어인 `DropTargetContextPeer` 의 인스턴스는,`DropTarget` 에 진행중의 조작 상태의 변화에 대해 통지할 수 있게 되어, 따라 `DropTarget` 는, 플랫폼과 `DropTarget` 에 등록되어 있는 `DropTargetListener` 의 사이에 끼어들 수가 있게 됩니다.

  #### 2.4. 3 DropTargetContext 의 정의

  진행중의 드래그＆드롭 조작에 관련지을 수 있었던 논리 커서가,`DropTarget` 에 관련지을 수 있었던 `Component` 의 가시 지오메트리와 최초로 교차하면(자),`DropTarget` 에 관련지을 수 있었던 `DropTargetContext` 가 인터페이스가 됩니다. 이 인터페이스를 개입시켜,`DropTargetListener` 로부터 접수측의 프로토콜 상태를 제어하거나 액세스 하거나 할 수 있습니다.

  `DropTarget` 의 `DropTargetContext` 가 존재하지 않는 경우는,`DropTarget` 의 `getDropTargetContext` 메소드가 불려 갔을 때에, 부작용으로서 `DropTarget` 의 `createDropTargetContext` 메소드에 의해 `DropTargetContext` 가 작성됩니다. <>

  `DropTargetContext` 인터페이스는, 다음과 같이 정의됩니다.

      public class DropTargetContext {
              public DropTarget getDropTarget();
              public Component getComponent();
              public void  dropComplete(boolean success)
      				throws InvalidDnDOperationException;
              public void acceptDrag(int dropAction);
              public void rejectDrag();
              public void acceptDrop(int dropAction);
              public void rejectDrop();
              public void addNotify(DropTargetContextPeer dtcp);
              public void removeNotify();
              protected Transferable createTransferableProxy(Transferable t,
      		   boolean isLocal
              );
              protected void setTargetActions(int actions);
              protected int  getTargetActions();
              protected DataFlavor[] getCurrentDataFlavors();
              protected List getCurrentDataFlavorsAsList();
              protected boolean isDataFlavorSupported(DataFlavor df);
              protected Transferable getTransferable();
              // ...
      }

  액세스 및 제어를 실시하는 메소드는, 대부분이 protected 메소드입니다. 이러한 메소드 상태에 public 액세스 할 때는, 일반적으로, 요구를 `DropTargetContext` 에 위양 하는 특정의 `DropTargetEvent` 서브 클래스의 호출에 의해 실시합니다.

  `getDropTarget()` 메소드는, 이 `DropTargetContext` 를 작성한 `DropTarget` 를 돌려줍니다.

  `getComponent` 메소드는, 이 `DropTargetContext` 를 작성한 `DropTarget` 에 관련지을 수 있었던 `Component` 를 돌려줍니다.

  `acceptDrag` 메소드는,`DropTargetDragEvent` 의 유사한 메소드로부터 위양 되고 있어,`DropTargetListener` 의 메소드 `dragEnter()`,`dragOver`, 또는 `dropActionChanged` 로부터 불려 갑니다. `acceptDrag` 의 호출은, 접수측에서는 지정된 조작을 포함한 드롭의 수취의 준비가 되어 있는 것을 의미합니다. 일반적으로은, 현재 사용자가 선택하고 있는 액션이 조작으로서 지정됩니다.

  `rejectDrag` 메소드는,`DropTargetDragEvent` 의 유사한 메소드로부터 위양 되고 있어,`DropTargetListener` 의 메소드 `dragEnter`,`dragOver`, 또는 `dropActionChanged` 로부터 불려 갑니다. `rejectDrag` 의 호출은, 현재 사용자가 선택하고 있는 액션을 납득할 수 없는 것을 의미합니다.

  `acceptDrop` 메소드는,`DropTargetDropEvent` 의 유사한 메소드로부터 위양 되고 있어,`DropTargetListener` 의 `drop` 메소드로부터 불려 갑니다. `acceptDrop` 의 호출은, 접수측에서는 지정된 조작을 포함한 드롭의 수취의 준비가 되어 있는 것을 의미합니다. 일반적으로은, 현재 사용자가 선택하고 있는 액션이 조작으로서 지정됩니다.

  `rejectDrop` 메소드는,`DropTargetDropEvent` 의 유사한 메소드로부터 위양 되고 있어,`DropTargetListener` 의 `drop` 메소드로부터 불려 갑니다. `rejectDrop` 의 호출은, 접수측에서는 현재 사용자가 선택하고 있는 액션을 포함한 드롭의 수취가 불가능한 것을 의미합니다. 이 메소드에 의해, 드래그＆드롭 조작이 종료해, 데이터는 전송 되지 않습니다.

  `dropComplete` 메소드는,`DropTargetListener` 가 드래그＆드롭 조작의 대상을 포함한 전송을 완료한 것, 및 조작이 완료한 것을, 전송원의 `DragSource` 에 통지합니다. 전송의 성공 (또는 실패) 및 지정된 오퍼레이션의 그 이후의 적용이, 실제의 파라미터의 값에 의해 통지됩니다.

  `getDataFlavors` 메소드는,`DragSource` 로 이용할 수 있는 `DataFlavors` 의 배열을 돌려줍니다.

  `getTransferable` 메소드는,`Transferable` 를 돌려주어,`getTransferData` 메소드를 개입시킨 데이터 전송을 가능하게 합니다. 반환되는 `Transferable` 는, 반드시 `DragSource` 가 등록한 것은 아니고, 프록시의 가능성도 있습니다 (JVM 간의 전송에서는 프록시). 최초로 `acceptDrop` 를 호출하지 않고 `getTransferable` 를 호출하는 것은 부정합니다.

  `addNotify` 및 `removeNotify` 메소드는, 기본적인 플랫폼의 `DropTargetContextPeer` 에 의해 배타적으로 불려 가`DropTargetContext` 및 그것과 관련지을 수 있었던 `DropTarget` 로 발생 또는 종료한 드래그＆드롭 조작을 `DropTargetContext` 에 통지합니다.

  `createTransferableProxy` 메소드에 의해,`DropTargetContext` 의 구현으로,`DropTargetListener` 라고 불러 방편원으로부터 제공된 `Transferable` 와의 사이에 `Transferable` 를 삽입할 수 있게 됩니다. 일반적으로, 호출원래는 기본적인 플랫폼의 `DropTargetContextPeer` 입니다.

  #### 2.4. 4 DropTargetListener 의 정의

  적절한 Drag-under 피드백 시멘틱스의 제공, 및 그 후의 드롭의 처리는,`DropTarget` 에 관련지을 수 있었던 `DropTargetListener` 를 사용해 가능하게 됩니다.

  `DropTargetListener` 는, 전송 바탕으로야는 제안된 동작, 이용 가능한 데이터형, 및 데이터 자체를 검사하는 것에 의해, 드롭이 가능한가 어떤가에 관한 적절한 Drag-under 피드백 및 `DragSource` 에의 응답을 결정합니다.

  특정의 `DropTargetListener` 인스턴스는,`addDropTargetListener` 메소드를 개입시켜 `DropTarget` 에 관련지을 수 있어`removeDropTargetListener` 메소드를 개입시켜 삭제됩니다.

      public interface java.awt.dnd.DropTargetListener
              extends java.util.EventListener {
              void dragEnter            (DropTargetDragEvent dtde);
              void dragOver             (DropTargetDragEvent dtde);
              void dropActionChanged    (DropTargetDragEvent dtde);
              void dragExit             (DropTargetDragEvent dtde);
              void drop                 (DropTargetDropEvent dtde);
      }

  `DropTargetListener` 의 `dragEnter` 메소드는, 논리 Drag 커서의 핫 스포트가,`DropTarget` 에 관련지을 수 있었던 `Component` 의 지오메트리의 가시 부분과 교차했을 때에 불려 갑니다. 이 통지를 받으면(자),`DropTargetListener` 는,`DragSource` 로부터 제공되는 조작 또는 동작, 혹은 데이터형 (`DataFlavors`) 및 데이터 자체를 조사해, 적절한 동작 및 Drag-under 피드백을 결정해,`acceptDrag` 또는 `rejectDrag` 를 부릅니다.

  `DropTargetListener` 의 `dragOver` 메소드는, 움직이고 있는 논리 Drag 커서의 핫 스포트가,`DropTarget` 에 관련지을 수 있었던 `Component` 의 지오메트리의 가시 부분과 계속 교차하고 있는 동안에 불려 갑니다. 이 통지를 받으면(자),`DropTargetListener` 는,`DragSource` 로부터 제공되는 동작, 및 데이터형 혹은 데이터 자신을 조사해, 적절한 동작 및 Drag-under 피드백을 결정해,`acceptDrag` 또는 `rejectDrag` 를 호출합니다.

  `DropTargetListener` 의 `dragExit` 메소드는, 논리 Drag 커서의 핫 스포트가,`DropTarget` 에 관련지을 수 있었던 `Component` 의 지오메트리의 가시 부분과 교차하지 않게 되었을 때, 또는 `drop` 에 의한 통지를 하기 직전에 불려 갑니다. 이 통지를 받으면(자),`DropTargetListener` 는, 그때까지 적용한 모든 Drag-under 피드백 효과를 취소합니다. 이 때의 부작용으로서`DropTarget` 에 관련지을 수 있었던 `DropTargetContext` 가 무효가 되는 것에 주의해 주세요.

  교차하고 있는 동안에 사용자가 드래그 제스처(gesture)를 종료하면(자),`DropTargetListener` 의 `drop` 메소드가 불려 갑니다. 이 통지를 받으면(자),`DropTargetListener` 는,`DropTargetDropEvent` 객체상의 `getSourceActions` 메소드의 반환값에 의해 지정된 조작을,`getTransferable` 메소드로부터 반환된 `Transferable` 객체상에서 실행합니다. 그 후, 관련지을 수 있었던 `DropTargetContext` 의 `dropComplete` 메소드를 호출해, 조작의 성공 또는 실패를 나타냅니다.

  #### 2.4. 5 DropTargetDragEvent 및 DropTargetDropEvent 의 정의

  `DropTargetEvent` 및 `DropTargetDragEvent` 는 다음과 같이 정의되고 있습니다.

      public abstract class java.awt.dnd.DropTargetEvent
      	  extends java.util.EventObject {

              public DropTargetContext getDropTargetContext();
              //...
      }

  `DropTargetEvent` 는,`DropTargetListener` 의 `dragExit` 메소드에게 건네집니다.

      public class   java.awt.dnd.DropTargetDragEvent
      	                 extends java.awt.dnd.DropTargetEvent {
              public Transferable getTransferable();
              public Point  getLocation();
              public int   getSourceActions();
              public getDropAction();
              public DataFlavor[] getCurrentDataFlavors();
              public List  getCurrentDataFlavorsAsList();
              public boolean isDataFlavorSupported();
      	public void acceptDrag(int operation);
      	public void rejectDrag();
              //...
      }

  `DropTargetDragEvent` 는,`DropTargetListener` 의 `dragEnter`,`dragOver`, 및 `dropActionChanged` 메소드에게 건네집니다.

  `getLocation` 메소드는, 관련지을 수 있었던 `Component` 를 원점으로서 논리 Drag 커서의 핫 스포트의 현재의 상대 좌표를 돌려줍니다.

  `getSourceActions` 메소드는, 현재의 「동작」, 즉 `DragSource` 에 의해 현재의 드래그＆드롭의 제스처(gesture)에 관련지을 수 있었던 조작 (ACTION_MOVE, ACTION_COPY, 또는 ACTION_REFERENCE)을 돌려줍니다.

  `getDropAction` 메소드의 반환값은, 사용자 제스처(gesture)에 의해 현재 선택되고 있는 액션을 돌려줍니다.

  `getCurrentDataFlavors`,`getCurrentDataFlavorsAsList`, 및 `isDataFlavorSupported` 메소드는, 전송원의 리스트형을 접수측에서 조사할 때 사용합니다.

  `getTransferable` 메소드는, 전송원의 데이터를 접수측에서 조사할 때 사용합니다. `DropTargetDragEvent` 인스턴스상의 `getTransferable` 는 각각의 `DropTargetListener` 의 메소드내에서만 불려 가 모든 필요한 데이터는 메소드가 돌려주어지기 전에, 반환된 `Transferable` 로부터 꺼내지는 것에 주목해 주세요.

  `DropTargetDropEvent` 는, 다음과 같이 정의됩니다.

      public class java.awt.dnd.DropTargetDropEvent
      	  extends java.awt.dnd.DropTargetEvent {

              public Point	  getLocation();
              public int getSourceActions();
              public int getDropAction();
              public void acceptDrop(int dropAction);
              public void rejectDrop();
              public boolean isLocalTransfer();
              public DataFlavor[] getCurrentDataFlavors();
              public List  getCurrentDataFlavorsAsList();
              public boolean isDataFlavorSupported(DataFlavor df);
              public Transferable getTransferable();
              public void dropComplete(boolean success);
              //...
      }

  드롭이 발생하면(자),`DropTargetDropEvent` 가 `DropTargetListener` 의 `drop` 메소드에게 건네집니다. `DropTargetDropEvent` 는 `DropTargetListener` 에 대해서,`getTransferable` 메소드로부터 반환되는 `Transferable` 를 개입시켜, 이 조작에 관련지을 수 있었던 데이터에의 액세스를 제공합니다.

  `getSourceActions` 메소드의 반환값은, 드롭의 발생시에 전송 바탕으로야는 정의된 동작을 돌려주도록(듯이) 정의되고 있습니다.

  `getDropAction` 메소드의 반환값은, 사용자 제스처(gesture)에 의해 현재 선택되고 있는 액션을 돌려줍니다.

  `getLocation` 메소드의 반환값은, 드롭이 발생한 위치를 돌려주도록(듯이) 정의되고 있습니다.

  `getCurrentDataFlavors`,`getCurrentDataFlavorsAsList`, 및 `isDataFlavorSupported` 메소드는,`Transferable` 의 `getTransferData` 메소드에 의해 후속의 전송을 할 때, 전송원의 데이터형을 접수측에서 조사할 때 사용됩니다.

  `drop` 메소드의 표준의 구현은, 액션 및 이용 가능한 `DataFlavor` 를 검사해, 교환이 정상적으로 종료할지 어떨지를 판정합니다.

  교환이 발생하면(자),`DropTargetListener.drop` 구현은,`getTransferable` 를 호출하기 전에, 선택된 조작으로 열매 파라미터로서 `acceptDrop` 를 호출합니다. `acceptDrop` 의 전에 `getTransferable` 를 호출하면(자),`InvalidDnDOperationException` 가 발생합니다.

  `rejectDrop` 를 호출해, 드롭 조작을 거부하는 일도 가능합니다. `rejectDrop`를 호출하면(자), 전송원과 접수측의 사이의 대화가 정지합니다. 이 때문에, 일반적으로은,`rejectDrop` 를 호출하면(자), 즉시 `drop` 메소드로부터 돌아옵니다.

  드래그＆드롭 조작의 전송원이,`drop` 에 의한 통지의 접수측과 동일한 물리 JVM 에 존재하는 경우는,`isLocalTransfer` 메소드로부터 true 가 돌려주어집니다. 동일한 물리 JVM 에 존재하지 않는 경우는, false 가 돌려주어집니다.

  로컬의 물리 JVM 로 불려 간 `Transferable.getTransferData` 로부터 객체 참조를 받는 경우는, 이 차이가 중요하게 됩니다. 이 경우, 받은 객체 참조는, 전송원으로 보관 유지되고 있는 것 것과 같습니다 (카피, 프록시, 및 다른 객체는 아니다). 이 때문에, 접수측에서는 공유 객체 참조를, 다음과 같은 특별한 방법으로 처리할 필요가 있습니다.

  - 액션이 ACTION_COPY 의 경우는, 접수측은, 객체 및 전송 되는 데이터의 특성에 응해, 객체 자체 또는 캡슐화되는 데이터, 혹은 그 양쪽 모두의 카피를 작성한다.
  - 액션이 ACTION_MOVE 의 경우는, 접수측은,`dropCompete` 가 불려 가 전송의 완료가 전송 바탕으로 통지될 때까지, 객체 또는 캡슐화된 데이터 상태를 변경할 수 없습니다. 또, 전송원래는,`getTransferData` 메소드로부터 이러한 객체를 돌려준 후에도,`dragDropEnd` 에 의한 통지를 받을 때까지, 객체 상태를 변경할 수 없습니다.
  - 액션이 ACTION_LINK 의 경우는, 접수측 및 전송원래는,`dropComplete` 및 `dragDropEnd` 메소드가 처리될 때까지는, 교환된 객체 또는 그 객체에 포함되는 데이터 상태를 변경할 수 없다. 그 후, 공유 시멘틱스는, 공유되고 있는 객체에 의존한 구현이 됩니다.

  `dropComplete` 메소드는, 관련지을 수 있었던 드래그＆드롭 조작의 종료를 통지해, 접수측에서 실행된 전송의 성공 (또는 실패)을 돌려줍니다. 이 메소드를 호출하면(자),`DragSourceListener` 의 `dragDropEnd` 메소드가,`DragSourceDropEvent` 로 사용할 수 있는 적절한 상태로 불려 갑니다. 이 메소드의 호출해에 실패하면(자), 드래그＆드롭 조작이 정상적으로 종료하지 않습니다.

  #### 2.4. 6 자동 스크롤의 지원

  많은 GUI `Component` 는, 대규모 (대규모로 될 수 있다) 데이터 세트에 대해, 스크롤 가능한 「뷰포트」를 제공합니다. 드래그＆드롭 조작시에는, 이러한 뷰포트를 자동 스크롤 할 수 있는 것이 바람직할 것입니다. 그러면, 조작의 대상물을 드롭 하고 싶은 특정의 (처음은 뷰포트에 표시되어 있지 않다) 멤버의 위치까지 스크롤 하면서, 데이터 세트상을 이동할 수가 있습니다.

  스크롤 가능한 `Component` 는, 다음의 인터페이스를 구현하는 것에 의해,`DropTarget` 에 드래그의 「자동 스크롤」기능을 제공합니다.

      public interface Autoscroll {
              Insets getAutoscrollInsets();
              void autoScrollContent(Point cursorLocn);
      }

  다음의 조건이 채워졌을 경우, 구현하는 `DropTarget` 는, 관련지을 수 있었던 `Component` (존재하는 경우)의 `autoscroll`메소드를 정기적으로 호출해,`Component` 의 좌표로 나타낸 현재의 논리 커서의 위치를 건네줍니다.

  - 논리 커서의 핫 스포트가, 관련지을 수 있었던 `Component` 의 가시 지오메트리, 및 `getAutoscrollInsets` 메소드가 돌려주는 `Insets` 에 의해 기술된 경계 영역과 교차했을 경우
  - 논리 커서의 핫 스포트가, 구현에 정의되고 있는 기간 (밀리 세컨드) 이동하지 않았던 경우 (다음의 조건에 의존)
  - 최초의 트리거의 발생에 이어 커서가 이동했지만, 플랫폼에 의존한 히스테리시스치 (픽셀)를 넘지 않은 경우

  위의 몇개의 조건이 채워지고 없어지면(자), 다음에 트리거가 되는 조건이 발생할 때까지 자동 스크롤 기능은 종료합니다.

  자동 스크롤 개시전의 초기 지연, 자동 스크롤 통지의 간격, 및 픽셀의 히스테리시스치는 모두, 외부에서 설정할 수 있어`Toolkit.getDesktopProperty` 메소드로부터 문의할 수가 있습니다.

  ### 2.5 데이터 전송 단계

  유효한 드롭이 발생했을 경우는,`DropTargetListener` 의 `drop` 메소드는, 제스처(gesture)에 관련지을 수 있었던 데이터의 전송에 착수합니다. ``DropTargetDropEvent` 는, 전송 되는 데이터 객체를 나타내는 `Transferable` 객체를 취득하는 수단을 제공합니다.`

  우선,`drop` 메소드에 의해,`DropTargetListener` 가,`rejectDrop` 를 호출해 드롭을 거부하는지 (이 경우는 곧바로 복귀한다), 또는 `getSourceActions` 에 의해 반환된 조작으로부터 선택된 조작을 지정하는 `acceptDrop` 를 호출해 드롭을 받아들입니다.

  `acceptDrop` 의 뒤는,`getTransferable` 가 불려 가 반환된 `Transferable` 의 `getTransferData` 메소드를 개입시켜 데이터 전송을 합니다. 마지막으로, 드롭의 전송처에서 전송원으로부터의 객체의 전송이 완료하면(자),`DropTargetContext.dropComplete` 가 불려 가 전송의 성공 또는 즉시 실패가 통지됩니다.

  `DropTargetContext.dropComplete` 메소드로부터 복귀하는 것과 동시에,`Transferable` 및 `DragSourceContext` 의 인스턴스가 유효하다라고 말하는 보증이 없어지기 (위해)때문에, 다음에 가베지 컬렉트할 수 있도록(듯이), 접수 측에보다 인스턴스에의 모든 참조가 파기됩니다.

  ACTION_REFERENCE 조작을 사용하는 경우는, 전송원과 전송처에서 객체 및 관련지을 수 있었던 전송의 시멘틱스에 합의가 필요합니다. 일반적으로, JVM 내의 전송에서는, 전송원과 전송처의 사이에 라이브 객체 참조가 건네받습니다만, JVM 간의 전송, 또는 네이티브 어플리케이션과 Java 어플리케이션의 사이에서는, 라이브 객체 참조는 무의미해, URI 등의 다른 종류의 참조가 교환됩니다. 전송이 JVM 내의 전송인가 어떤가는,`DragSource` 와 `DropTarget` 의 양쪽 모두로 검출할 수 있습니다.

  #### 2.5. 1 FlavorMap 및 SystemFlavorMap

  타겟이 되는 모든 드래그＆드롭 플랫폼은, 같은 기구를 사용해 전송 데이터의 형태를 나타냅니다만, 이 표현 방법에는 차이가 있습니다. Java 플랫폼에서는,`DataFlavor` 내에 캡슐화된 MIME 형식을 사용해 데이터형을 나타냅니다. Java 와 플랫폼에 네이티브인 어플리케이션과의 사이에서의 데이터 전송을 허가하려면 , 이러한 플랫폼명의 존재가 공개될 필요가 있습니다. 이 때문에, 이러한 플랫폼에 의존하는 형명, 그러한 표현 방법, 및 Java MIME 베이스의 `DataFlavor` 간으로, 플랫폼에 의존하지 않는 확장 가능한 매핑을 작성하기 위한 기구가 필요합니다.

  이 구현은, 플랫폼에 네이티브인 데이터형 (캐릭터 라인)과 `DataFlavors` 의 구축에 사용되는 MIME 형식 (캐릭터 라인)과의 사이의 매핑을 외부에서 지정하는 기구를 제공합니다. 이 외부 매핑은, 배후의 플랫폼의 드래그＆드롭 기구에 의해 전송원으로부터 전송 먼저 export 되는 적절한 `DataFlavors` (MIME 형식)를 공개하기 위해서, 배후의 플랫폼 고유의 구현 코드로 사용됩니다.

  배후의 시스템은,`DragSource` 클래스 및 `DropTarget` 클래스의 어느 쪽을 사용해도, 플랫폼에 의존하는 이름과 `DataFlavors` 간의 매핑에 액세스 할 수 있습니다.

      public interface java.awt.datatransfer.FlavorMap {
              java.util.Map getNativesForFlavors(DataFlavor[] dfs);
              java.util.Map getFlavorsForNatives(String[] natives);
      }

  `getNativesForFlavors` 메소드는,`DataFlavor` 의 배열을 파라미터에 있어, 열매 파라미터 `dfs` 로부터, 관련지을 수 있었던 `String` 형의 값 (그 MIME 형식에 대응하는 플랫폼에 의존하는 형명에 일치)과 함께,`DataFlavor` 형의 제로개이상의 키를 포함한 `Map` 객체를 돌려줍니다.

  `getFlavorsForNatives` 메소드는,`String` 형의 배열을 파라미터에 있어, 열매 파라미터 natives 로부터, 관련지을 수 있었던 `DataFlavor` 형의 값 (그 플랫폼에 의존하는 형명에 대응하는 플랫폼에 의존하지 않는 형태에 일치)과 함께,`String` 형의 제로개이상의 키를 포함한 `Map` 객체를 돌려줍니다.

  이러한 메소드에 의해 반환되는 `Map` 객체는 가변의 경우도 있습니다만, 반드시 그 필요는 없습니다.

  null 가 이러한 메소드 가운데 어느 쪽인가에 건네받으면(자), 호출의 시점에서 구현에 있어 기존인 모든 키와 값의 현재의 맵이 돌려주어집니다.

  예를 들어, Win32 에서는, 심플 텍스트의 클립보드 형식의 이름은, CF_TEXT (실제로는 이것은 정수 1)입니다만, Motif 에서는, STRING 라는 이름의 X11 Atom 입니다. MIME 형식을 사용해 이것을 표현하는 경우는, text/plain charset=us-ascii 입니다. 플랫폼에 대한 이식성이 있는 `FlavorMap` 은, Win32 상의 CF_TEXT 와 Motif/X11 상의 STRING 간의 매핑을 실시합니다.

  일반적으로, 이러한 매핑은,`SystemFlavorMap` 에 구현할 경우에, 외부의 고정된 설정 형식 (프로퍼티 파일 또는 URL) 으로 유지해, 플랫폼으로부터 로드해, 특정의 플랫폼에 적절히 `FlavorMap` 를 설정하도록(듯이) 합니다.

  `SystemFlavorMap` 클래스는, 전시스템에 공통된 매핑세트를 지정하기 위한 , 플랫폼에서 설정이 가능한 단순한 기구를 구현하기 위해서 제공되고 있습니다. 다음과 같이 정의되고 있습니다.

      public class  java.awt.datatransfer.SystemFlavorMap implements FlavorMap, FlavorTable {
      	public static FlavorMap getSystemFlavorMap();
      	public synchronized Map getNativesForFlavors(DataFlavor[] dfs);
      	public synchronized Map getFlavorsForNatives(String[] natives);
      	public static String encodeDataFlavor(DataFlavor flav);
      	public static String encodeJavaMIMEType(String mimeType);
      	public static boolean isJavaMIMEType(String mimeStr);
      	public static String decodeJavaMIMEType(String nat);
      	public static DataFlavor decodeDataFlavor(String nat);
      	//...
      }

  `SystemFlavorMap` 클래스는, 플랫폼 고유의 `FlavorMap` 의 프로퍼티 파일 (`java.awt.Properties` 를 참조)을 사용한 단순한 구현을 제공합니다. 이 클래스는, AWT 의 프로퍼티인 AWT.flavorMapFileURL (`Toolkit.getProperty` 를 참조)의 값인가, 또는 `System.getProperty("java.home") + File.separator + "lib" + File.separator + "flavormap.properties"` 의 디폴트의 파일 위치를 사용해, 그 프로퍼티으로부터 적절한 `Map` 를 작성합니다.

  게다가 이 클래스는, Java `MimeType` 와 플랫폼에 의존한 이름 공간의 코드화 또는 복호화에 사용하는, 몇개의 static 인 간이 함수를 제공합니다. 프로퍼티 파일의 구문은, 다음과 같습니다.

  { <platform_type_name> ‘=' <IETF_MIME_RFC_conformant_specification> <nl> } *

  `DragSource` 및 `DropTarget` 의 디폴트 구현은, 그 외의 구현에 의해 오버라이드(override)되어 있지 않으면,`getFlavorMap` 메소드로부터 `SystemFlavorMap` 를 돌려줍니다.

  #### 2.5. 2 JVM 경계를 넘는 데이터의 전송

  이 API 에서는, Java 와 네이티브 어플리케이션의 사이에 데이터를 드래그＆드롭 할 수 있는 것이 최우선의 목표입니다. 이것이, Java 가상 머신의 경계를 넘어 데이터가 건네받았을 때에 행해지는, 실제의 데이터 encode 및 데이터 교환의 방법 및 기구에 크게 영향을 주고 있습니다.

  이러한 데이터 교환에서는, 전송원 또는 접수측이 Java 의 데이터형을 인식하지 않는 네이티브 어플리케이션이기 (위해)때문에, 이 드래그＆드롭의 시스템에서는 단순하게 Java 객체의 참조를 건네줄 수가 없습니다. 전송원 또는 접수측에서 Java 의 데이터형의 인식 또는 조작을 실시할 수가 없을 가능성이 있기 (위해)때문에입니다.

  데이터 교환이 발생하면(자), 전송원과 접수측의 구현에 관계없이, 데이터형 및 encode의 방식으로 쌍방이 합의하고 있을 때 한정해, 데이터 교환이 실현됩니다. 즉 유감스럽게, 교환으로 발생하는 문제는, 대부분의 경우, 전송원 및 접수측의 어플리케이션이 원인입니다.

  실질적으로는, 플랫폼에 의존한 이미지, 문서, 그 외의 「Content-Type」 등, 「네이티브」인 데이터 형식의 경우에 대해, 관련하는 외부 형식의 encode와 복호화는, 전송을 실시하는 전송원과 전송처의 책임에 의해 행해집니다.

  이 드래그＆드롭 시스템에서는, 그러한 Java 가상 머신의 경계를 넘는 「네이티브」인 데이터형의 외부 표현이,`java.io.InputStream` 또는 그 서브 클래스내에 캡슐화되어 공개됩니다.

  즉,`java.io.InputStream` 를 상속하는 표현 클래스를 포함한 모든 `DataFlavor` 가, Java 가상 머신의 경계를 넘어 전송 가능하고, 전송을 위해서(때문에) 공개되게 됩니다.

  이러한 네이티브인 데이터형의 교환을 구현하려면 ,`DataFlavor` 를 MIME 의 「Content-Type」에 정의합니다. MIME 의 「Content-Type」에는, 「네이티브」인 데이터형의 특성이,`java.io.InputStream` 클래스를 상속하는 표현 클래스를 사용해 기술되고 있습니다. `java.io.InputStream` 클래스에 의해, 캡슐화된 데이터가 바이트 스트림에 encode 됩니다.

  특히, 이러한 `InputStream` 서브 클래스에 의해, 다음의 시멘틱스가 구현됩니다.

  - `java.io.InputStream` 형의 인수를 1 개 취하는 public 생성자 의 제공

    `java.io.InputStream` 의 서브 클래스에 의해 이 생성자 이 제공되기 (위해)때문에,`DropTarget` 에 관련지을 수 있었던 드래그＆드롭 시스템에서는, 요구된 `DataFlavor` 로 지정되고 있는 표현 클래스의 인스턴스가 자동적으로 재구축 됩니다. 그 인스턴스는, 서브 클래스의 요구에 응해 포맷 된 캡슐화 데이터를 포함한 `InputStream` 에 의해 초기화됩니다. 이 인스턴스는, 초기화되면(자),`Transferable.getTransferData` 메소드의 호출 측에 돌려주어집니다. 다음에, 호출측에서는, 데이터 스트림이 전송 되면(자), 포맷 된 내용이 읽어내지고 해석됩니다.

  - `InputStream.read(byte b[], int off, int len)` 의 구현의 제공

  이 메소드의 제공 (또는 슈퍼 클래스 구현의 상속)에 의해,`DragSource` 에 관련지을 수 있었던 드래그＆드롭 시스템에서는, 캡슐화된 데이터의 encode 된 스트림이 `Transferable` 로부터 자동적으로 추출됩니다. 이 결과, 이 데이터는 JVM 의 경계를 넘어,`DataFlavor` 의 리퀘스터에 단순한 바이트 스트림로서 전송 됩니다.

  #### 2.5. 3 JVM 경계를 넘는 파일 리스트의 전송

  드래그＆드롭 전송의 전형적인 대상으로 해, 플랫폼에 의존하는 1 개(살) 이상의 파일명의 리스트를 들 수가 있습니다. 파일명 리스트의 작성 또는 처리를 실시하는 프로그램을 간단하게 개발할 수 있도록(듯이), 드래그＆드롭 시스템에서는, 파일명 리스트는 독자적으로 처리됩니다.

  `DataFlavor` 가 `application/x-java-file-list;class=java.util.List` 라고 하는 MIME 「Content-Type」로 지정되고 있는 경우, 드래그＆드롭 시스템에서는, 리스트의 요소가 `java.io.File` 형의 객체의 리스트와 동질인 것을 전제로 하고 있습니다. 따라서, 파일 리스트의 전송이 지원되고 있는 경우는, 이 `DataFlavor` 가 요구되면(자), 전송원에서는, 그 `File` 객체의 `List` 가 구축됩니다. 또, 접수측이, 유효한 `DataFlavor` 를 요구했을 경우는, 그 `File` 객체의 `List` 를 전송원으로부터 받습니다. 전송원과 타겟간에 파일 리스트를 전송 할 때는, 이 독자적인 처리에 의한 간단한 기구가 사용됩니다.

  #### 2.5. 4 JVM 경계를 넘는 java.rmi.Remote 참조의 전송

  RMI 기구의 기능을 사용하면, JVM 간에 객체 참조를 드래그＆드롭 할 수가 있습니다. 드래그＆드롭 시스템에서는, 다음의 요건을 채우도록(듯이), 객체 참조의 전송이 자동적으로 구성됩니다.

  - 요구된 `DataFlavor` 에 관련지을 수 있었던 인터페이스의 표현 클래스가,`java.rmi.Remote` 와 `java.io.Serializable` 의 양쪽 모두를 구현하고 있다

    (MIME 의 「Content-Type」에는, 임의의 적합한 데이터형, 또는 application/x-java-remote-object 를 지정할 수 있다)

    (효과적으로 구현하려면 , 전송 된 객체 구현 클래스는,`java.rmi.server.UnicastRemoteObject` 로부터 상속되어 있지 않으면 안 된다. RMI 시스템에는 필요한 초기화가 몇개인가 구현되고 있기 때문에 있다. 그 초기화가 구현되어 있지 않은 경우는, 전송은 정상적으로 완료하지 않는다)

  - 드롭 액션이 ACTION_LINK 이다

  이러한 조건이 채워지고 있는 경우는, 적절한 `DataFlavor` 가 요구되면(자), 리퀘스터 (전송원과 다른 JVM 에 존재하는 경우)에 반환되는 객체는,`DataFlavor` 의 표현 클래스로서 지정되고 있는 `Remote` 객체 서브 인터페이스의 인스턴스에의 RMI 참조가 됩니다.

  ## 3.0 문제점

  #### 3.0. 1 다양한 플랫폼 프로토콜 엔진에 관한 문제점

  특정의 기본적인 플랫폼의 드래그＆드롭, 및 윈도우 시스템의 구현에는 제한이 있기 (위해)때문에, 드래그 조작의 대화, 및 AWT `Component` 에의 이벤트 송신의 시멘틱스는, 플랫폼에 의존하고 있습니다. 이 때문에, 드래그 조작중에 `DragSource` 가 그 드래그에 속하는 플랫폼의 윈도우 시스템 이벤트의 처리를 실시해, 일반적으로의 이벤트 처리가 배제되는 일이 있습니다.

  플랫폼 네이티브인 드래그＆드롭 시스템의 싱글스 레드의 처리부와 AWT 내의 구현을 담당하는 네이티브인 윈도우 시스템 이벤트의 대화에 의해,`DropTargetListener`, 및 `DragSourceListener` 에의 「콜백」은, AWT 시스템 이벤트를 처리하는 thread상인가, 또는 thread와 동기 해 발생합니다. 이것은, 시큐리티의 면에서 바람직하지 않은 동작입니다만, 구조는 아니고 구현상의 특징이므로, 피할 수가 없습니다.

  #### 3.0. 2 VM 간의 전송인가, 그렇지 않으면 VM 내의 전송인가

  JVM 내의 드래그＆드롭 전송을 가능하게 하기 위한(해), 기존의 `DataFlavor` 클래스는, 직렬화 된 고정 표현은 아니고, 「라이브」객체 참조의 형태를 표현할 수 있도록(듯이) 확장됩니다. 이러한 객체는, 같은 JVM, 및 `ClassLoader` 문맥내에 있는 전송원과 전송처의 사이에 전송 됩니다.

  MIME 컨텐츠 타입은, application/x-java-local-objectref 가 됩니다.

  #### 3.0. 3 Transferable 의 라이프 타임

  `Transferable` 객체, 거기에 관련지을 수 있었던 `DataFlavor`, 및 드래그＆드롭 조작의 오퍼랜드로 지정된 기본적인 데이터를 캡슐화하는 객체는, 적어도, 조작을 제어하는 `DragSource` 에 관련지을 수 있었던 `DragSourceListener` 가 `dragDropEnd` 이벤트를 받을 때까지 유효합니다. 전송원과 전송처의 사이에서의 조작 대상의 라이프 타임은, 그 시점을 지나 정의되는 구현입니다.

  #### 3.0. 4 Transferable 를 개입시켜 공개되는 전송원객체의 ACTION_MOVE 시멘틱스

  정상적으로 종료한 드래그＆드롭 (ACTION_MOVE) 조작의 「전송원」은, 전송이 정상적으로 완료한 뒤, 곧바로 `Transferable` 의 대상인 객체에의 참조를 삭제 또는 방폐할 필요가 있습니다. 이것은,`DragSourceListener.dragDropEnd` 통지로부터 돌아오기 전에 실시할 필요가 있습니다.

  #### 3.0. 5 ACTION_REFERENCE 조작의 시멘틱스

  이전의 버젼의 스펙에 대한 개발자로부터의 피드백의 결과, 동작 태그 ACTION_REFERENCE 가 추가되었습니다. 이 태그에 의해, 기존의 플랫폼의 드래그＆드롭 「링크」시멘틱스를 포함할 수가 있습니다.

  참조, 즉 링크의 시멘틱스는, 플랫폼 네이티브의 드래그＆드롭에 있어 매우 무례한 것이기 (위해)때문에, 네이티브인 어플리케이션간조차도 본질적으로 쓸모가 있지 않게 되어 있다고 말할 수 있습니다. 이 때문에, 네이티브와 플랫폼에 의존하지 않는 Java 어플리케이션과의 사이로는, 이 시멘틱스의 사용은 추천 되지 않습니다.

  Java 대 Java 로 사용하는 경우, 요구되는 시멘틱스 (동일한 JVM 및 `ClassLoader` 내)는, 전송처가 전송 대상에의 Java 객체 참조를 취득하도록(듯이) 정의되고 있습니다. JVM 또는 `ClassLoader` 간으로는, 시멘틱스의 구현은 정의가 끝난 상태입니다만, 전송원으로부터 전송 먼저 URL 를 보내는지, RMI `Remote` 참조에 의해 구현할 수도 있습니다.

  ## 부록 A:DropTargetPeer 의 정의

  이 정의는, 이 스펙의 표준적인 부분이 아닙니다만, 스펙을 알기 쉽게 하기 위해서 포함할 수 있고 있습니다.

      public interface DropTargetPeer {
              void addDropTarget(DropTarget dt);
              void removeDropTarget(DropTarget dt);
      }

  ## 부록 B:DragSourceContextPeer 의 정의

  이 정의는, 이 스펙의 표준적인 부분이 아닙니다만, 스펙을 알기 쉽게 하기 위해서 포함할 수 있고 있습니다.

      public interface DragSourceContextPeer {
          void startDrag(DragSourceContext dsc,
                         Cursor            c,
                         Image             di,
                         Point             ioff
          ) throws InvalidDnDOperationException;
          Cursor getCursor();
          void   setCursor(Cursor c) throws InvalidDnDOperationException;
          void transferablesFlavorsChanged();
      }

  ## 부록 C:DropTargetContextPeer 의 정의

  이 정의는, 이 스펙의 표준적인 부분이 아닙니다만, 스펙을 알기 쉽게 하기 위해서 포함할 수 있고 있습니다.

      public interface DropTargetContextPeer {
          int  getTargetActions();
          void setTargetActions(int actions);
          DropTarget getDropTarget();
          DataFlavor[] getTransferDataFlavors();
          Transferable getTransferable() throws InvalidDnDOperationException;
          boolean isTransferableJVMLocal();
          void acceptDrag(int dragAction);
          void rejectDrag();
          void acceptDrop(int dropAction);
          void rejectDrop();
          void dropComplete(boolean success);
      }