작업공간 저장 처리는 Workbench가 사용자에 의해 종료되거나 플랫폼에 의해 주기적으로 종료될 때 트리거됩니다. 플러그인은 작업공간의 나머지 지속적 데이터가 저장될 때마다 중요한 플러그인 데이터가 디스크에 저장될 수 있도록 작업공간 저장 프로세스에 참여할 수 있습니다.
작업공간 저장 프로세스를 사용하여 플러그인 활성화 간에 발생하는 변경사항을 추적할 수도 있습니다.
작업공간 저장에 참여하려면 작업공간에 저장 참여자를 추가해야 합니다. 일반적으로 이 작업은 플러그인의 startup 메소드 동안 수행됩니다. 또한 플러그인이 마지막으로 종료되었을 때 여기서 사용자가 저장한 상태를 읽습니다.
저장 프로세스를 설명하는 간단한 플러그인을 살펴보겠습니다.
package com.example.saveparticipant; import org.eclipse.core.runtime.*; import org.eclipse.core.resources.*; import java.io.File; import java.util.*; public class MyPlugin extends Plugin { private static MyPlugin plugin; public MyPlugin(IPluginDescriptor descriptor) { super(descriptor); plugin = this; } public static MyPlugin getDefault() { return plugin; } protected void readStateFrom(File target) { } public void startup() throws CoreException { super.startup(); ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(this, saveParticipant); if (lastState == null) return; IPath location = lastState.lookup(new Path("save")); if (location == null) return; // the plugin instance should read any important state from the file. File f = getStateLocation().append(location).toFile(); readStateFrom(f); } protected void writeImportantState(File target) { } }
ISaveparticipant는 작업공간 저장 참여자 프로토콜을 정의합니다. 이 인터페이스에 대한 구현은 서로 다른 저장 프로세스 단계에 대한 작동을 제공합니다. 단계를 살펴 보고 WorkspaceSaveParticipant 클래스가 각 단계를 구현하는 방법을 살펴 보도록 합시다.
public void prepareToSave(ISaveContext context) throws CoreException { }
public void saving(ISaveContext context) throws CoreException { switch (context.getKind()) { case ISaveContext.FULL_SAVE: MyPlugin myPluginInstance = MyPlugin.getDefault(); // save the plug-in state int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // if we fail to write, an exception is thrown and we do not update the path myPluginInstance.writeImportantState(f); context.map(new Path("save"), new Path(saveFileName)); context.needSaveNumber(); break; case ISaveContext.PROJECT_SAVE: // get the project related to this save operation IProject project = context.getProject(); // save its information, if necessary break; case ISaveContext.SNAPSHOT: // This operation needs to be really fast because // snapshots can be requested frequently by the // workspace. break; } }
ISaveContext는 저장 조작에 대한 정보를 설명합니다. 저장 조작에는, FULL_SAVE, SNAPSHOT 및 PROJECT_SAVE의 세 가지가 있습니다. 저장 참여자는 수신한 저장 이벤트 유형에 대해 적절한 처리를 수행해야 합니다. 예를 들어, 스냅샷 이벤트가 자주 발생할 수 있는데 스냅샷 이벤트는 플러그인이 중요한 상태를 저장할 수 있도록 계획됩니다. 고장이 발생할 경우 다시 계산할 수 있는 상태를 저장하는 데 오랜 시간이 소요되면 플랫폼이 느려집니다.
저장 번호는 순차 번호(save-1, save-2 등)를 사용하여 이름 지정된 데이터 저장 파일을 작성하는 데 사용됩니다. 각 파일은 저장 번호와 관계 없이 논리 파일 이름(save)에 맵핑됩니다.플러그인 데이터는 해당 파일에 기록되기 때문에 마지막 저장 조작에 사용된 특정 저장 번호를 모를 경우에도 나중에 검색할 수 있습니다. 플러그인의 시작 코드에서 살펴 본 이 기술을 상기하십시오.
IPath location = lastState.lookup(new Path("save"));데이터를 저장하고 파일 이름을 맵핑하였다면, 작업공간 저장에 참여했으며 저장 활동에 번호를 지정하려 함을 표시하기 위해 needSaveNumber를 호출합니다. 저장 번호를 사용하여 위의 데이터 파일을 작성할 수 있습니다.
public void doneSaving(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // delete the old saved state since it is not necessary anymore int previousSaveNumber = context.getPreviousSaveNumber(); String oldFileName = "save-" + Integer.toString(previousSaveNumber); File f = myPluginInstance.getStateLocation().append(oldFileName).toFile(); f.delete(); }
여기서, 이전 저장 조작의 저장 정보를 정리합니다. getPreviousSaveNumber를 사용하여 지금 완료한 저장 조작이 아닌 이전 저장 조작에서 지정한 저장 번호를 가져옵니다. 이 번호를 사용하여 삭제해야 하는 파일 이름을 구성합니다. 현재 저장 파일 번호를 이미 맵핑했으므로 저장 상태의 논리 파일 맵을 사용하지 않습니다.
public void rollback(ISaveContext context) { MyPlugin myPluginInstance = MyPlugin.getDefault(); // since the save operation has failed, delete the saved state we have just written int saveNumber = context.getSaveNumber(); String saveFileName = "save-" + Integer.toString(saveNumber); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); f.delete(); }
여기서, 방금 저장한 상태를 삭제합니다. 지금 저장한 파일 이름을 구성하기 위해 현재 저장 번호를 사용합니다. 이 파일 이름을 ISaveContext에 맵핑했다는 사실은 중요하지 않습니다. 플랫폼은 저장 조작이 실패하면 컨텍스트를 버립니다.
플러그인이 저장 라이프 사이클 동안 예외를 처리하면, 현재 저장 조작에서 제외되고 나머지 라이프 사이클 메소드를 가져오지 않습니다. 예를 들어, saving 메소드 동안 실패하면 rollback 또는 doneSaving 메시지가 수신되지 않습니다.
작업공간에 저장 참여자를 추가할 때 ISavedState 오브젝트가 리턴되는데, 이 오브젝트는 마지막 저장 조작 동안 플러그인이 저장한 내용(또는 플러그인이 이전에 상태를 저장하지 않은 경우 널)을 설명합니다. 이 오브젝트를 사용하여 이전 저장 파일(저장 번호 및 파일 맵 사용)에서 정보에 액세스하거나 플러그인 활성화 간에 발생한 변경사항을 처리할 수 있습니다.
저장 번호에 따라 논리적으로 이름 지정된 파일 이름을 저장하기 위해 파일 맵이 사용된 경우, 이 동일한 맵을 사용하여 마지막으로 알려진 저장 상태에서 데이터를 검색할 수 있습니다.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { String saveFileName = lastState.lookup(new Path("save")).toString(); File f = myPluginInstance.getStateLocation().append(saveFileName).toFile(); // the plugin instance should read any important state from the file. myPluginInstance.readStateFrom(f); }
플러그인이 활성화되기 전에 작업공간에서 임의 수의 자원 변경 이벤트가 발생할 수 있습니다. 플러그인이 비활성화된 이후에 발생한 변경사항을 알려면 저장 메커니즘을 사용하면 됩니다(사실, 기타 데이터를 저장할 필요는 없음).
저장 참여자는 플랫폼이 참여자 대신 자원 델타를 유지하도록 요청해야 합니다. 이것은 저장 조작의 일부로 수행됩니다.
public void saving(ISaveContext context) throws CoreException { // no state to be saved by the plug-in, but request a // resource delta to be used on next activation. context.needDelta(); }
플러그인이 시작되는 동안 이전에 저장된 상태에 액세스할 수 있으며, 마지막 저장 이후로 발생한 모든 변경사항에 대해 변경 이벤트가 작성됩니다.
ISaveParticipant saveParticipant = new MyWorkspaceSaveParticipant(); ISavedState lastState = ResourcesPlugin.getWorkspace().addSaveParticipant(myPluginInstance, saveParticipant); if (lastState != null) { lastState.processResourceChangeEvents(new MyResourceChangeReporter()); }
제공된 클래스는 자원 변경사항 추적에 설명된 대로 IResourceChangeListener를 구현해야 합니다. 마지막 저장 이후의 변경사항은 POST_AUTO_BUILD 자원 변경 이벤트의 일부로 보고됩니다.
참고: 마커 변경사항은 ISavedState에 저장된 변경 이벤트에 보고되지 않습니다. 마지막 상태가 저장된 이후로 임의의 또는 모든 마커가 변경되었다고 가정해야 합니다.