Spec-Zone .ru
спецификации, руководства, описания, API
|
SPI JNDI обеспечивает средства, которыми разработчики могут записать различное именование и провайдеров службы каталогов и сделать их доступными так, чтобы соответствующие службы были доступны из приложений, которые используют API JNDI. Поставщик услуг является рядом модулей, которые вместе удовлетворяют запросы API JNDI. Кроме того, потому что JNDI позволяет использование имен, которые охватывают многократные пространства имен, одна реализация поставщика услуг, возможно, должна взаимодействовать с другим, чтобы завершить работу. SPI обеспечивает методы, которые позволяют различным реализациям провайдера сотрудничать, чтобы завершить клиент операции JNDI.
Этот документ описывает компоненты SPI и объясняет, как разработчики могут создать поставщиков услуг для JNDI. Предполагается, что читатель знаком с содержанием документа API JNDI.
Все разработчики поставщика услуг должны считать "раздел" Соображений Безопасности документа API JNDI. Это содержит важные проблемы, которые должны рассмотреть все разработчики, использующие JNDI, особенно те, которые пишут поставщиков услуг.
Есть несколько типов реализаций, которые находятся ниже API JNDI. Поставщик услуг содержит как минимум реализацию контекста. Реализация контекста реализует Context
взаимодействуйте через интерфейс или любой из его подынтерфейсов, такой как DirContext
, EventContext
, или LdapContext
. Сложность реализации зависит прежде всего от сложности базовой службы, и во вторую очередь на числе функций JNDI, которые поддерживает реализация. Глава 2 описывает детали создания реализации контекста.
К реализации контекста можно получить доступ по-разному. Наиболее распространенный способ состоит в том, чтобы получить доступ к этому от начального контекста. Глава 3 описывает два способа, которыми к реализации контекста можно получить доступ от начального контекста: через начальную фабрику контекста и фабрику контекста URL.
Архитектура JNDI определяет компоненты/реализации, которые могут использоваться, чтобы увеличить поведение реализаций контекста. Это позволяет пользователям и приложениям настраивать реализацию. Эти компоненты поддерживаются через фабрики. JNDI определяет три типа фабрик и обеспечивает методы SPI, которые используют их. Эти фабрики описываются в Главе 4.
SPI JNDI содержится в javax.naming.spi
пакет. Следующие разделы обеспечивают краткий обзор SPI. Для получения дополнительной информации на SPI, см. соответствующий javadoc.
Информация в этой графике доступна в документации API.
NamingManager
class содержит статические методы, которые выполняют связанные с провайдером операции. Например, это содержит методы, чтобы создать экземпляры использования объектов Reference
, получить экземпляр начального контекста, используя java.naming.factory.initial
свойство, и устанавливать ObjectFactoryBuilder
и InitialContextFactoryBuilder
. DirectoryManager
class обеспечивает подобные статические методы для DirContext
связанные операции.
InitialContextFactory
интерфейс для того, чтобы создать начальный экземпляр контекста. См. Раздел 3.1 для большего количества деталей.
InitialContextFactoryBuilder
интерфейс для того, чтобы создать InitialContextFactory
экземпляры. См. Раздел 3.3 для большего количества деталей.
ObjectFactory
интерфейс для того, чтобы поддерживать создание объектов, используя информацию, хранившую в пространстве имен. DirObjectFactory
подынтерфейс ObjectFactory
для использования реализациями контекста, которые реализуют DirContext
интерфейс. См. Раздел 4.1 для большего количества деталей.
ObjectFactoryBuilder
интерфейс для того, чтобы создать объектные фабрики. См. Раздел 4.1.4 для большего количества деталей.
StateFactory
интерфейс для того, чтобы поддерживать объекты преобразования в форматы storable, поддерживаемые именованием/службой каталогов. DirStateFactory
подынтерфейс StateFactory
для использования реализациями контекста, которые реализуют DirContext
интерфейс. DirStateFactory.Result
class для содержания пары java.lang.Object
и Attributes
это возвращается DirStateFactory.getStateToBind()
. См. Раздел 4.2 для большего количества деталей.
Resolver
интерфейс определяет метод для провайдеров, чтобы реализовать, который позволяет им участвовать в федерации для того, чтобы поддерживать расширенные интерфейсы к Context
. Переживите "Разрешение к Подынтерфейсам Контекста" на странице 10 для большего количества деталей.
ResolveResult
возвращаемое значение вызова Resolver.resolveToClass()
. Это содержит объект к который разрешение, за которым следуют, и остающееся имя все же, чтобы быть разрешенным.
Одна из основных задач в создании поставщика услуг состоит в том, чтобы определить class, который реализует Context
взаимодействуйте через интерфейс или любой из его подынтерфейсов. Этот class вызывают реализацией контекста. Следующие направляющие линии должны использоваться для того, чтобы разработать реализацию контекста.
Вообще, любой объект, который передают в качестве параметра к методам в Context
интерфейс (или подынтерфейсы) и NamingManager
/DirectoryManager
служебные методы принадлежат вызывающей стороне. Во многих случаях параметр в конечном счете достигает реализации контекста. Поскольку вызывающей стороне принадлежит объект, реализации контекста мешают изменить объект. Кроме того реализации контекста позволяют поддержать указатель на объект только для продолжительности работы а не вне. Если реализация контекста должна сохранить информацию, содержавшуюся в параметре вне продолжительности работы, это должно поддержать свою собственную копию.
В целях владения параметра работа на экземпляре контекста, как полагают, не завершилась, в то время как любые отсылки, сгенерированные той работой, все еще сопровождаются, или если работа возвращает a NamingEnumeration
, в то время как перечисление находится все еще в использовании.
Экземпляр контекста не должен быть повторно используемым. Два потока, которые должны получить доступ к тому же самому экземпляру контекста одновременно, должны синхронизироваться среди себя и обеспечить необходимую блокировку.
Однако, различные экземпляры контекста должны быть безопасными для параллельного многопоточного доступа. Таким образом, два потока каждая работа одновременно на их соответствующем экземпляре контекста не должны должны быть синхронизировать свой доступ. Например, даже при том, что два контекста могли бы совместно использовать те же самые ресурсы (такие как то же самое соединение), это должно быть возможно (и безопасно) для двух отдельных потоков, чтобы работать на каждом из тех контекстов без потоков, имеющих необходимость сделать любую явную синхронизацию.
В целях управления совместным выполнением работа на экземпляре контекста, как полагают, не завершилась, в то время как любые отсылки, сгенерированные той работой, все еще сопровождаются, или если работа возвращает a NamingEnumeration
, в то время как перечисление находится все еще в использовании.
Реализация контекста определяет реализации для каждого из методов в Context
взаимодействуйте через интерфейс или подынтерфейсы, которые поддерживает реализация.
Если метод не поддерживается, он должен бросить OperationNotSupportedException
.
Для методов в Context
взаимодействуйте через интерфейс или подынтерфейсы, которые принимают параметр имени (любой как a String
или a Name
), пустое название обозначает текущий контекст. Например, если пустое название предоставляется lookup()
, это означает возвращать новый экземпляр текущего контекста. Если пустое название предоставляется list()
, это означает перечислять имена в текущем контексте. Если пустое название предоставляется getAttributes()
, это означает получать атрибуты, связанные с этим контекстом.
Приложение A содержит реализацию контекста в качестве примера, которая реализует плоское, пространство имен в памяти.
JNDI поощряет провайдеров предоставлять реализации Context
и его подынтерфейсы, которые являются естественными и интуитивными для прикладного программиста Java. Например, когда поиск принтера называет в пространстве имен, естественно для программиста ожидать возвращать объект принтера, на котором можно работать.
Context ctx = new InitialContext(); Printer prt = (Printer)ctx.lookup(somePrinterName); prt.print(someStreamOfData);
Точно так же, храня объект приложения в базовую службу, это является самым переносимым и удобным, если приложение не должно знать о базовом представлении данных.
Однако, что связывается в базовом каталоге, или службы именования обычно не являются объектами в языке программирования Java, но просто информации о ссылке, которая может использоваться, чтобы определить местоположение или получить доступ к фактическому объекту. Этот случай довольно распространен, специально для приложений Java получающие доступ и совместно использующие службы в существующей установленной основе. Ссылка в действительности действует как "указатель" на реальный объект. В примере принтера, что фактически связывается, могла бы быть информация о том, как получить доступ к принтеру (например, его тип протокола, его адрес сервера). Чтобы включить этой удобной в работе модели для разработчика приложений, реализация контекста должна сделать преобразование данных к/от базовой службе в соответствующие объекты в языке программирования Java.
Есть различные способы достигнуть этой цели. У одной реализации контекста мог бы быть доступ ко всем классам реализации объектов, которые может возвратить каталог; у другой реализации контекста мог бы быть специальный загрузчик class для того, чтобы определить местоположение классов реализации для ее объектов. JNDI обеспечивает Reference
class как стандартный способ представить ссылки. Приложения и реализации контекста поощряются использовать этот class, вместо того, чтобы изобрести отдельные механизмы самостоятельно. Однако, это не устраняет реализации контекста от использования их собственных механизмов для того, чтобы достигнуть той же самой цели.
JNDI обеспечивает утилиты для реализаций контекста, чтобы использовать, читая/храня объекты в языке программирования Java независимым от формата способом к базовой службе. Этот раздел описывает эти утилиты. Эти утилиты взаимодействуют с компонентами, названными объектом, и утверждают фабрики, которые делают фактические преобразования. Эти фабрики описываются в Главе 4.
JNDI обеспечивает следующие методы, которые реализации контекста должны использовать, чтобы преобразовать данные, считанные из базовой службы в объекты в языке программирования Java:
Object NamingManager.getObjectInstance(Object refInfo, Name name, Context nameCtx, Hashtable env) throws Exception; Object DirectoryManager.getObjectInstance(Object refInfo, Name name, Context nameCtx, Hashtable env, Attributes attrs) throws Exception;
refInfo
данные (представляющий объект) чтение от базовой службы. name
имя объекта в то время как nameCtx
контекст, в котором можно решить name
. name
/nameCtx
пара может использоваться, чтобы получить больше информации об объекте, чем доступно от refInfo
. env
среда контекста от который getObjectInstance()
вызывается. attrs
набор атрибутов, считанных из каталога об объекте, обычно в том же самом запросе, который использовался, чтобы добраться refInfo
. Это не мог бы быть полный набор атрибутов, если бы такой не требовался. Метод в NamingManager
class должен использоваться реализациями контекста, которые реализуют Context
интерфейс, в то время как метод в DirectoryManager
class должен использоваться реализациями контекста, которые реализуют DirContext
интерфейс.
Создавая объекты, которые будут возвращены для следующих методов, реализация контекста должна вызвать getObjectInstance()
, или его собственный механизм для того, чтобы генерировать объекты от связанной информации, если это хочет, чтобы эта функция была включена в их контекстах. (Строковые перегрузки, не показанные.)
javax.naming.Context.lookup(Name name) javax.naming.Context.lookupLink(Name name) javax.naming.Binding.getObject() javax.naming.directory.SearchResult.getObject()
Для Binding
и SearchResult
, реализация контекста должна или передать объект, который является результатом вызова getObjectInstance()
или его эквивалент конструктору, или переопределение реализация по умолчанию Binding
и SearchResult
так, чтобы их getObject()
вызов реализаций getObjectInstance()
или его эквивалент перед возвратом.
Вот пример. Предположите, что принтеры представляются в использовании пространства имен Reference
s. Поворачивать принтер Reference
в живое Printer
объект, реализация контекста использовала бы NamingManager.getObjectInstance()
метод. Таким образом базовая служба не должна знать ничто определенное о принтерах.
Object lookup(Name name) { ... Reference ref = <some printer reference looked up from naming service>; return NamingManager.getObjectInstance(ref, name, this, env); }
В другом примере предположите, что принтеры представляются в каталоге как набор атрибутов. Поворачивать запись в каталоге принтера в живое Printer
объект, реализация контекста использовала бы DirectoryManager.getObjectInstance()
.
Object lookup(Name name) { ... Attributes attrs = <read attributes from directory>; Reference ref = <construct reference from attributes>; return DirectoryManager.getObjectInstance(ref, name, this, env, attrs); }
JNDI обеспечивает следующие методы, которые реализации контекста должны использовать, чтобы преобразовать объект прежде, чем сохранить его в базовой службе:
Object NamingManager.getStateToBind( Object obj, Name name, Context nameCtx, Hashtable env) throws NamingException; DirStateFactory.Result DirectoryManager.getStateToBind( Object obj, Name name, Context nameCtx, Hashtable env, Attributes attrs) throws NamingException;
obj
объект, который будет сохранен в базовой службе. name
имя объекта в то время как nameCtx
контекст, в котором можно решить name
. name
/nameCtx
пара может использоваться, чтобы получить больше информации об объекте, чем доступно от obj
. env
среда контекста от который getStateToBind()
вызывается. attrs
набор атрибутов, который должен быть связан с объектом. DirStateFactory.Result
class, который содержит объект и набор атрибутов.
Метод в NamingManager
class должен использоваться реализациями контекста, которые реализуют Context
интерфейс, в то время как метод в DirectoryManager
class должен использоваться реализациями контекста, которые реализуют DirContext
интерфейс.
Прежде, чем хранить объект, предоставленный приложением, реализация контекста должна вызвать getStateToBind()
, или его собственный механизм для того, чтобы генерировать информацию, которая будет связана, если это хочет, чтобы эта функция была включена в их контекстах. (Строковые перегрузки, не показанные.)
javax.naming.Context.bind(Name name, Object o) javax.naming.Context.rebind(Name name, Object o) javax.naming.DirContext.bind(Name name, Object o, Attributes attrs) javax.naming.DirContext.rebind(Name name, Object o, Attributes attrs)
Вот пример как a Context
реализация поддерживает Context.bind
:
// First do transformation obj = NamingManager.getStateToBind(obj, name, ctx, env); // Check for Referenceable if (obj instanceof Referenceable) { obj = ((Referenceable)obj).getReference(); } if (obj instanceof Reference) { // store as ref } else if (obj instanceof Serializable) { // serialize } else { ... }
Вот пример как a DirContext
реализация поддерживает DirContext.bind
:
// First do transformation DirStateFactory.Result res = DirectoryManager.getStateToBind( obj, name, ctx, env, inAttrs); obj = res.getObject(); Attributes outAttrs = res.getAttributes(); // Check for Referenceable if (obj instanceof Referenceable) { obj = ((Referenceable)obj).getReference(); } if (obj instanceof Reference) { // store as ref and add outAttrs } else if (obj instanceof Serializable) { // serialize and add outAttrs } else if (obj instanceof DirContext) { // grab attributes and merge with outAttrs } else { ... }
Как показано в этих примерах, реализация контекста могла бы быть в состоянии сохранить различные типы объектов (Reference
, Serializable
, и DirContext
). Если реализация контекста не может сохранить Referenceable
объекты непосредственно и getStateToBind()
возвращает такой объект, реализация контекста должна впоследствии вызвать Referenceable.getReference()
и сохраните получающееся Reference
вместо этого.
Если реализация контекста может сохранить различные типы объектов, она должна следовать за этим порядком на следующие общие типы:
Этот порядок рекомендуется, потому что он, наиболее вероятно, получит намерение вызывающей стороныbind()
/rebind()
метод. Например, a Reference
Serializable
, так, если Вы выполняли Serializable
проверьте сначала, нет Reference
объекты когда-либо хранились бы в ссылочном формате (то есть, они будут все сериализированы).
Когда контексту дают параметр имени строки, имя представляет составное имя, которое может охватить многократные пространства имен, или у этого может быть только единственный составной компонент имени (который поочередно может быть составлен из одного или нескольких атомарных имен), который принадлежит единому пространству имен. Реализация контекста должна определить, какая часть имени должна быть решена/обработана в его контексте и передать остальных на следующий контекст. Это может быть сделано синтаксически, исследуя имя, или динамически разрешая имя.
Когда контексту дают a Name
параметр, если это - экземпляр CompositeName
, тогда это будет обработано как составное имя. Иначе, это будет обработано как составное имя, которое реализуется CompoundName
class или некоторая другая составная реализация имени.
Контекст участвует в федерации, выполняя фазу разрешения всех операций контекста. lookup()
метод должен всегда поддерживаться. Поддержка других методов является дополнительной, но если контекст должен участвовать в федерации, то разрешение, неявное во всех операциях, должно поддерживаться.
Рисунок 1: Пример Разрешения через Промежуточные Контексты Выполнить связывание ().
Например, предположите, что контекст не поддерживает bind()
работа. Когда тот контекст используется в качестве промежуточного контекста для bind()
, это должно выполнить часть разрешения той работы, чтобы позволить работе продолжаться к следующему контексту. Это должно только бросить OperationNotSupportedException
если просят создать привязку в ее собственном контексте. Рисунок 1 показывает пример как bind()
работу передают через промежуточные контексты, которые будут выполняться в целевом контексте.
Вызвать a DirContext
метод (такой как getAttributes()
), приложение сначала получает начальную букву DirContext
, и затем выполните работу на DirContext
.
DirContext ctx = new InitialDirContext(); Attributes attrs = ctx.getAttributes(someName);С точки зрения реализации контекста, чтобы получить атрибуты,
getAttributes()
возможно, должен был бы пересечь многократные системы именования. Некоторые из этих систем именования только поддерживают Context
интерфейс, не DirContext
интерфейс. Эти системы именования используются в качестве посредников для того, чтобы решить к целевому контексту. Целевой контекст должен поддерживать DirContext
интерфейс. Рисунок 2 показывает пример этого. Рисунок 2: Пример Разрешения Через Промежуточный non-DirContexts
Для промежуточных систем именования, чтобы участвовать в федерации для расширений Context
, они должны реализовать Resolver
интерфейс. Resolver
интерфейс используется платформой JNDI, чтобы решить через промежуточные контексты, которые не поддерживают определенный подынтерфейс Context
. Это состоит из двух перегруженных форм метода resolveToClass()
. Этот метод используется, чтобы частично разрешить имя, останавливающееся в первом контексте, который является экземпляром необходимого подынтерфейса. Оказывая поддержку для этого метода и фазы разрешения всех методов в Context
интерфейс, реализация контекста может действовать как промежуточный контекст для расширений (подынтерфейсы) Context
.
public interface Resolver { public ResolveResult resolveToClass(Name name, Class contextType)
throws NamingException; public ResolveResult resolveToClass(String name, Class contextType)
throws NamingException; }
Разрешение (многокомпонентного) составного имени продолжается от одной системы именования до следующего с разрешением компонентов, которые охватывают каждую систему именования, обычно обрабатываемую соответствующей реализацией контекста. С точки зрения реализации контекста это передает компоненты, для которых это не ответственно (реализация контекста) затем именование системы.
Есть несколько путей, которыми может быть расположена реализация контекста для следующей системы именования. Это может быть сделано явно с помощью стыка, где имя в одной системе именования связывается с контекстом (или a Reference
к контексту) в следующей системе именования. Например, с составным именем "cn=fs,ou=eng/lib/xyz.zip", имя LDAP "cn=fs, ou=eng" могло бы решить к контексту файловой системы, в котором "lib/xyz.zip" могло тогда быть разрешено имя.
Поочередно, следующая система именования может быть расположена неявно. Например, реализация контекста может выбрать следующую систему именования, основанную на специфичном для службы знании объекта, что это решило. Например, с составным именем "ldap.wiz.com/cn=fs,ou=eng", именем DNS ldap.wiz.com
мог бы назвать запись DNS. Чтобы получить следующую систему именования вне DNS, реализация контекста DNS могла бы создать контекст, используя ресурсные записи SRV, найденные в той записи, которую в этом случае, оказывается, называет контекстом LDAP. Когда следующая система именования располагается этим способом, разделитель имени составного объекта JNDI используется, чтобы обозначить границу от одной системы именования до следующего, и упоминается как неявный следующий системный указатель именования.
Однако следующая система именования располагается, реализация контекста должна вручить следующей системе именования остающуюся часть составного имени к решению.
В выполнении работы на имени, которое охватывает многократные пространства имен, контекст в промежуточной системе именования должен передать работу на следующую систему именования. Контекст делает это первым построением a CannotProceedException
содержа информационное точное определение, как далеко это продолжилось. При этом это определяет разрешенный объект, разрешенное имя, остающееся имя, и части среды исключения 2 (В случае Context.rename()
метод, это также устанавливает "разрешенный newname" часть.)
Это тогда получает контекст продолжения из JNDI, передавая CannotProceedException
к статическому методу NamingManager
.getContinuationContext()
public class NamingManager { public static Context getContinuationContext( CannotProceedException e) throws NamingException; ... }
Информация в исключении используется getContinuationContext()
создать экземпляр контекста, в котором можно продолжать работу.
Получить контекст продолжения для DirContext
операции, использовать Directory-Manager.getContinuationDirContext()
.
public class DirectoryManager { public static getContinuationDirContext( CannotProceedException e) throws NamingException; ... }
После получения контекста продолжения работа должна продолжаться, используя остаток от имени, которое не было разрешено.
Например, пытаясь продолжать a bind()
работа, код в реализации контекста мог бы смотреть следующим образом:
public void bind(Name name, Object obj) throws NamingException { ... try { internal_bind(name, obj); ... } catch (CannotProceedException e) { Context cctx = NamingManager.getContinuationContext(e); cctx.bind(e.getRemainingName(), obj); } }
В этом примере, bind()
зависит от внутреннего метода, internal_bind(),
выполнить фактическую работу связывания и бросить a CannotProceedException
когда это обнаруживает, что это - выход за пределы этой системы именования. К исключению тогда передают getContinuationContext()
чтобы продолжать работу. Если работа не может продолжаться, контекст продолжения бросит CannotProceedException
к вызывающей стороне оригинала bind()
работа.
В некоторых конфигурациях федерации результат разрешения в одной системе именования не указывает, который является следующей системой именования. Единственное заключение, что реализация контекста может потянуть, состоит в том, что разрешение завершилось в текущей системе именования и должно продолжиться к следующей системе именования.
Например, предположите, что составное имя "lib/xyz.zip/part1/abc" состоит из двух частей: "lib/xyz.zip", который называет файл в формате ZIP, и "part1/abc", который называет запись в пределах файла ZIP. Хотя разрешение "lib/xyz.zip" результатов в объекте файла, требуемым результатом является контекст, в котором можно разрешить имена записей ZIP. Точно так же другое составное имя могло назвать запись в пределах файла в формате "tar", и требуемым результатом разрешения компонента файла составного имени будет контекст, в котором можно разрешить записи tar.
В действительности любой тип контекста мог бы быть объединен в федерацию ниже пространства имен файловой системы в зависимости от формата файлов. Такие отношения должны быть симметричными: для контекста файла ZIP и других подобных контекстов должно быть возможно объединить в федерацию ниже другого, пространств имен нефайловой системы. Кроме того разработчики, пишущие реализацию контекста файловой системы и те, которые пишут реализации контекста для контекста файла ZIP, контекста файла tar, или контекста для некоторого все же будущего определенного формата, должны быть в состоянии работать независимо.
Чтобы поддерживать этот тип федерации, JNDI определяет специальную форму Reference
названный nns ссылкой ("nns" обозначает "следующую систему именования"). Это Reference
имеет адрес с типом nns
. Содержание адреса является разрешенным объектом (в вышеупомянутом примере, файле ZIP). Продолжаясь с примером файловой системы, реализация контекста файловой системы могла бы создать nns ссылку следующим образом:
RefAddr addr = new RefAddr("nns") { public Object getContent() { return theFile; } }; Reference ref = new Reference("java.io.File", addr);
Затем, реализация контекста создает a CannotProceedException
(как со случаем стыка) при использовании nns ссылки как разрешенный объект, и разрешенное имя, состоящее из разрешенного имени файла и пустого компонента. Пустой компонент используется в качестве неявного следующего системного указателя именования и указывает, что разрешение успешно выполнилось на грани разрешения следующей системы именования. (Заметьте, как значения разрешенного объекта и разрешенного имени являются соответствующими.) Контекст impementation тогда передает CannotProceedException
к getContinuationContext()
.
Как с любым разрешенным объектом в a CannotProceedException
, getContinuationContext()
поиски реализации контекста, которая принимает эту nns ссылку. Реализация контекста файла ZIP, например, могла бы принять nns ссылку и другую информацию если, такие как имя файла (относительно данного контекста). Если реализация контекста решает, что файл является файлом ZIP, это тогда создало бы контекст для того, чтобы разрешить имена в пределах того файла.
Центральный к платформе SPI JNDI для федерации CannotProceedException
. A Cannot-ProceedException
содержит информацию, такую как разрешенное имя/объект и остающееся имя, наследованное от NamingException
суперкласс. Кроме того, a CannotProceedException
также содержит поля для имени "alt" и контекста имени "alt". В то время как разрешенное имя от NamingException
полное составное имя (относительно запускающегося контекста работы), имя alt является разрешенным именем относительно контекста имени alt. Таким образом, имя alt не могло бы обязательно быть тем же самым как разрешенным именем. Имя высокого звука и контекст имени alt используются в качестве параметров NamingManager
/DirectoryManager.getObjectInstance()
. Они позволяют фабрики, которые вызывает этот метод, чтобы получить больше информации о разрешенном объекте (например, это могло использоваться, чтобы получить специальный атрибут об объекте). Эти фабрики описываются в Главе 4.
В то время как акцент платформы SPI JNDI находится на "ожидании" и попытке найти следующую систему именования, некоторые реализации контекста, когда-то расположенные, должны "оглянуться назад" цепочка разрешения, чтобы получить контекстную информацию. Например, определенная реализация контекста, которая объединяется в федерацию прочь системы именования узла, могла бы быть разработана так, что, единственное подразумевает, который она может узнать, что информация об узле должна спросить (возможно не непосредственный) превосходящая система именования. Чтобы сделать это, это нуждается в контекстной информационной информации о как разрешение, продолженное к его текущей точке.
Суммируя более ранние обсуждения федерации, выполняя работу на имени, которое охватывает многократные пространства имен, реализация контекста сначала создает a CannotProceed-Exception
содержа информационное точное определение, как далеко это продолжилось. Это тогда получает контекст продолжения из JNDI, вызывая getContinuationContext()
. Поддерживать извлечение контекстной информации, getContinuationContext()
автоматически добавляет свойство среды java.naming.spi.CannotProceedException
, со значением Cannot-ProceedException
параметр, к среде контекста продолжения. Это свойство наследовано контекстом продолжения и может использоваться реализацией того контекста, чтобы осмотреть поля исключения.
LDAP-разработайте поддержку служб каталогов понятие отсылок для того, чтобы перенаправить запрос клиента к другому серверу. Отсылка отличается от механизма продолжения федерации, описанного ранее, в котором отсылка может быть представлена клиенту JNDI, который тогда решает, следовать ли за этим, тогда как a CannotProceedException
должен быть возвращен клиенту только, когда никакое дальнейшее продвижение не возможно. Другое различие - то, что отдельная реализация контекста предлагает возможность продолжения работы, используя отсылку (и он непосредственно определяет механизм для того, чтобы сделать так). В федерации механизм продолжения выходит за рамки отдельных реализаций контекста: отдельное преимущество реализаций контекста от общего механизма федерации обеспечило платформой SPI JNDI.
Реализация контекста, которая поддерживает отсылки, определяет подкласс ReferralException
и обеспечивает реализации для его абстрактных методов. getReferralContext()
возвращает контекст, в котором можно продолжить работу, и getReferralInfo()
информация о возвратах о том, где отсылка приводит в формате, соответствующем реализации контекста.
Свойство среды java.naming.referral
определяет, как реализация контекста должна обработать отсылки. Если реализацию контекста просят выдать исключение, когда с отсылкой встречаются, или если реализация контекста встречается с проблемами после отсылки, это бросает a ReferralException
к приложению. Чтобы продолжать работу, приложение повторно вызывает метод на контекст отсылки, используя те же самые параметры, которые это предоставляло к исходному методу. Следующий пример кода показывает как ReferralException
может использоваться application:3
while (true) { try { bindings = ctx.listBindings(name); while (bindings.hasMore()) { b = (Binding) bindings.next(); ... } break; } catch (ReferralException e) { ctx = e.getReferralContext(); } }
Это соглашение перевызова метода, используя исходные параметры является простым для приложений, чтобы следовать. Это помещает бремя в реализацию ReferralException, чтобы предоставить достаточно информации к реализации контекста отсылки для работы, которая будет продолжаться. Отметьте, что это, вероятно, представит некоторые из параметров, которые передают к повторно вызванной лишней работе. Реализация контекста отсылки свободна проигнорировать любую избыточную или ненужную информацию.
Для работы возможно возвратить результаты в дополнение к отсылке. Например, ища контекст, сервер мог бы возвратить несколько результатов в дополнение к нескольким отсылкам как, туда, где получить дальнейшие результаты. Эти результаты и отсылки могли бы быть чередованы на уровне протокола. Если отсылки требуют взаимодействия с пользователем (то есть, не сопровождаемый автоматически), реализация контекста должна возвратить результаты посредством перечисления поиска сначала. Когда результаты были возвращены, исключение отсылки может тогда быть выдано. Это позволяет простой модели программирования использоваться, даря пользователю с четким отношением между отсылкой и ее набором результатов.
JNDI определяет Attribute
интерфейс для того, чтобы представить атрибут в каталоге. Атрибут состоит из идентификатора атрибута (строка) и ряд значений атрибута, которые могут быть любым объектом в языке программирования Java. Есть также методы, определенные в Attribute
для того, чтобы получить определение атрибута и определение синтаксиса из схемы каталога.
public class Attribute { public DirContext getAttributeDefinition() throws NamingException; public DirContext getAttributeSyntaxDefinition()
throws NamingException; ... }
Утилита class, BasicAttribute
, не обеспечивает полезные реализации для этих методов. Реализация контекста каталога, у которой есть поддержка такой информации о схеме, должна обеспечить реализации Attribute
та реализация эти два метода, основанные на ее механизмах схемы, возможно разделяя на подклассы BasicAttribute
и переопределение этих двух методов. Реализация контекста должна тогда возвратить экземпляры этих подклассов когда спрошено возвратить экземпляры Attribute
. Реализация контекста, когда это получает Attribute
экземпляр, у которых нет значимых реализаций этих двух методов, должен использовать разумные значения по умолчанию, чтобы определить определение атрибута и синтаксис, используя информацию, такую как имена class значений атрибута или соглашения, используемые для идентификатора атрибута.
DirContext
интерфейс содержит связанные со схемой методы:
public class DirContext { ... public DirContext getSchema(Name name) throws NamingException; public DirContext getSchema(String name) throws NamingException; public DirContext getSchemaClassDefinition(Name name) throws NamingException; public DirContext getSchemaClassDefinition(String name) throws NamingException; }
getSchema()
возвращает дерево схемы для именованного объекта, в то время как getSchemaClassDefinition()
возвращает контекст, содержащий схему определения class для именованного объекта. У некоторых систем есть только одна глобальная схема и, независимо от значения name
параметр, возвратит то же самое дерево схемы. Другие поддерживают более прекрасный, гранулировал определения схемы, и может возвратить различные деревья схемы, в зависимости от которых исследуется контекст.
Реализация контекста поддерживает уведомление о событии, обеспечивая реализацию для методов в EventContext
/EventDirContext
интерфейсы. Модель событий, защищенная этими интерфейсами, может с готовностью поддерживаться, используя многопоточную модель. Когда приложение использует addNamingListener()
чтобы зарегистрировать слушателя в контексте, контекст записывает запросы и принимает меры, чтобы собрать информацию, требуемую генерировать события. Когда контекст в конечном счете получает информацию, чтобы генерировать события, это запускает события в слушателя. Поток, который делает регистрацию, обычно отличается от потока, который выполняет слушателя. Реализация контекста обычно использует поток, который она создала и управляет выполнить метод слушателя. Когда одно событие диспетчеризируется многократным слушателям, реализация контекста может выбрать к (и обычно поощряется) выполнить методы слушателя одновременно в отдельных потоках.
addNamingListener()
методы принимают экземпляр NamingListener
. Экземпляр мог бы реализовать один или более подынтерфейсов NamingListener
. Если слушатель реализует больше чем один подынтерфейс, реализация контекста должна попытаться сохранить ресурсы, требуемые удовлетворить регистрацию. Например, реализация могла бы быть в состоянии представить единственный запрос серверу, который получает все запросы подынтерфейсов.
Где только возможно реализация контекста должна запустить a NamingExceptionEvent
слушателю, если контекст будет неспособен запустить дальнейшие события и затем автоматически вычеркнуть из списка слушателя. Например, если соединение с сервером повреждается последующее за регистрацией слушателя, и никакая информация не будет доступна, чтобы запустить события, контекст должен запустить a NamingExceptionEvent
слушателю.
Каждый экземпляр Context
(или его подынтерфейсы), мог связать с этим среду, которая содержит предпочтение, выраженное приложением того, как это хотело бы получить доступ к услугам, предложенным контекстом. Примерами информации, найденной в среде, является связанная с безопасностью информация, которые определяют учетные данные пользователя и требуемый уровень безопасности (none
, simple
, strong
), и конфигурационная информация, такая как сервер, чтобы использовать. См. Главу 6 и Приложение A документа API JNDI для большего количества деталей о свойствах среды.
Свойства среды определяются в общем, чтобы гарантировать максимальную мобильность. Отдельные поставщики услуг должны отобразить эти универсальные свойства на характеристики, подходящие для их службы. Свойства, которые не относятся к провайдеру, должны быть записаны и тихо проигнорированы. Среда может также использоваться для того, чтобы сохранить специфичные для поставщика услуг свойства или предпочтение, когда их применимость через различных провайдеров ограничивается.
См. Раздел 6.1 в документе API JNDI для описания того, как свойства среды называют. У специфичных для поставщика услуг свойств должен быть префикс, который отражает их уникальность к провайдеру. Обычная практика должна использовать имя пакета поставщика услуг как префикс. Например, так как провайдер Sun LDAP прежде всего содержится в пакете com.sun.jndi.ldap
, у свойств, определенных для провайдера Sun LDAP, есть префикс "com.sun.jndi.ldap"..
Создавая начальный контекст (любое использование конструкторов от InitialContext
или его подклассы), приложение может предоставить среду в качестве параметра. Параметр представляется как a Hashtable
или любой из его подклассов (например, Properties
). Библиотека class JNDI увеличивает данные от этого параметра с данными из других источников (см. Главу 6 в документе API JNDI), и передает это к реализации контекста.
Как все другие параметры, параметр среды, полученный реализацией контекста, принадлежит вызывающей стороне. Реализация контекста должна сделать копию параметра среды, который это получает, или иначе предпримите шаги, чтобы гарантировать, что изменения вызывающей стороной к параметру не влияли бы на то, что реализация контекста видит и наоборот. Отметьте также это, если параметр среды является a Properties
экземпляр, перечисление и Hashtable.get()
на параметре только исследуют высокоуровневые свойства (не любые вложенные значения по умолчанию). Это - ожидаемое поведение. Реализация контекста, как ожидают, не получит или перечислит значения в Properties
вложенные значения по умолчанию экземпляра.
Библиотека JNDI ответственна за слияние свойств из различных источников, таких как параметр среды к начальному контексту, файлам ресурсов, и, где необходимо, системным свойствам и параметрам апплета (см. документ API JNDI, Главу 6). Реализация контекста обычно только читает свойство, в котором она нуждается от среды, которая она была предоставлена. редко есть потребность в реализации контекста, чтобы консультироваться с другими источниками.
Среда наследована от родителя до дочернего элемента, поскольку методы контекста продолжаются от одного контекста до следующего. Вся среда экземпляра контекста наследована дочерними экземплярами контекста, независимо от того, игнорируются ли определенные свойства в пределах среды определенным контекстом.
Реализация контекста должна передать среду от одного экземпляра контекста до следующего, чтобы реализовать эту черту "наследования" сред. В пределах одной реализации контекста это может сделать так, передавая среду как параметр Context
конструктор, или к NamingManager/DirectoryManager.getObjectInstance()
метод для того, чтобы создать Context
экземпляры.
Через реализации контекста в федерации это поддерживается, передавая среду как часть CannotProceedException
параметр NamingManager.getContinuationContext()/DirectoryManager.getContinuationDirContext()
, который поочередно будет использовать эту среду, создавая экземпляр контекста, в котором можно продолжать работу.
Наследование может быть реализовано всегда, пока оно сохраняет семантику, что у каждого контекста есть свое собственное представление его среды. Например, реализация копии на записи могла использоваться, чтобы задержать копирование среды, пока это не абсолютно необходимо.
Среда контекста может быть обновлена через использование addToEnvironment() and removeFromEnvironment()
методы в Context
интерфейс.
public interface Context { ... public Object addToEnvironment(String propName, Object propVal) throws NamingException; public Object removeFromEnvironment(String propName) throws NamingException; }
Эти методы обновляют среду этого экземпляра Context
. Свойство среды, которое не относится к реализации контекста, тихо игнорируется, но сохраняется как часть среды. Обновленная среда влияет на этот экземпляр Context
, и будет наследован любым новым дочерним элементом Context
экземпляры, но не влияет на никого Context
экземпляры, уже существующие. Поиск пустого названия на a Context
возвратит новое Context
экземпляр со средой, наследованной как с любым другим дочерним элементом.
См. Раздел 6.6 в документе API JNDI для деталей.
У каждого поставщика услуг есть дополнительный файл ресурсов, который содержит свойства, определенные для того провайдера. Имя этого ресурса:
[prefix/]jndiprovider.propertiesгде префикс является именем пакета реализации (й) контекста провайдера с каждым периодом (". ") преобразованный в наклонную черту (" / "). Например, предположите, что поставщик услуг определяет реализацию контекста с помощью имени class
com.sun.jndi.ldap.LdapCtx
. Ресурс провайдера для этого провайдера называют com/sun/jndi/ldap/jndiprovider.properties
. Библиотека class JNDI будет консультироваться с этим файлом, когда это должно будет определить значение свойства, как описано в Разделе 6.5.2 в документе API JNDI.
Когда поставщик услуг должен будет определить значение свойства, это обычно примет что значение непосредственно от среды. Поставщик услуг может определить специфичные для провайдера свойства, которые будут помещены в его собственный файл ресурсов провайдера. В этом случае это должно считать их из своего файла ресурсов свойства и объединить их в пути, непротиворечивом с алгоритмом, описанным в Разделе 6.5.2 в документе API JNDI.
Для реализации контекста, которая использует клиент-серверный протокол, есть не обязательно непосредственное отображение между контекстом и соединением между клиентом и сервером. JNDI является высокоуровневым API, который не имеет дело непосредственно с соединениями. Это - задание реализации контекста, чтобы сделать любое необходимое управление соединением. Следовательно, единственное соединение может быть совместно использовано многократными экземплярами контекста, и реализация контекста свободна использовать свои собственные алгоритмы, чтобы сохранить соединение и сетевое использование. Таким образом, когда метод вызывается на экземпляр контекста, реализация контекста, возможно, должна была бы сделать некоторое управление соединением в дополнение к выполнению требуемой работы.
Context.close()
и NamingEnumeration.close()
методы могут использоваться приложениями, чтобы обеспечить подсказки для реализации контекста относительно когда к связанным с бесплатным подключением ресурсам. Реализация контекста может выбрать к (и обычно призывается к), принимают другие меры, чтобы собрать "мусор" и сохранить его связанные с соединением ресурсы.
Некоторые свойства среды влияют на соединение контекста. Например, если приложение изменяет связанные с безопасностью свойства, реализация контекста, возможно, должна была бы изменить или создать новое соединение, используя те обновленные свойства. Если бы соединение совместно использовалось другими контекстами до изменения, то изменение соединения не должно влиять на контексты, свойства которых не были обновлены.
Так как все методы именования выполняются относительно контекста, приложение нуждается в запускающемся контексте, чтобы вызвать их. Этот начальный контекст упоминается как начальный контекст. Привязка в начальном контексте определяется политиками, сформулированными начальной реализацией контекста, возможно используя стандартные политики для того, чтобы назвать глобальные и пространства имен всего предприятия. Например, начальный контекст мог бы содержать привязку с интернет-пространством имен DNS, привязку с пространством имен всего предприятия, и привязку с персональным каталогом, принадлежащим пользователю, который запускает приложение.
Приложение получает начальный контекст, выполняя следующий вызов:
Context ctx = new InitialContext();Альтернативный конструктор позволяет среде быть переданной как параметр. Это позволяет приложению передавать в предпочтении или информации о безопасности, которая будет использоваться в конструкции начального контекста.
Hashtable env = new Hashtable();4 env.put(Context.SECURITY_PRINCIPAL, "jsmith"); env.put(Context.SECURITY_CREDENTIALS, "xxxxxxx"); Context ctx = new InitialContext(env);
Последующий за получением начального контекста, приложение может вызвать Context
методы.
Object obj = ctx.lookup("this/is/a/test");
InitialContext
class (и подклассы) выбирает реализацию, используя алгоритм значения по умолчанию, который может быть переопределен, устанавливая начального разработчика фабрики контекста (описанный ниже).
InitialDirContext
расширение InitialContext
. Это используется для того, чтобы выполнить операции каталога, используя начальный контекст. InitialLdapContext
class является расширением InitialDirContext
. Это используется для того, чтобы выполнить специальный LDAP v3 операции, используя начальный контекст. Алгоритмы и политики, описанные в этом разделе также, применяются к InitialDirContext
и InitialLdapContext
. Места, где DirContext/LdapContext
требуется вместо Context
были отмечены.
Начальной фабрикой контекста является class, который создает экземпляр контекста, который был реализован после направляющих линий, обрисованных в общих чертах в Главе 2. Фабрика используется InitialContext
class (или подкласс) конструктор.
Учитывая среду, фабрика возвращает экземпляр Context
(или его подынтерфейсы).
public interface InitialContextFactory { public Context getInitialContext(Hashtable env)
throws NamingException; }
Приложение A содержит пример InitialContextFactory
.
Как только экземпляр контекста был создан, когда метод вызывается на InitialContext
при использовании имени не-URL (см. ниже), метод передается и вызывается на тот экземпляр контекста.
JNDI выбирает начальную реализацию контекста, чтобы использовать при использовании свойства java.naming.factory.initial
. Это свойство содержит полностью определенное имя class начальной фабрики контекста. class должен реализовать InitialContextFactory
соедините интерфейсом и имейте общедоступного конструктора, который не берет параметров. JNDI загрузит начальную фабрику контекста class и затем вызовет getInitialContext()
на этом, чтобы получить a Context
экземпляр, который будет использоваться в качестве начального контекста.
Приложение, которое хочет использовать определенный начальный контекст, должно предоставить java.naming.factory.initial
свойство в среде, которую передают к InitialContext
(или подкласс) конструкторы, или через файлы ресурсов, системные свойства, или параметры апплета.
Когда свойство java.naming.factory.initial
устанавливается в не -null
значение, InitialContext
(и подкласс) конструкторы попытаются загрузить и инстанцировать начальной фабрики контекста, которая тогда создаст экземпляр контекста. Если фабрика или контекст не могут быть созданы, например в результате проблемы аутентификации, начальная фабрика контекста может выдать исключение, чтобы указать на эту проблему. Отметьте однако, что это до реализации контекста, когда это проверяет и указывает пользователям начального контекста на любое свойство среды - или соединение - связанные проблемы. Это может сделать настолько лениво задерживающийся, пока работа не выполняется на контексте, или нетерпеливо, в то время, когда контекст создается.
Если свойство java.naming.factory.initial
не устанавливается, никакая попытка не будет предпринята, чтобы создать базовый контекст для начального контекста. Начальный контекст все еще полезен, например, для того, чтобы обработать имена URL, как описано затем.
Если строку URL5 передадут к начальному контексту, то она будет разрешена, используя соответствующую реализацию контекста URL. Эта функция поддерживается InitialContext
class (и подклассы) и независим от установки java.naming.factory.initial
свойство среды.
Эта функция позволяет приложениям использовать начальный контекст, чтобы достигнуть любого пространства имен, для которого реализация контекста URL была сделана доступной. Например, следующий код перечисляет пространство имен LDAP от начального контекста:
new InitialContext().list("ldap://lserver/ou=eng,o=wiz,c=us");
У строки URL есть следующий формат:
Например, у строки URL LDAP есть идентификатор схемы "ldap"; у файла URL есть идентификатор схемы "файл".
Реализацией контекста URL является class, который реализует Context
интерфейс (и возможно некоторые подынтерфейсы) и принимают параметры имени, которые являются строками URL схемы, которую он поддерживает. Например, контекст URL LDAP принимает "ldap" строки URL.
Когда имя строки URL передают к контексту URL, методы контекста, которые принимают String
обработайте имя как URL с синтаксисом, определенным схемой URL. Когда a Name
объект, в котором первый компонент является именем строки URL, передают к контексту URL, первый компонент обрабатывается как строка URL, и остальное используется для федерации (то есть, разрешение первого компонента укажет который, называя систему, чтобы использовать, чтобы разрешить остальных). Name
экземпляр должен быть a CompositeName
; иначе, InvalidNameException
должен быть брошен.
Параметры имени, которые не являются строками URL, и строками URL с несоответствующим идентификатором схемы, должны быть отклонены с InvalidNameException
.
Фабрикой контекста URL является class (фактически специальная фабрика объекта типа (см. Раздел 4.1)), который создает экземпляр контекста URL для URL одной или более схем.
Когда InitialContext
class получает строку URL как параметр имени, он будет искать фабрику контекста URL при использовании следующего алгоритма. Свойство среды java.naming.factory.url.pkgs
содержит разделенный от двоеточия список префиксов пакета. Имя class фабрики создается при использовании следующего правила:
package_prefix +"." + scheme_id +"." + scheme_idURLContextFactory
для каждого префикса пакета, перечисленного в свойстве. Префикс пакета значения по умолчанию com.sun.jndi.url
добавляется до конца списка.
Например, если URL"ldap://somehost:389
"и java.naming.factory.url.pkgs
содержит"com.widget:com.wiz.jndi
", InitialContext
class попытается определить местоположение соответствующей фабрики class, загружая следующие классы, пока каждый успешно не инстанцируют:
com.widget.ldap.ldapURLContextFactory com.wiz.jndi.ldap.ldapURLContextFactory com.sun.jndi.url.ldap.ldapURLContextFactoryФабрика class реализует
ObjectFactory
у интерфейса (см. "Фабрику Контекста URL" на странице 31) и есть общедоступный конструктор, который не берет параметров. InitialContext
class передает идентификатор схемы как разрешенный объект к фабрике getObjectInstance()
метод, который поочередно создает контекст URL для схемы URL. Контекст URL будет тогда использоваться, чтобы выполнить первоначально предназначенный Context
или DirContext
работа на URL, предоставленном InitialContext
.
Нет никакого требования что предоставление поставщика услуг фабрика контекста URL и реализация контекста URL. Это только делает так, если это хочет позволить названиям строк URL с его схемой URL быть принятыми InitialContext
class. Поставщик услуг, например, мог бы только обеспечить начальную фабрику контекста и реализацию контекста, к которой получают доступ через ту фабрику.
Политика создания начальной фабрики контекста, используя java.naming.factory.initial
свойство среды и поддержка URL создаются в InitialContext
class. Есть два способа, которыми приложение может переопределить некоторых или всю эту политику.
Если приложение не хочет, чтобы строки URL были обработаны особенно, оно может использовать метод NamingManager.getInitialContext()
, который создает экземпляр контекста, используя фабрику, названную в java.naming.factory.initial
свойство среды.
Этот метод также полезен, если приложение должно получить доступ к интерфейсам, реализованным контекстом, создаваемым начальной фабрикой контекста, но которые не являются одним из Context
, DirContext
, или LdapContext
. Вот фрагмент кода, который получает использование контекста NamingManager.getInitialContext()
и затем броски это к подклассу:
FooContext ctx = (FooContext) NamingManager.getInitialContext(env); ... Object obj = ctx.lookup(name); ctx.fooMethod1(...);Отметьте, что установка начального разработчика фабрики контекста (обсуждал затем) влияет на результат
NamingManager.getInitialContext()
.
Начальным разработчиком фабрики контекста является class, который создает экземпляры начальных фабрик контекста.
Приложение может установить начального разработчика фабрики контекста, чтобы определить ее собственную политику того, как определить местоположение и создать начальные реализации контекста. Когда разработчик был установлен, это исключительно ответственно за создание начальных фабрик контекста. Ни одна из политик значения по умолчанию (java.naming.factory.initial
свойство или поддержка URL), обычно используемый JNDI используются.
Реализация начального разработчика фабрики контекста должна реализовать InitialContext-FactoryBuilder
интерфейс. createInitialContextFactory()
метод создает экземпляры InitialContextFactory
.
После того, как разработчик был установлен. приложение может получить начальный контекст любым использованием InitialContext
/InitialDirContext
/InitialLdapContext
конструкторы, или при использовании NamingManager.getInitialContext()
. Когда один из конструкторов используется, его class является в основном оберткой вокруг базовой реализации контекста, возвращенной NamingManager.getInitialContext()
.
Когда есть потребность обеспечить начальный контекст, который поддерживает интерфейс, который расширяется от Context
, DirContext
, или LdapContext
, поставщик услуг должен предоставить подкласс InitialContext
(или InitialDirContext/InitialLdapContext
).
Добавить поддержку URL таким же образом InitialContext
и InitialDirContext
сделайте, подкласс должен использовать защищенные методы, доступные в InitialContext
следующим образом. Это только имеет смысл для интерфейсов, у которых есть методы, которые принимают параметр имени.
Например, предположить FooContext
подынтерфейс DirContext
. Его начальная реализация контекста определила бы getURLOrDefaultInitFooCtx()
методы (для обоих Name
и String
параметры), которые получают реальный начальный контекст, чтобы использовать.
public class InitialFooContext extends InitialDirContext { ... protected FooContext getURLOrDefaultInitFooCtx(Name name) throws NamingException { Context answer = getURLOrDefaultInitCtx(name); if (!(answer instanceof FooContext)) { throw new NoInitialContextException("Not a FooContext"); } return (FooContext)answer; } // similar code for getURLOrDefaultInitFooCtx(String name) }Обеспечивая реализации для новых методов в
FooContext
интерфейс, которые принимают параметр имени, getURLOrDefaultInitFooCtx()
используется следующим образом. public Object FooMethod1(Name name, ...) throws NamingException { return getURLOrDefaultInitFooCtx(name).FooMethod1(name, ...); }
Обеспечивая реализации для новых методов в FooContext
интерфейс, у которых нет параметра имени, или для которого не требуется поддержка URL, использует InitialContext.getDefaultInitCtx()
.
protected FooContext getDefaultInitFooCtx() throws NamingException { Context answer = getDefaultInitCtx(); if (!(answer instanceof FooContext)) { throw new NoInitialContextException("Not an FooContext"); } return (FooContext)answer; } public Object FooMethod2(Args args) throws NamingException { return getDefaultInitFooCtx().FooMethod2(args); }
Реализация должна предоставить соответствующим конструкторам для class. Конструктор должен вызвать соответствующего конструктора суперкласса. Если среда должна быть изменена или исследована до вызываемого конструктора суперкласса, она должна использовать защищенного конструктора, который принимает, что булев флаг управляет инициализацией начального контекста, и затем использует init()
метод, чтобы инициализировать контекст. Вот пример:
public InitialFooContext(Hashtable environment, Object otherArg) throws NamingException { super(true); // don't initialize yet // Clone environment and adjust Hashtable env = (environment == null) ? new Hashtable(11) : (Hashtable)environment.clone(); ... init(env); }Клиентские программы, которые используют этот новый начальный контекст, смотрели бы следующим образом.
import com.widget.jndi.InitialFooContext; ... FooContext ctx = new InitialFooContext(env); Object obj = ctx.lookup(name); ctx.FooMethod1(name, ...);
JNDI позволяет реализации контекста быть настроенной - приложением, deployer приложения или пользователем, или поставщиком услуг - в том, как это читает и хранит объекты в именовании/службе каталогов. Подобное средство также доступно для сужения LDAP v3 классы управления.
Можно думать об этих средствах как о модулях, которые включают реализацию контекста.
JNDI обеспечивает универсальный способ создать объекты (включая экземпляры Context
) использование информации сохранено в пространстве имен. Та информация может иметь произвольный тип (java.lang.Object
). Например, это может быть a Reference
, или URL, или любые другие данные, требуемые создать объект. Превращение такой информации, хранившей в пространстве имен в объект, поддерживается с помощью объектных фабрик. Объектной фабрикой является class, который реализует ObjectFactory
интерфейс (или DirObjectFactory
подынтерфейс):
public interface ObjectFactory { public Object getObjectInstance(Object refObj, Name name, Context nameCtx, Hashtable env) throws Exception; } public interface DirObjectFactory extends ObjectFactory { public Object getObjectInstance(Object refObj, Name name, Context nameCtx, Hashtable env, Attributes attrs) throws Exception; }Учитывая некоторую информацию о ссылке (
refObj
) об объекте дополнительная информация об имени объекта и где это связывается, и дополнительно некоторая дополнительная информация о среде (например, некоторые идентификационные данные или информация об аутентификации о пользователе, создающем объект), фабрика, пытается создать объект, представленный информацией о ссылке. Например, данный информацию о ссылке о принтере, фабрика объекта принтера могла бы возвратить экземпляр Printer
. В случае объектной фабрики, которая должна использоваться с a DirContext
реализация, фабрике также дают некоторые атрибуты об объекте. Если фабрика требует большего количества атрибутов или информации, она может получить их непосредственно из именования/службы каталогов при использовании name
/nameCtx
параметры. Если фабрика не может, создал объект, используя предоставленные параметры, она должна возвратиться null
. Например, когда фабрика объекта принтера является определенными данными о дисководе, это должно возвратиться null
. Фабрика должна только выданный исключение, если никакие другие объектные фабрики нельзя попробовать. Поэтому, фабрика должна быть осторожной относительно исключений на этапе выполнения, которые могли бы быть брошены от ее реализации. Например, если фабрика объекта принтера является определенными данными о принтере, но данные уродливы в некотором роде, это должно выдать исключение.
Объектные фабрики используются в нескольких местах в JNDI, в основном чтобы превратить любую информацию о ссылке в объект. Они используются в федерации, обработке URL в начальном контексте, и, как иллюстрировано примером принтера, превращая данные в форму, ожидаемую приложением.
A Reference
содержит методы для того, чтобы возвратить название и местоположение class объектной фабрики. Следующие методы находятся в Reference
.
public class Reference { ... public String getClassName(); public String getFactoryClassName(); public String getFactoryClassLocation(); }Если объект, считанный из службы каталога/именования, является экземпляром
Reference
или Referenceable
, его соответствующая объектная фабрика может быть расположена, используя информацию в Reference
. getFactoryClassName()
метод получает имя фабрики class, который реализует ObjectFactory
интерфейс. Эта фабрика должна реализовать ObjectFactory
соедините интерфейсом и имейте общедоступного конструктора, который не берет параметров. getFactoryClassLocation()
получает кодовую базу реализации class для фабрики, которая является списком разделенных пробелом URL. JNDI создает объект, вызывая getObjectInstance()
на ObjectFactory
экземпляр, при использовании Reference
и среда как параметры. Результатом является экземпляр class, идентифицированного getClassName()
.
Отметьте, что все классы, необходимые, чтобы инстанцировать объекта, возвращенного к приложению, делаются доступными механизмами использования, обеспеченными JNDI. Приложение не должно установить классы локально.
Рисунок 3: Пример Используя Ссылку, чтобы Возвратить Объект От Пространства имен
Возвращаясь к примеру принтера, предположить Printer
интерфейс для того, чтобы представить принтер и BSDPrinter
class является реализацией того интерфейса. BSDPrinter
реализации Referenceable
интерфейс и использование Reference
class, чтобы хранить информацию на том, как создать экземпляры BSDPrinter
и информация об адресах для того, чтобы связаться с сервером печати. Reference
содержит имя class объекта ("Printer"
), имя class принтера возражают фабрике ("PrinterFactory
") и URL для того, чтобы загрузить реализацию class фабрики. Используя фабрику имя class и расположение реализации, JNDI первые загрузки реализация PrinterFactory
и создает экземпляр PrinterFactory
. Это тогда вызывает getObjectInstance()
на фабрике, чтобы создать экземпляр Printer
использование ссылки. Например, у одного адреса в ссылке может быть адрес типа"bsd
", и содержит имя хоста сервера печати ("lobby-printserver
"). PrinterFactory
экземпляр использует тип адреса ("bsd
"), чтобы решить создать a BSDPrinter
экземпляр и передачи содержание адреса ("lobby-printserver
") его конструктору. Получающееся BSDPrinter
объект возвращается как результат lookup()
.
С точки зрения реализации контекста все это делается автоматически ее вызовом NamingManager
/DirectoryManager.getObjectInstance()
.
Когда приложение вызывает print()
на BSDPrinter
экземпляр, возвращенный lookup()
, данные отправляются серверу печати на машине"lobby-printserver
"для того, чтобы напечатать. Приложение не должно знать детали Reference
сохраненный в пространстве имен, протокол, используемый, чтобы выполнить задание, или ли BSDPrinter
class был определен локально или загружался по сети. Преобразование информации, хранившей в базовой службе в объект, который реализует Printer
интерфейс делается прозрачно через сотрудничество поставщика услуг (который хранит привязку имен принтера к информации об адресах принтера), поставщик услуг принтера (который обеспечивает PrinterFactory
и BSDPrinter
классы), и платформа SPI JNDI (который связывает два, чтобы возвратить объект, который приложение может использовать непосредственно).
Поставщик услуг для такого объекта должен сделать следующее:
BSDPrinter
) это реализует Referenceable
или подкласс Reference
. Reference
и его ссылка адресуется для объекта. ObjectFactory
(например, PrinterFactory
). Этот class getObjectInstance()
метод создаст экземпляр class от шага 1 (например, BSDPrinter
) когда дано Reference
от шага 2. Если a Reference
содержит адрес типа "URL", но не фабрика название и местоположение class, или если ссылка будет массивом строк, содержащих URL, то JNDI будет использовать поддержку фабрики контекста URL, описанную в Разделе 3.2, чтобы определить местоположение фабрики, и затем передать строку URL в адресе к фабрике getObjectInstance()
метод. См. Раздел 4.1.6 для описания того, как JNDI ожидает, что реализация фабрики контекста URL будет вести себя.
Поставщик услуг для такого объекта должен сделать следующее:
BSDPrinter
). ObjectFactory
. Этот class getObjectInstance()
метод создаст экземпляр class от шага 1 (например, BSDPrinter
) когда дано URL от шага 2. В дополнение к извлечению информации о фабрике от Reference
s, или использование URL, JNDI также ищет объектные фабрики, определенные в java.naming.factory.object
свойство, которое может быть в среде или файле ресурсов провайдера (см. Раздел 2.9.5). Свойство содержит разделенный от двоеточия список полностью определенных имен class объектных фабрик. Каждый class должен реализовать ObjectFactory
соедините интерфейсом и имейте общедоступного конструктора, который не берет параметров. Для каждого class в списке JNDI пытается загрузить и инстанцировать фабрики class, и вызвать ObjectFactory/DirObjectFactory.getObjectInstance()
метод на этом использующий объект и параметры среды предоставляется. Если создание успешно, получающийся объект возвращается; иначе, JNDI использует ту же самую процедуру на следующем class в списке, пока список не исчерпывается, или фабрика возвращается не -null
результат.
Рисунок 4: Пример используя java.naming.factory.object, чтобы Возвратить Объект от Пространства имен
Для примера принтера, вместо того, чтобы использовать a Reference
чтобы представить принтер в пространстве имен, некоторая другая информация хранится. Когда та информация позже получается, объектные определенные фабрики java.naming.factory.object
пробуются поочередно, чтобы попытаться превратить ту информацию в a Printer
экземпляр.
Поставщик услуг для такого объекта должен сделать следующее:
BSDPrinter
). Reference
. Это может быть что-либо, что будет понято под ее соответствующей объектной фабрикой (например, некоторая строка, содержащая имя сервера"printer type=bsd; host=lobby-printserver
"). ObjectFactory
(например, PrinterFactory
). Этот class getObjectInstance()
метод создаст экземпляр class от шага 1 (например, BSDPrinter
) когда приведено пример class от шага 2 (например,"printer type=bsd; host=lobby-printserver
"). Поставщик услуг должен автоматически преобразовать между фактическим объектом (например, BSDPrinter
) и информация о ссылке (шаг 2, например,"printer type=bsd; host=lobby-printserver
"), связывая или ища объект.
Приложение, которое хочет использовать определенную фабрику для того, чтобы генерировать объекты, должно включать имя class фабрики в java.naming.factory.object
свойство среды и делает классы фабрики и классы объектов доступными.
Объектным разработчиком фабрики является class, который создает экземпляры объектных фабрик.
Приложение может установить объектного разработчика фабрики к определению ее собственной политики того, как определить местоположение и создать объектные реализации фабрики. Когда разработчик был установлен, это исключительно ответственно за создание объектных фабрик. Ни одна из политик значения по умолчанию (Reference
, Строка URL, или java.naming.factory.object
свойство), обычно используемый JNDI используются.
Рисунок 5: Пример используя Объектного Разработчика Фабрики, чтобы Возвратить Объект из Namespece
Поставщик услуг для объектного разработчика фабрики должен сделать следующее:
ObjectFactory
. ObjectFactoryBuilder
. Этот class createObjectFactory()
метод будет использовать конструкторов для ObjectFactory
классы в шаге 1.Приложение, которое хочет использовать этого разработчика фабрики, должно сначала установить это.
NamingManager.setObjectFactoryBuilder(builder);
Фабрика контекста является объектной фабрикой, которая создает экземпляры Context
. Реализация этих контекстов для определенного именования или службы каталогов упоминается как реализация контекста. Реализации контекста описываются в Главе 2. Как любая другая объектная фабрика, фабрика контекста может быть получена при использовании любого из этих трех механизмов, описанных выше: от a Reference
, идентификатор схемы URL, или перечисленный в java.naming.factory.object
свойство.
Фабрика контекста URL является специальным видом фабрики контекста. Это следует за этими правилами, реализовывая ObjectFactory.getObjectInstance()
.
refObj
null
, создайте контекст для того, чтобы разрешить URL схемы, связанной с этой фабрикой. Получающийся контекст не связывается к определенному URL. Например, вызов
getObjectInstance(null, null, null, env)
ldap://ldap.wiz.com/o=wiz,c=us
"или"ldap://ldap.umich.edu/
", ...).
refObj
строка URL, создайте объект, идентифицированный URL. Например, вызовgetObjectInstance("ldap://ldap.wiz.com/o=wiz,c=us", null, null, env);
o=wiz,c=us
"на сервере LDAP ldap.wiz.com
. Если это, оказывается, называет контекст, он может тогда использоваться для того, чтобы разрешить (относительные) имена LDAP (например,"cn=Jane Smith
"). refObj
массив строк URL, предположение - то, что URL эквивалентны с точки зрения контекста, к которому они обращаются. Проверка того, являются ли URL, или должны быть, эквивалентны, до фабрики контекста. Порядок URL в массиве не является существенным. Объект, возвращенный getObjectInstance()
то же самое как это для единственного случая URL - это - объект (возможно, контекст) названный URL. refObj
любой другой тип, поведение getObjectInstance()
определяется реализацией. Фабрики контекста URL используются InitialContext
class, когда это передают URL, чтобы решить. Фабрики контекста URL также используются для того, чтобы создать объекты в языке программирования Java от URL, сохраненных в пространстве имен (см. Раздел 4.1.2).
JNDI обеспечивает механизм, чтобы преобразовать объект в форму storable базовой реализацией контекста. Та форма может быть любым произвольным типом, приемлемым для базовой реализации контекста. Например, это может быть a Reference
, URL, a Serializable
объект, или ряд атрибутов, или любых других данных, приемлемых базовой реализацией контекста. Превращение произвольного объекта в данные, которые могут храниться в пространстве имен, поддерживается с помощью фабрик состояния. Фабрикой состояния является class, который реализует StateFactory
интерфейс (или DirStateFactory
подынтерфейс):
public interface StateFactory { public Object getStateToBind(Object obj, Name name, Context nameCtx, Hashtable env) throws NamingException; } public interface DirStateFactory { public DirStateFactory.Result getStateToBind(Object obj, Name name, Context nameCtx, Hashtable env, Attributes attrs) throws NamingException; }Учитывая объект (
obj
), дополнительная информация об имени объекта и где это связывается, и дополнительно некоторая дополнительная информация о среде (например, некоторые идентификационные данные или информация об аутентификации о пользователе, получающем доступ к пространству имен), фабрика, пытается создать объект, подходящий для того, чтобы связать. Как правило, фабрика состояния хорошо осведомлена о целевом именовании/службе каталогов и/или реализации контекста, и знает, какие форматы данных являются приемлемыми. В случае фабрики состояния, которая должна использоваться с a DirContext
реализация, фабрике также дают некоторые атрибуты, которые должны быть сохранены объектом. Если фабрика запрашивает больше информации об объекте, это может получить их непосредственно из именования/службы каталогов при использовании name
/nameCtx
параметры. Например, фабрика состояния принтера для каталога LDAP могла бы возвратить ряд атрибутов, которые представляют принтер. Если фабрика не может возвратить данные, используя предоставленные параметры, это должно возвратиться null
. Например, когда фабрике состояния принтера дают дисковый объект, она должна возвратиться null
. Фабрика должна только выданный исключение, если никакие другие фабрики состояния нельзя попробовать. Поэтому, фабрика должна быть осторожной относительно исключений, которые могли бы быть выданы от ее реализации. Например, если фабрике состояния принтера дают объект принтера, но возможно противоречащие атрибуты, она могла бы выдать исключение.
В конечном счете выходные форматы фабрики определяются базовым именованием/службой каталогов. Реализация контекста для Служб Объекта CORBA (COS) служба именования, например, может только сохранить ссылки на объект CORBA в службу; реализация контекста для LDAP может только сохранить атрибуты, хотя есть большая гибкость в том, как закодировать информацию в пределах тех атрибутов.
Поставщик услуг обычно предоставляет фабрику для каждого (общего) типа ввода, который это ожидает, и приложение может увеличить тот набор с собственными фабриками состояния. Например, у поставщика услуг для именования COS могла бы быть фабрика состояния для того, чтобы преобразовать Java Удаленный Вызов метода (RMI) объект в ссылку на объект CORBA. Пользователь того провайдера мог бы добавить фабрику состояния для того, чтобы преобразовать ссылку COM-объекта Microsoft в ссылку на объект CORBA.
JNDI ищет фабрики состояния, определенные в java.naming.factory.state
свойство, которое может быть в среде или файле ресурсов провайдера (см. Раздел 2.9.5). Свойство содержит разделенный от двоеточия список полностью определенных имен class фабрик состояния. Каждый class должен реализовать StateFactory
соедините интерфейсом и имейте общедоступного конструктора, который не берет параметров. Для каждого class в списке JNDI пытается загрузить и инстанцировать фабрики class, и вызвать StateFactory/DirStateFactory.getStateToBind()
метод на этом использующий объект, имя, контекст, среду, и параметры атрибутов предоставляется. Если фабрика производит не -null
результат, результат возвращается; иначе, JNDI использует ту же самую процедуру на следующем class в списке, пока список не исчерпывается, или фабрика возвращается не -null
результат.
LDAP v3 протокол позволяет средствам управления ответом сопровождать любой ответ, отправленный сервером. Управление состоит из строкового идентификатора OID и последовательности BER ASN.1 закодированные байты. В отсутствие любой внешней информации или помощи, реализация контекста может только возвратить простую реализацию Control
интерфейс, который возвращает OID и байты.
JNDI обеспечивает следующий абстрактный class для того, чтобы он имел дело со средствами управления ответом:
public abstract javax.naming.ldap.ControlFactory { ... public static Control getControlInstance(Control ctl, Context ctx, Hashtable env) throws NamingException; public abstract Control getControlInstance(Control ctl) throws NamingException; }Когда реализация контекста получает управление ответом, она вызывает помехи
getControl-Instance()
метод, чтобы найти фабрику управления, которая может сузить управление к тому, у которого есть больше удобных для пользователя методов доступа. Такое управление, например, может декодировать байты BER ASN.1 и обеспечить методы доступа, которые возвращают информацию как типы Java. Если никакая такая фабрика управления не может быть найдена, исходное управление ответом возвращается. Вот пример гипотетического Time-ResponseControl
который декодирует время суток. public class TimeResponseControl implements Control { long time; // Constructor used by ControlFactory public TimeResponseControl(String OID, byte[] berVal) throws NamingException { // check validity of OID time = // extract time from berVal }; // Type-safe and User-friendly method public long getTime() { return time; } // Low-level methods public String getID() { return TIME_OID; } public byte[] getEncodedValue() { return // original berVal } ... }Фабрика управления может быть ответственной за одни или более средств управления. Если фабрика не может возвратить управление, используя предоставленные параметры, она должна возвратиться
null
. Как правило, это включает только соответствие OID управления против списка OID, поддерживаемых фабрикой. Фабрика должна только выданный исключение, если никакие другие фабрики управления нельзя попробовать. Поэтому, фабрика должна быть осторожной относительно исключений, которые могли бы быть выданы от ее реализации. Например, если фабрика управления дается контроль с OID, который она поддерживает, но у байтового массива есть ошибка кодирования, она должна выдать исключение. Вот пример фабрики управления:
public class VendorXControlFactory extends ControlFactory { public VendorXControlFactory () { } public Control getControlInstance(Control orig) throws NamingException { if (isOneOfMyControls(orig.getID())) { ... // determine which of ours it is and call its constructor return new TimeResponseControl(orig.getID(), orig.getEncodedValue()); } return null; // not one of ours } }
JNDI ищет фабрики управления ответом, определенные в java.naming.factory.control
свойство, которое может быть в среде или файле ресурсов провайдера (см. Раздел 2.9.5). Свойство содержит разделенный от двоеточия список полностью определенных имен class фабрик управления. Каждый class должен реализовать ControlFactory
соедините интерфейсом и имейте общедоступного конструктора, который не берет параметров. Для каждого class в списке JNDI пытается загрузить и инстанцировать фабрики class, и вызвать ControlFactory.getControlInstance()
метод экземпляра для этого использующий управление, контекст, и параметры среды предоставляется. Если фабрика производит не -null
результат, результат возвращается; иначе, JNDI использует ту же самую процедуру на следующем class в списке, пока список не исчерпывается, или фабрика возвращается не -null
результат.
Любой объект, который передают в качестве параметра к методу на фабрике, принадлежит вызывающей стороне. Поэтому, фабрике мешают поддержать указатель на объект вне продолжительности работы или изменить объект. Если фабрика должна сохранить информацию, содержавшуюся в параметре вне продолжительности работы, это должно поддержать свою собственную копию.
Экземпляр фабрики должен быть повторно используемым. Таким образом, для многократных потоков должно быть возможно вызвать методы на единственный экземпляр фабрики одновременно.
CannotProceedException
май хорошо был брошен одним из внутренних методов контекста, когда это обнаружило, что обрабатываемое имя выходит за рамки его системы именования. Процесс, которым производится исключение, зависит от реализации контекста. 3
Примечания, что это - код в приложении. В "Продолжении Работы в Федерации", представленный пример кода является кодом в реализации контекста. 4 можно также использовать подкласс Хеш-таблицы (например, Свойства) для этого. 5 упоминание о "URL" в этом документе обращается к строке URL как определено RFC 1738 и его связанным RFCs. Именно любая строка соответствует синтаксису, описанному там, и, возможно, не всегда имеет соответствующей поддержки в java.net.URL
class или Веб-браузеры. Строку URL или передают как String
параметр имени, или как первый компонент Name
параметр.