Связанные ресурсы

Ранее при обсуждении ресурсов и файловой системы (Хранение ресурсов на диске) предполагалось, что все ресурсы проекта находятся в одном месте файловой системы.  В большинстве случаев это верно.  Однако концепция связанных ресурсов рабочей среды позволяет хранить файлы и папки проекта не в том же месте файловой системы, в котором находится проект. 

Для связанных ресурсов проект должен служить родительским ресурсом. Виртуально связанные ресурсы могут располагаться где угодно. Они могут находиться за пределами каталога проекта или даже в другом проекте. На расположение связанных ресурсов накладываются только несколько ограничений. Проверка допустимости заданного расположения для создания связанного ресурса осуществляется с помощью метода IWorkspace.validateLinkLocation.

Связанные ресурсы создаются с помощью метода IFolder.createLink или IFile.createLink. Для программного определения, является ли данный ресурс связанным, можно воспользоваться методом IResource.isLinked. Обратите внимание, что этот метод возвращает true только для самих связанных ресурсов, не включая их дочерние ресурсы.

Помимо особых методов для создания связанных ресурсов и проверки ресурса на связанность, вы можете управлять связанными ресурсами через обычный API рабочей области. В большинстве случаев связанные ресурсы работают точно так же, как и любые другие ресурсы рабочей области. Однако на удаление, перемещение и копирование связанных ресурсов накладываются некоторые ограничения.  Сведения по конкретным ресурсам и их ограничениям можно найти в описании класса IResource и его производных классов.

Переменные пути

При задании расположения связанных ресурсов можно пользоваться переменными пути.  Переменная пути - это просто связь (строка -> IPath), задающая ярлык для конкретного места файловой системы.  С помощью переменных управлять связанными ресурсами проще: уменьшается количество мест, где используются абсолютные жестко закодированные пути файловой системы.

Переменные пути рационализируют управление связанными ресурсами для пользователей:

Последний пункт этого списка требует небольшого объяснения. Когда пользователь создает в проекте связанный ресурс, его описание добавляется в файл описания проекта (".project") в месте расположения проекта. С помощью переменной пути пользователи могут совместно работать с проектом (путем копирования содержимого проекта или через хранилище) и переопределяют переменную так, чтобы она соответствовала каждой рабочей станции.  Например, один пользователь может хранить внешние ресурсы в каталоге c:\temp одной системы, другой пользователь, работающий под Unix, - в каталоге /home/username/tmp.  Определение переменной пути на каждой рабочей станции (TEMP=c:\temp и TEMP=/home/userb/tmp) позволяет обойти это различие и работать с проектом, содержащим связанные ресурсы, как обычно.

Для определения API для создания, управления и обработки переменных пути служит класс IPathVariableManager. В нем предусмотрены методы для проверки имен и значений переменных перед их созданием и методы для установки получателя запросов, оповещающего о переопределении переменной пути. Все экземпляры этого класса можно получить с помощью IWorkspace.getPathVariableManager. Дополнительно посмотрите примеры кода в конце этого раздела.

Для нахождения необработанного расположения связанного ресурса служит метод IResource.getRawLocation. То есть, с его помощью можно получить фактическое имя переменной пути вместо обработки ее значения.  Если расположение ресурса не определено с помощью переменной пути, то метод getRawLocation работает как метод getLocation.

Неработающие ссылки

Клиенты, управляющие ресурсами программно, должны помнить о возможности неработающих ссылок. Такие ссылки могут возникнуть либо в результате отсутствия связанного ресурса в указанном месте, либо если они указывают на неопределенную переменную пути. При использовании протокола IResource возможны следующие случаи:

Совместимость с установленными модулями

В некоторых модулях обработка связанных ресурсов не поддерживается, поэтому есть ряд механизмов для их отключения. Если для вашего модуля строго необходимо, чтобы все содержимое проекта находилось в каталоге проекта по умолчанию, то с помощью этих приемов можно запретить пользователям создание связанных ресурсов в нежелательных местах.

Первый прием называется запрет классификатора проекта. Если вы определяете собственный классификатор проекта, то в нем можно указать, что этот тип проекта не поддерживает связанные ресурсы. Ниже приведен пример определения классификатора, в котором используется этот прием:

<extension
	id="myNature"
	name="My Nature"
	point="org.eclipse.core.resources.natures">
	<runtime>
		<run class="com.xyz.MyNature"/>
	</runtime>
	<options allowLinking="false"/>
</extension>

Второй прием запрета создания связанных ресурсов - перехватчик модуля совместной работы. Если у вас собственная реализация хранилища, то в ней можно воспользоваться точкой расширения org.eclipse.core.resources.teamHook для предотвращения создания связанных ресурсов в проектах, работающих с вашим хранилищем. По умолчанию модули типов хранилищ не разрешают создавать связанные ресурсы в проектах, подключенных к хранилищу. 

Если поддержка хранилища реализована более старым модулем, не учитывающим связанные ресурсы, то в таких проектах создать связанные ресурсы невозможно. 

И наконец, есть атрибут, с помощью которого можно отключить связанные ресурсы для всей рабочей области. Два предыдущих способа работали на уровне проекта, а этот атрибут действует на все проекты рабочей области. Программно настроить этот атрибут можно с помощью ResourcesPlugin.PREF_DISABLE_LINKING. Обратите внимание, что даже если атрибут установлен, пользователь либо модуль может его переопределить и выключить.

Связанные ресурсы в коде

Рассмотрим несколько примеров кода для работы со связанными ресурсами. Начнем с определения переменной пути:

   IWorkspace workspace = ResourcesPlugin.getWorkspace();
   IPathVariableManager pathMan = workspace.getPathVariableManager();
   String name = "TEMP";
   IPath value = new Path("c:\\temp");
   if (pathMan.validateName(name).isOK() && pathMan.validateValue(value).isOK()) {
      pathMan.setValue(name, value);
   } else {
      // недопустимое имя или значение, генерируется исключительная ситуация или предупреждение    }

Создаем связанный ресурс, относящийся к определенной переменной пути:

   IProject project = workspace.getProject("Project");// считаем, что он существует
   IFolder link = project.getFolder("Link");
   IPath location = new Path("TEMP/folder");
   if (workspace.validateLinkLocation(location).isOK()) {
      link.createLink(location, IResource.NONE, null);
   } else {
      // недопустимое расположение, генерируется исключительная ситуация или предупреждение
   }

Это именно то, что нам нужно! У нас в рабочей области есть связанная папка с именем "Link" которая находится в "c:\temp\folder".

Напоследок - несколько фрагментов кода для этого связанного ресурса, иллюстрирующие поведение других методов работы со связанными ресурсами:

   link.getFullPath() ==> "/Project/Link"
   link.getLocation() ==> "c:\temp\folder"
   link.getRawLocation() ==> "TEMP/folder"
   link.isLinked() ==> "true"
   
   IFile child = link.getFile("abc.txt");
   child.create(...);
   child.getFullPath() ==> "/Project/Link/abc.txt"
   child.getLocation() ==> "c:\temp\folder\abc.txt"
   child.getRawLocation() ==> "c:\temp\folder\abc.txt"
   child.isLinked() ==> "false"