자원 변경사항 추적

실행 프로그램에서 자원 변경을 일괄처리하는 방법(자원 변경 일괄처리)을 살펴 보았습니다. 이제 다른 면을 살펴 보겠습니다. 플러그인이 실행 중인 동안 발생하는 작업공간에 대한 모든 변경사항을 계속 추적하면 어떻게 되겠습니까? IResourceChangeListener를 작업공간에 등록할 수 있습니다. 변경사항을 설명하는 IResourceChangeEvent 오브젝트를 통해 리스너에 변경사항이 통지됩니다.

리스너 등록

먼저 작업공간에 자원 변경 리스너를 등록해야 합니다.

   IResourceChangeListener listener = new MyResourceChangeReporter();
   ResourcesPlugin.getWorkspace().addResourceChangeListener(
      listener, IResourceChangeEvent.POST_CHANGE);

작업공간 자원이 수정된 후에 리스너에 통지됩니다. 자원을 수정하는 자원 API 메소드는 이 이벤트를 문서화된 작동의 일부로 트리거합니다. 자원 API 메소드에 대한 메소드 주석은 메소드가 자원 변경 이벤트를 트리거하는지 여부를 명시적으로 설명합니다. 예를 들어 IFile.setContents() 주석에 다음이 포함됩니다.

   이 메소드는 자원을 변경합니다. 이 변경사항은 이 파일의 컨텐츠가 변경되었다는 표시를 포함하여
후속 자원 변경 이벤트에서 보고됩니다.

자원을 작성, 삭제, 변경하는 메소드가 일반적으로 이 이벤트를 트리거합니다. 자원을 읽지만 기록하지는 않는 메소드는 일반적으로 이 이벤트를 트리거하지 않습니다.

자원 변경 이벤트

자원 변경 이벤트는 작업공간에서 발생한 변경 세부사항(또는 변경사항 세트)을 설명합니다. 이벤트에는 변경사항의 최종 결과를 설명하는 자원 델타가 포함되어 있습니다. 예를 들어, 변경사항을 일괄처리하는 동안 자원을 추가했다가 나중에 삭제하면 자원이 델타에 표시되지 않습니다.

자원 델타는 작업공간 루트에 정착된 트리로 구성됩니다. 자원 델타 트리는 다음 유형의 변경사항을 설명합니다.

자원 델타 트리를 순회하기 위해 IResourceDeltaVisitor 인터페이스를 구현하거나 IResource.getAffectedChildren을 사용하여 명시적으로 트리를 순회할 수 있습니다. 자원 델타 방문자는 트리에 각 변경사항을 열거할 때 자원 델타에 의해 호출되는 visit 메소드를 구현합니다.

참고:  자원 세션 특성 또는 자원 지속적 특성에 대한 변경사항은 자원 델타에서 식별되지 않습니다.

자원 변경 이벤트는 작업공간에 변경사항(또는 일괄처리된 변경사항 세트)이 작성될 때마다 전송됩니다. 또한 자원 변경 이벤트는 특정 작업공간 조작을 위해 전송됩니다. 다음 테이블은 자원 변경 이벤트 유형과 자원 변경 이벤트가 보고되는 시기를 요약한 것입니다.

이벤트 유형

설명

PRE_CLOSE

리스너에게 프로젝트가 처리완료될 것임을 알립니다. 이 이벤트를 사용하여 프로젝트가 처리완료되기 전에 프로젝트의 내부 메모리 표시(예: 세션 특성)에서 필요한 정보를 추출하여 저장합니다 (프로젝트가 처리완료되면, 내부 메모리 표시가 처리됨). 이 이벤트 동안 작업공간이 잠깁니다. 자원을 갱신할 수 없습니다. 이 이벤트에는 처리완료 중인 프로젝트가 포함되어 있습니다.

PRE_DELETE

리스너에게 프로젝트가 삭제될 것임을 알립니다. 이 이벤트를 사용하여 정리 조작(예: 플러그인의 디렉토리에서 프로젝트와 관련된 저장된 상태 제거)을 수행할 수 있습니다.  이 이벤트 동안 작업공간이 잠깁니다. 자원을 갱신할 수 없습니다. 이 이벤트에는 삭제 중인 프로젝트가 포함되어 있습니다.

PRE_AUTOBUILD

자동 빌드가 발생하기 전에 리스너에게 알립니다.  이 이벤트는 자동 빌드가 실제 활성화되었는지에 관계 없이 플랫폼에서 자동 빌드의 발생 요구를 감지하면 브로드캐스트됩니다.  작업공간은 이 이벤트 동안 잠기지 않습니다. 자원을 갱신할 수 있습니다. 이 이벤트에는 마지막 POST_CHANGE 이벤트가 보고된 이후로 발생한 변경사항을 설명하는 자원 델타가 포함되어 있습니다.

POST_AUTOBUILD

자동 빌드가 발생한 후에 리스너에게 알립니다. 이 이벤트는 자동 빌드의 실제 사용 여부에 관계 없이 플랫폼에서 자동 빌드가 수행되고 나면 브로드캐스트됩니다. 작업공간은 이 이벤트 동안 잠기지 않습니다. 자원을 갱신할 수 있습니다. 이 이벤트에는 마지막 POST_CHANGE 이벤트가 보고된 이후로 발생한 변경사항을 설명하는 자원 델타가 포함되어 있습니다.

POST_CHANGE

마지막 POST_CHANGE 이벤트가 보고된 이후로 작업공간에 발생한 변경사항 세트를 설명합니다. 자원 변경 API가 개별적으로 사용되거나 일괄처리된 작업공간 변경사항 세트에서 사용된 후에 트리거됩니다. PRE_AUTOBUILD 또는 POST_AUTOBUILD 알림이 완료된 이후에도 트리거됩니다. 이 이벤트에는 마지막 POST_CHANGE 이벤트 이후의 최종 변경사항을 설명하는 자원 델타가 포함되어 있습니다.  이 이벤트 동안 작업공간이 잠깁니다. 자원을 갱신할 수 없습니다.

자원 변경 리스너 구현

다음 예는 콘솔 기반의 자원 변경 리스너를 구현합니다. 자원 변경 리스너는 특정 이벤트 유형에 등록되며, 이 이벤트에 대한 정보가 콘솔에 인쇄됩니다.

   IResourceChangeListener listener = new MyResourceChangeReporter();
ResourcesPlugin.getWorkspace().addResourceChangeListener(listener,
      IResourceChangeEvent.PRE_CLOSE
      | IResourceChangeEvent.PRE_DELETE
      | IResourceChangeEvent.PRE_AUTO_BUILD
      | IResourceChangeEvent.POST_AUTO_BUILD
      | IResourceChangeEvent.POST_CHANGE);

리스너는 각 이벤트 유형을 확인하여 변경된 자원 및 발생한 변경 유형에 대한 정보를 보고합니다.  이 예가 모든 자원 이벤트 유형을 처리하는 일반 리스너를 표시하도록 설계되었지만 일반적인 리스너는 하나의 이벤트 유형에만 등록됩니다.

POST_CHANGE 에 대한 구현은 자원 델타의 변경사항을 방문하는 데 사용할 수 있는 또다른 자원을 사용합니다.

      import org.eclipse.resources.*;
   import org.eclipse.runtime.*;

   public class MyResourceChangeReporter implements IResourceChangeListener {
      public void resourceChanged(IResourceChangeEvent event) {
         IResource res = event.getResource();
         switch (event.getType()) {
            case IResourceChangeEvent.PRE_CLOSE:
               System.out.print("Project ");
               System.out.print(res.getFullPath());
               System.out.println(" is about to close.");
      break;
            case IResourceChangeEvent.PRE_DELETE:
               System.out.print("Project ");
               System.out.print(res.getFullPath());
               System.out.println(" is about to be deleted.");
      break;
            case IResourceChangeEvent.POST_CHANGE:
               System.out.println("Resources have changed.");
               event.getDelta().accept(new DeltaPrinter());
      break;
            case IResourceChangeEvent.PRE_AUTO_BUILD:
               System.out.println("Auto build about to run.");
               event.getDelta().accept(new DeltaPrinter());
      break;
            case IResourceChangeEvent.POST_AUTO_BUILD:
               System.out.println("Auto build complete.");
               event.getDelta().accept(new DeltaPrinter());
      break;
         }
      }
   }

DeltaPrinter 클래스는 자원 델타를 심의하기 위해 IResourceDeltaVisitor 인터페이스를 구현합니다. visit() 메소드가 자원 델타의 각 자원 변경사항에 대해 호출됩니다. 방문자는 리턴값을 사용하여 하위 자원의 델타를 방문해야 하는지 여부를 표시합니다.

      class DeltaPrinter implements IResourceDeltaVisitor {
      public boolean visit(IResourceDelta delta) {
         IResource res = delta.getResource();
         switch (delta.getKind()) {
            case IResourceDelta.ADDED:
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
               System.out.println(" was added.");
      break;
            case IResourceDelta.REMOVED"
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
               System.out.println(" was removed.");
      break;
case IResourceDelta.CHANGED:
      System.out.print("Resource ");
               System.out.print(res.getFullPath());
      System.out.println(" has changed.");
      break;
         }
         return true; // visit the children
      }
   }

제공된 자원 델타에서 자세한 정보를 얻을 수 있습니다. 다음 스니펫은 자원 변경사항을 자세히 설명하기 위해 IResourceDelta.CHANGED 사례를 구현할 수 있는 방법을 표시합니다.

   ...
case IResourceDelta.CHANGED:
      System.out.print("Resource ");
      System.out.print(delta.getFullPath());
      System.out.println(" has changed.");
      int flags = delta.getFlags();
      if ((flags & IResourceDelta.CONTENT) != 0) {
            System.out.println("--> Content Change");
      }
      if ((flags & IResourceDelta.REPLACED) != 0) {
            System.out.println("--> Content Replaced");
      }
      if ((flags & IResourceDelta.MARKERS) != 0) {
            System.out.println("--> Marker Change");
            IMarkerDelta[] markers = delta.getMarkerDeltas();
            // if interested in markers, check these deltas
      }
      break;
   ...

자원 델타, 방문자, 마커 델타에 대한 자세한 설명은 IResourceDelta, IResourceDeltaVisitorIMarkerDelta에 대한 API 스펙을 참조하십시오.

참고:  자원 변경 리스너는 플러그인 활성화 동안 자원에 발생하는 변경사항을 추적하는 데 유용합니다. 플러그인이 시작 코드 동안 자원 변경 리스너를 등록하면, 플러그인이 활성화되기 전에 다수의 자원 변경 이벤트가 트리거되었을 수 있습니다. 플러그인에 의해 수신된 첫 번째 자원 변경 이벤트에 포함된 자원 델타에는 플러그인이 마지막으로 활성화된 이후의 모든 변경사항이 포함되지 않습니다. 플러그인 활성화 간에 작성된 변경사항을 추적해야 하는 경우, 작업공간 저장을 위해 제공된 지원을 사용해야 합니다. 이에 대한 설명은 작업공간 저장 참여를 참조하십시오.
참고:  배경 스레드에서 발생하는 일부 자원 변경 이벤트는 처리 중에 트리거됩니다. 자원 변경 리스너는 스레드 안전식(thread-safe)이어야 합니다. UI가 있는 스레드 안전에 대한 설명은 스레딩 문제를 참조하십시오.