동기화 API를 이해하는 가장 좋은 방법은 실제로 작동하는 단순 예제를 작성하는 것입니다. 이 예제에서는 작업공간의 모든 파일에 대한 최신 로컬 히스토리 상태를 표시할 페이지를 동기화 보기에 작성합니다. 작업공간을 변경할 때 로컬 히스토리 동기화가 자동으로 갱신되므로, 비교 편집기를 열어 찾아보고 병합한 후 변경할 수 있습니다. 또한 로컬 히스토리 요소의 최신 시간 소인을 표시할 사용자 정의 데코레이터 및 작업공간 파일을 마지막으로 저장된 로컬 히스토리 상태로 되돌릴 조치를 추가하게 됩니다. 이것은 사용 가능한 자원 변형에 대한 저장이 이미 있고 이 저장을 관리할 필요가 없기 때문에 매우 유용한 예제입니다.
이 예제의 나머지에서는 실행 중인 예제를
이용합니다. 일부를 제외한 대다수의 소스 코드가
이 페이지에 포함됩니다. 전체 소스 코드는 org.eclipse.team.examples.filesystem
플러그인의 로컬 히스토리 패키지에서 찾을 수
있습니다. CVS 저장소에서 프로젝트를 체크아웃하여 이 학습서를 읽는 동안
참조로 사용할 수 있습니다. 면책사항: 예제 플러그인의
소스 코드는 시간이 흐르면서 변경될 수 있습니다. 이 예제에서 사용되는
내용과 일치하는 사본을 가져올 경우 3.0 버전 태그(대부분의 경우 R3_0) 또는
2004년 6월 28일의 날짜 태그를 사용하여 프로젝트를 체크아웃할 수 있습니다.
이 스크린 샷은 동기화 보기의 로컬 히스토리 동기화를
표시합니다. 이를 통해 로컬 자원과 히스토리의 최신 상태 간의 변경사항을
찾아볼 수 있습니다. 여기에는 로컬 히스토리의 컨텐츠로 파일을 되돌리는
사용자 정의 조치 및 로컬 히스토리 입력과 연관된 시간 소인을 표시하는 사용자 정의
데코레이터가 있습니다. 또한 문제점 어노테이션, 압축된 폴더 레이아웃 및
경로 탐색 단추를 제공하는 표준 동기화 보기 프리젠테이션도
사용됩니다.
첫 번째 단계는 로컬 히스토리의 요소를 표시할 변형을 정의하는 것입니다. 이를 수행하면 동기화 API가 로컬 히스토리의 컨텐츠에 액세스할 수 있으므로, 이를 현재 컨텐츠와 비교하여 사용자에게 표시할 수 있습니다.
public class LocalHistoryVariant implements IResourceVariant {
private final IFileState state;
public LocalHistoryVariant(IFileState state) {
this.state = state;
}
public String getName() {
return state.getName();
}
public boolean isContainer() {
return false;
}
public IStorage getStorage(IProgressMonitor monitor) throws TeamException {
return state;
}
public String getContentIdentifier() {
return Long.toString(state.getModificationTime());
}
public byte[] asBytes() {
return null;
}
}
IFileState 인터페이스가 이미 로컬 히스토리의 파일 컨텐츠(예: IStorage
인터페이스 구현)에 대한 액세스를 제공하므로 이것은 쉬운 경우였습니다.
일반적으로 변형을 작성할 때 컨텐츠에 액세스하는 방법, 이 변형을
식별하기 위해 사용자에게 표시할 컨텐츠 ID 및 이름을 제공해야
합니다. asBytes() 메소드는 세션 간 변형을 유지할 경우에만
필요합니다.
다음으로, SyncInfo 계산으로 로컬 자원을 해당 변형과 비교할 수 있도록 하는
변형 비교기를 작성하기로 합니다. 로컬 히스토리 상태의 컨텐츠가
파일의 현재 컨텐츠와 다름을 로컬 히스토리 상태의 존재로 알 수 있기 때문에
이 역시 쉽습니다. 이것은 파일이 변경되지 않은 경우 로컬 히스토리 상태를
작성하지 않음을 로컬 히스토리의 스펙으로 알 수 있기 때문입니다.
public class LocalHistoryVariantComparator implements IResourceVariantComparator {
public boolean compare(IResource local, IResourceVariant remote) {
return false;
}
public boolean compare(IResourceVariant base, IResourceVariant remote) {
return false;
}
public boolean isThreeWay() {
return false;
}
}
로컬과 다르다는 것을 로컬 히스토리 상태의 존재로 알 수 있기 때문에 파일을 해당 로컬 히스토리 상태와 비교할 때 false를 쉽게 리턴할 수 있습니다. 또한 로컬 히스토리와의 동기화는 기본 자원에 대한 액세스가 없기 때문에 2방향뿐이므로, 두 자원 변형을 비교하는 메소드는 사용되지 않습니다.
변형이 없을 경우(예: 널(null)) 동기화 계산이 비교기의 비교 메소드를 호출하지 않습니다. 두 요소가 모두 존재할 경우에만 호출됩니다. 예제에서 이는 로컬 히스토리가 없는 파일의 경우 및 모든 폴더의 경우(로컬 히스토리가 전혀 없는) 모두에서 발생합니다. 이를 처리하려면 이러한 경우의 계산된 동기화 상태를 수정하기 위해 SyncInfo의 고유 서브클래스를 정의해야 합니다.
public class LocalHistorySyncInfo extends SyncInfo {
public LocalHistorySyncInfo(IResource local, IResourceVariant remote, IResourceVariantComparator comparator) {
super(local, null, remote, comparator);
}
protected int calculateKind() throws TeamException {
if (getRemote() == null)
return IN_SYNC;
else
return super.calculateKind();
}
}
널(2방향 비교만 사용 중이므로)인 기본을 항상 제공하기 위해 생성자를 대체했으며, 원격이 없을 경우(로컬 히스토리에 로컬 파일 및 파일 상태가 있는 경우에만 고려하므로) IN_SYNC를 리턴하는 동기화 유형 계산을 수정했습니다.
이제 로컬 히스토리의 자원 변형에 대한 액세스를 제공할 가입자를 작성하기로 합니다. 작업공간의 모든 파일에 로컬 히스토리를 저장할 수 있으므로 로컬 히스토리 가입자는 모든 자원을 관리하며, 루트 세트가 작업공간의 모든 프로젝트가 됩니다. 또한 로컬 파일의 컨텐츠가 변경될 때에만 로컬 히스토리가 변경되므로 가입자를 새로 고치는 기능을 제공할 필요가 없습니다. 따라서 자원 델타가 발생할 때마다 상태를 갱신할 수 있습니다. 이제 로컬 히스토리 가입자에는 두 관련 메소드(SyncInfo 얻기 및 작업공간 순회)만 남아 있습니다.
public SyncInfo getSyncInfo(IResource resource) throws TeamException {
try {
IResourceVariant variant = null;
if(resource.getType() == IResource.FILE) {
IFile file = (IFile)resource;
IFileState[] states = file.getHistory(null);
if(states.length > 0) {
// last state only
variant = new LocalHistoryVariant(states[0]);
}
}
SyncInfo info = new LocalHistorySyncInfo(resource, variant, comparator);
info.init();
return info;
} catch (CoreException e) {
throw TeamException.asTeamException(e);
}
}
가입자는 로컬 히스토리의 최신 파일 상태가 들어 있는 새 SyncInfo 인스턴스를 리턴합니다. SyncInfo는 원격 요소의 로컬 히스토리 변형과 함께 작성됩니다. 로컬 히스토리가 없는 프로젝트, 폴더 및 파일의 경우에는 원격 자원 변형이 제공되지 않는데, 이것은 LocalHistorySyncInfo의 calculateKind 메소드로 인해 자원이 동기화 중인 것으로 간주될 수 있기 때문입니다.
로컬 히스토리 가입자의 나머지 코드는 다음과 같이 members 메소드에 대한 구현입니다.
public IResource[] members(IResource resource) throws TeamException {
try {
if(resource.getType() == IResource.FILE)
return new IResource[0];
IContainer container = (IContainer)resource;
List existingChildren = new ArrayList(Arrays.asList(container.members()));
existingChildren.addAll(
Arrays.asList(container.findDeletedMembersWithHistory(IResource.DEPTH_INFINITE, null)));
return (IResource[]) existingChildren.toArray(new IResource[existingChildren.size()]);
} catch (CoreException e) {
throw TeamException.asTeamException(e);
}
}
이 메소드에 대한 세부사항은 삭제된 자원에 로컬 히스토리가 있을 경우 기존 하위가 아닌 하위를 리턴한다는 것입니다. 이로 인해 가입자는 로컬 히스토리에만 존재하고 작업공간에는 더 이상 존재하지 않는 요소의 SyncInfo를 리턴할 수 있습니다.
지금까지 로컬 히스토리에 있는 요소의 SyncInfo에 대한 액세스를 제공하는 클래스를 작성했습니다. 다음에는 동기화 보기의 페이지에 로컬 히스토리에 있는 모든 요소의 마지막 히스토리 상태를 표시할 수 있게 하는 UI 요소를 작성합니다. 가입자가 있기 때문에 이를 동기화 보기에 추가하는 것은 쉽습니다. 다음과 같이 동기화 참여자 확장점을 추가하여 시작하기로 합니다.
<extension point="org.eclipse.team.ui.synchronizeParticipants">
<participant
persistent="false"
icon="synced.png"
class="org.eclipse.team.synchronize.example.LocalHistoryParticipant"
name="Latest From Local History"
id="org.eclipse.team.synchronize.example"/>
</extension>
다음으로는 LocalHistoryParticipant를 구현해야 합니다. 이것은 가입자로부터 SyncInfo를 수집하고 작업공간이 변경될 때 동기화 상태를 갱신하기 위한 모든 기본 작동을 제공할 SubscriberParticipant를 서브클래스로 분류합니다. 또한 작업공간 자원을 로컬 히스토리의 최신 상태로 되돌리는 조치를 추가합니다.
먼저 사용자 정의 조치가 참여자에 추가되는 방법을 살펴보겠습니다.
public static final String CONTEXT_MENU_CONTRIBUTION_GROUP = "context_group_1"; //$NON-NLS-1$
private class LocalHistoryActionContribution extends SynchronizePageActionGroup {
public void initialize(ISynchronizePageConfiguration configuration) {
super.initialize(configuration);
appendToGroup(
ISynchronizePageConfiguration.P_CONTEXT_MENU, CONTEXT_MENU_CONTRIBUTION_GROUP,
new SynchronizeModelAction("Revert to latest in local history", configuration) { //$NON-NLS-1$
protected SynchronizeModelOperation getSubscriberOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements) {
return new RevertAllOperation(configuration, elements);
}
});
}
}
여기에서는 특정 SynchronizeMoidelAction 및 조작을 추가합니다. 여기에서 자유롭게 가져올 수 있는 작동은 배경에서 실행을 하고 작업 중인 노드의 사용 중 상태를 표시하는 기능입니다. 이 조치는 작업공간의 모든 자원을 로컬 히스토리의 최신 상태로 되돌립니다. 조치 지시문을 참여자 구성에 추가하여 이 조치를 추가합니다. 이 구성은 실제 동기화 UI를 표시할 참여자 페이지를 빌드하는 데 사용되는 특성의 설명에 사용합니다.
참여자는 로컬 히스토리 조치 그룹을 컨텍스트 메뉴에 추가하기 위해 다음과 같이 구성을 초기화합니다.
protected void initializeConfiguration(ISynchronizePageConfiguration configuration) {
super.initializeConfiguration(configuration);
configuration.addMenuGroup(
ISynchronizePageConfiguration.P_CONTEXT_MENU,
CONTEXT_MENU_CONTRIBUTION_GROUP);
configuration.addActionContribution(new LocalHistoryActionContribution()); configuration.addLabelDecorator(new LocalHistoryDecorator());
}
이제 사용자 정의 데코레이션을 제공하는 방법을 살펴 보기로 합니다. 위 메소드의 마지막 행은 다음 데코레이터를 페이지 구성과 함께 등록합니다.
public class LocalHistoryDecorator extends LabelProvider implements ILabelDecorator {
public String decorateText(String text, Object element) {
if(element instanceof ISynchronizeModelElement) {
ISynchronizeModelElement node = (ISynchronizeModelElement)element;
if(node instanceof IAdaptable) {
SyncInfo info = (SyncInfo)((IAdaptable)node).getAdapter(SyncInfo.class);
if(info != null) {
LocalHistoryVariant state = (LocalHistoryVariant)info.getRemote();
return text+ " ("+ state.getContentIdentifier() + ")";
}
}
}
return text;
}
public Image decorateImage(Image image, Object element) {
return null;
}
}
데코레이터는 동기화 보기에 표시되고 로컬 히스토리 자원 변형의 컨텐츠 ID를 해당 보기에 표시되는 텍스트 레이블에 추가하는 모델 요소에서 자원의 압축을 풉니다.
마지막이자 최종 단계는 로컬 히스토리 참여자를 작성할 마법사를 제공하는 것입니다. 팀 동기화 Perspective는 사용자가 신속히 동기화를 작성할 수 있게 하는 글로벌 동기화 조치를 정의합니다. 또한 동기화 보기 도구 모음에서 동기화를 작성하는 기능을 사용할 수 있습니다. 시작하려면 다음과 같이 synchronizeWizards 확장점을 작성하십시오.
<extension
point="org.eclipse.team.ui.synchronizeWizards">
<wizard
class="org.eclipse.team.synchronize.example.LocalHistorySynchronizeWizard"
icon="synced.png"
description="Creates a synchronization against the latest local history state of all resources in the workspace"
name="Latest From Local History Synchronize"
id="ExampleSynchronizeSupport.wizard1"/>
</extension>
이렇게 하면 마법사가 목록에 추가되며, 마법사 finish() 메소드에서 간단히 참여자를 작성하여 동기화 관리자에 추가합니다.
LocalHistoryPartipant participant = new LocalHistoryPartipant();
ISynchronizeManager manager = TeamUI.getSynchronizeManager();
manager.addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
ISynchronizeView view = manager.showSynchronizeViewInActivePage();
view.display(participant);
이것은 동기화 API 사용에 대한 단순 예제이며, 예제를 이해하기 더욱 쉽게
하기 위해 세부사항 중 일부에는 주석을 첨부했습니다.
반응이 빠르고 정확한 동기화 지원을 작성하는 것은 중요한 일이며,
가장 어려운 부분은 동기화 정보 및 동기화 상태 변경의 알림을 관리하는
것입니다. SubscriberParticipants와 연관된 사용자 인터페이스가
적절할 경우 사용자 인터페이스는 가입자 구현이 완료하면 쉬운
부분입니다. 추가 예제는 org.eclipse.team.example.filesystem
플러그인을 참조하여 가입자 및 ISynchronizeParticipant의 작업공간에서 서브클래스를 찾아보십시오.
다음 섹션에서는 Workbench 세션 간 동기화 상태를 캐시하는 방법을 포함하여
처음부터 가입자를 작성하는 데 도움이 될 수 있는 인터페이스 및 일부 클래스를
설명합니다.