include sdk.mk
-.PHONY: clean all osgi jni
+.PHONY: clean all osgi
all: osgi
$(MAKE) -f Makefile-rcp.mk all
BUNDLES = \
org.argeo.init \
-org.argeo.util \
org.argeo.api.uuid \
+org.argeo.api.register \
org.argeo.api.acr \
org.argeo.api.cli \
org.argeo.api.cms \
org.argeo.cms.ux \
org.argeo.cms.ee \
org.argeo.cms.lib.jetty \
-org.argeo.cms.lib.equinox \
org.argeo.cms.lib.sshd \
-org.argeo.cms.lib.pgsql \
org.argeo.cms.cli \
+osgi/equinox/org.argeo.cms.lib.equinox \
swt/org.argeo.swt.minidesktop \
swt/org.argeo.cms.swt \
swt/org.argeo.cms.e4 \
swt/rap/org.argeo.swt.specific.rap \
swt/rap/org.argeo.cms.swt.rap \
-swt/rap/org.argeo.cms.swt.rap.cli \
swt/rap/org.argeo.cms.e4.rap \
DEP_CATEGORIES = \
org.argeo.tp \
-org.argeo.tp.apache \
+org.argeo.tp.crypto \
org.argeo.tp.jetty \
osgi/api/org.argeo.tp.osgi \
osgi/equinox/org.argeo.tp.eclipse \
org.argeo.api.acr \
org.argeo.api.cms
-jni:
- $(MAKE) -C jni
-
clean:
rm -rf $(BUILD_BASE)
- $(MAKE) -C jni clean
$(MAKE) -f Makefile-rcp.mk clean
A2_BUNDLES_CLASSPATH = $(subst $(space),$(pathsep),$(strip $(A2_BUNDLES)))
-native-image:
- mkdir -p $(A2_OUTPUT)/libexec/$(A2_CATEGORY)
-# cd $(A2_OUTPUT)/libexec/$(A2_CATEGORY) && /opt/graalvm-ce/bin/native-image \
- -cp $(A2_CLASSPATH):$(A2_BUNDLES_CLASSPATH) org.argeo.eclipse.ui.jetty.CmsRapCli \
- --enable-url-protocols=http,https \
- -H:AdditionalSecurityProviders=sun.security.jgss.SunProvider,org.bouncycastle.jce.provider.BouncyCastleProvider,net.i2p.crypto.eddsa.EdDSASecurityProvider \
- --initialize-at-build-time=org.argeo.init.logging.ThinLogging,org.slf4j.LoggerFactory \
- --no-fallback
- cd $(A2_OUTPUT)/libexec/$(A2_CATEGORY) && /opt/graalvm-ce/bin/native-image \
- -cp $(A2_CLASSPATH):$(A2_BUNDLES_CLASSPATH) org.argeo.cms.ux.cli.FileSync \
- --initialize-at-build-time=org.argeo.init.logging.ThinLogging,org.slf4j.LoggerFactory \
- --no-fallback
-
-
include $(SDK_SRC_BASE)/sdk/argeo-build/osgi.mk
\ No newline at end of file
all: osgi
-move-rcp: osgi
- mkdir -p $(A2_OUTPUT)/swt/rcp/$(A2_CATEGORY)
- mv -v $(A2_OUTPUT)/$(A2_CATEGORY)/*.rcp.$(MAJOR).$(MINOR).jar $(A2_OUTPUT)/swt/rcp/$(A2_CATEGORY)
- mv -v $(A2_OUTPUT)/$(A2_CATEGORY)/*.rcp.cli.$(MAJOR).$(MINOR).jar $(A2_OUTPUT)/swt/rcp/$(A2_CATEGORY)
- #touch $(BUILD_BASE)/*.rcp/bnd.bnd
-
A2_CATEGORY = org.argeo.cms
BUNDLES = \
swt/rcp/org.argeo.swt.specific.rcp \
swt/rcp/org.argeo.cms.swt.rcp \
-swt/rcp/org.argeo.cms.swt.rcp.cli \
swt/rcp/org.argeo.cms.e4.rcp \
-A2_OUTPUT = $(SDK_BUILD_BASE)/a2
-A2_BASE = $(A2_OUTPUT)
-
DEP_CATEGORIES = \
org.argeo.cms \
swt/org.argeo.cms \
org.argeo.tp \
-org.argeo.tp.apache \
+org.argeo.tp.crypto \
org.argeo.tp.jetty \
osgi/equinox/org.argeo.tp.eclipse \
osgi/api/org.argeo.tp.osgi \
swt/rcp/org.argeo.tp.swt \
lib/linux/x86_64/swt/rcp/org.argeo.tp.swt \
swt/rcp/org.argeo.tp.swt.workbench \
-org.argeo.tp.jcr
clean:
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
- <storageModule moduleId="org.eclipse.cdt.core.settings">
- <cconfiguration id="cdt.managedbuild.toolchain.gnu.cross.base.1367283591">
- <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.cross.base.1367283591" moduleId="org.eclipse.cdt.core.settings" name="Linux x86_64">
- <externalSettings/>
- <extensions>
- <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
- <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
- </extensions>
- </storageModule>
- <storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.cross.base.1367283591" name="Linux x86_64" parent="org.eclipse.cdt.build.core.emptycfg">
- <folderInfo id="cdt.managedbuild.toolchain.gnu.cross.base.1367283591.350590933" name="/" resourcePath="">
- <toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.2019979628" name="Cross GCC">
- <option id="cdt.managedbuild.option.gnu.cross.prefix.715257330" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
- <option id="cdt.managedbuild.option.gnu.cross.path.1210265928" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path"/>
- <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.cross.2070205849" isAbstract="false" osList="all"/>
- <builder enableAutoBuild="true" id="cdt.managedbuild.builder.gnu.cross.1468217036" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder"/>
- </toolChain>
- </folderInfo>
- <sourceEntries>
- <entry flags="VALUE_WORKSPACE_PATH" kind="sourcePath" name="org_argeo_api_uuid_libuuid"/>
- </sourceEntries>
- </configuration>
- </storageModule>
- <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
- </cconfiguration>
- </storageModule>
- <storageModule moduleId="cdtBuildSystem" version="4.0.0">
- <project id="org.argeo.api.uuid.null.1913821562" name="org.argeo.api.uuid"/>
- </storageModule>
- <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
- <storageModule moduleId="refreshScope" versionNumber="2">
- <configuration configurationName="Linux x86_64"/>
- <configuration configurationName="Default">
- <resource resourceType="PROJECT" workspacePath="/Java_org_argeo_api_uuid"/>
- </configuration>
- </storageModule>
- <storageModule moduleId="scannerConfiguration">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
- <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1367283591;cdt.managedbuild.toolchain.gnu.cross.base.1367283591.350590933;cdt.managedbuild.tool.gnu.cross.c.compiler.453851306;cdt.managedbuild.tool.gnu.c.compiler.input.1102448447">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
- </scannerConfigBuildInfo>
- <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.cross.base.1367283591;cdt.managedbuild.toolchain.gnu.cross.base.1367283591.350590933;cdt.managedbuild.tool.gnu.cross.cpp.compiler.365551368;cdt.managedbuild.tool.gnu.cpp.compiler.input.916135861">
- <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
- </scannerConfigBuildInfo>
- </storageModule>
- <storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
- <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
- <buildTargets>
- <target name="ide" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
- <buildCommand>make</buildCommand>
- <buildArguments/>
- <buildTarget>ide</buildTarget>
- <stopOnError>true</stopOnError>
- <useDefaultCommand>true</useDefaultCommand>
- <runAllBuilders>true</runAllBuilders>
- </target>
- </buildTargets>
- </storageModule>
-</cproject>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>jni-commons</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
- <triggers>full,incremental,</triggers>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.cdt.core.cnature</nature>
- <nature>org.eclipse.cdt.core.ccnature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
- <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<project>
- <configuration id="cdt.managedbuild.toolchain.gnu.cross.base.1367283591" name="Linux x86_64">
- <extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
- <provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
- <provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
- <provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
- <provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
- </extension>
- </configuration>
-</project>
\ No newline at end of file
+++ /dev/null
-doxygen/doxygen_new_line_after_brief=true
-doxygen/doxygen_use_brief_tag=false
-doxygen/doxygen_use_javadoc_tags=true
-doxygen/doxygen_use_pre_tag=false
-doxygen/doxygen_use_structural_commands=false
-eclipse.preferences.version=1
+++ /dev/null
-include ../sdk.mk
-
-JNIDIRS = org_argeo_api_uuid_libuuid
-
-.PHONY: clean all
-
-all:
- $(foreach dir, $(JNIDIRS), $(MAKE) -C $(dir);)
-
-clean:
- rm -rf $(BUILD_DIR) $(SDK_BUILD_BASE)/jni
-
-
-
+++ /dev/null
-TARGET_EXEC := libJava_$(NATIVE_PACKAGE).so
-
-LDFLAGS = -shared -fPIC -Wl,-soname,$(TARGET_EXEC).$(MAJOR).$(MINOR) $(ADDITIONAL_LIBS)
-CFLAGS = -O3 -fPIC
-
-SRC_DIRS := .
-
-#
-# Generic Argeo
-#
-BUILD_DIR := $(SDK_BUILD_BASE)/jni/$(NATIVE_PACKAGE)
-
-# Every folder in ./src will need to be passed to GCC so that it can find header files
-INC_DIRS := $(shell find $(SRC_DIRS) -type d) $(JAVA_HOME)/include $(JAVA_HOME)/include/linux $(ADDITIONAL_INCLUDES)
-
-
-.PHONY: clean all ide
-all: $(SDK_BUILD_BASE)/jni/$(TARGET_EXEC)
-
-# Find all the C and C++ files we want to compile
-# Note the single quotes around the * expressions. Make will incorrectly expand these otherwise.
-SRCS := $(shell find $(SRC_DIRS) -name '*.cpp' -or -name '*.c' -or -name '*.s')
-
-# String substitution for every C/C++ file.
-# As an example, hello.cpp turns into ./build/hello.cpp.o
-OBJS := $(SRCS:%=$(BUILD_DIR)/%.o)
-
-# String substitution (suffix version without %).
-# As an example, ./build/hello.cpp.o turns into ./build/hello.cpp.d
-DEPS := $(OBJS:.o=.d)
-
-# Add a prefix to INC_DIRS. So moduleA would become -ImoduleA. GCC understands this -I flag
-INC_FLAGS := $(addprefix -I,$(INC_DIRS))
-
-# The -MMD and -MP flags together generate Makefiles for us!
-# These files will have .d instead of .o as the output.
-CPPFLAGS := $(INC_FLAGS) -MMD -MP
-
-# The final build step.
-$(SDK_BUILD_BASE)/jni/$(TARGET_EXEC): $(OBJS)
- $(CC) $(OBJS) -o $@ $(LDFLAGS)
-
-# Build step for C source
-$(BUILD_DIR)/%.c.o: %.c
- mkdir -p $(dir $@)
- $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
-
-# Build step for C++ source
-$(BUILD_DIR)/%.cpp.o: %.cpp
- mkdir -p $(dir $@)
- $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
-
-# Include the .d makefiles. The - at the front suppresses the errors of missing
-# Makefiles. Initially, all the .d files will be missing, and we don't want those
-# errors to show up.
--include $(DEPS)
-
-# MAKEFILE_DIR := $(dir $(firstword $(MAKEFILE_LIST)))
+++ /dev/null
-NATIVE_PACKAGE := org_argeo_api_uuid_libuuid
-
-ADDITIONAL_INCLUDES = /usr/include/uuid
-ADDITIONAL_LIBS = -luuid
-
-include ../../sdk.mk
-include ../jni.mk
-
+++ /dev/null
-#include <jni.h>
-#include <uuid.h>
-#include "org_argeo_api_uuid_libuuid_DirectLibuuidFactory.h"
-
-JNIEXPORT void JNICALL Java_org_argeo_api_uuid_libuuid_DirectLibuuidFactory_timeUUID(
- JNIEnv *env, jobject uuidFactory, jobject uuidBuf) {
- uuid_generate_time((*env)->GetDirectBufferAddress(env, uuidBuf));
-}
+++ /dev/null
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_argeo_api_uuid_libuuid_DirectLibuuidFactory */
-
-#ifndef _Included_org_argeo_api_uuid_libuuid_DirectLibuuidFactory
-#define _Included_org_argeo_api_uuid_libuuid_DirectLibuuidFactory
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: org_argeo_api_uuid_libuuid_DirectLibuuidFactory
- * Method: timeUUID
- * Signature: (Ljava/nio/ByteBuffer;)V
- */
-JNIEXPORT void JNICALL Java_org_argeo_api_uuid_libuuid_DirectLibuuidFactory_timeUUID
- (JNIEnv *, jobject, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+++ /dev/null
-#include <jni.h>
-#include <uuid.h>
-#include "org_argeo_api_uuid_libuuid_LibuuidFactory.h"
-
-/*
- * UTILITIES
- */
-
-static inline jobject fromBytes(JNIEnv *env, uuid_t out) {
- jlong msb = 0;
- jlong lsb = 0;
-
- for (int i = 0; i < 8; i++)
- msb = (msb << 8) | (out[i] & 0xff);
- for (int i = 8; i < 16; i++)
- lsb = (lsb << 8) | (out[i] & 0xff);
-
- jclass uuidClass = (*env)->FindClass(env, "java/util/UUID");
- jmethodID uuidConstructor = (*env)->GetMethodID(env, uuidClass, "<init>",
- "(JJ)V");
-
- jobject jUUID = (*env)->AllocObject(env, uuidClass);
- (*env)->CallVoidMethod(env, jUUID, uuidConstructor, msb, lsb);
-
- return jUUID;
-}
-
-static inline void toBytes(JNIEnv *env, jobject jUUID, uuid_t result) {
-
- jclass uuidClass = (*env)->FindClass(env, "java/util/UUID");
- jmethodID getMostSignificantBits = (*env)->GetMethodID(env, uuidClass,
- "getMostSignificantBits", "()J");
- jmethodID getLeastSignificantBits = (*env)->GetMethodID(env, uuidClass,
- "getLeastSignificantBits", "()J");
-
- jlong msb = (*env)->CallLongMethod(env, jUUID, getMostSignificantBits);
- jlong lsb = (*env)->CallLongMethod(env, jUUID, getLeastSignificantBits);
-
- for (int i = 0; i < 8; i++)
- result[i] = (unsigned char) ((msb >> ((7 - i) * 8)) & 0xff);
- for (int i = 8; i < 16; i++)
- result[i] = (unsigned char) ((lsb >> ((15 - i) * 8)) & 0xff);
-}
-
-/*
- * JNI IMPLEMENTATION
- */
-
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_timeUUID(
- JNIEnv *env, jobject uuidFactory) {
- uuid_t out;
-
- uuid_generate_time(out);
- return fromBytes(env, out);
-}
-
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_nameUUIDv5(
- JNIEnv *env, jobject uuidFactory, jobject namespaceUuid,
- jbyteArray name) {
- uuid_t ns;
- uuid_t out;
-
- toBytes(env, namespaceUuid, ns);
- jsize length = (*env)->GetArrayLength(env, name);
- jbyte *bytes = (*env)->GetByteArrayElements(env, name, 0);
-
- uuid_generate_sha1(out, ns, bytes, length);
- return fromBytes(env, out);
-}
-
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_nameUUIDv3(
- JNIEnv *env, jobject uuidFactory, jobject namespaceUuid,
- jbyteArray name) {
- uuid_t ns;
- uuid_t out;
-
- toBytes(env, namespaceUuid, ns);
- jsize length = (*env)->GetArrayLength(env, name);
- jbyte *bytes = (*env)->GetByteArrayElements(env, name, 0);
-
- uuid_generate_md5(out, ns, bytes, length);
- return fromBytes(env, out);
-}
-
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_randomUUIDStrong(
- JNIEnv *env, jobject uuidFactory) {
- uuid_t out;
-
- uuid_generate_random(out);
- return fromBytes(env, out);
-}
+++ /dev/null
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class org_argeo_api_uuid_libuuid_LibuuidFactory */
-
-#ifndef _Included_org_argeo_api_uuid_libuuid_LibuuidFactory
-#define _Included_org_argeo_api_uuid_libuuid_LibuuidFactory
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class: org_argeo_api_uuid_libuuid_LibuuidFactory
- * Method: timeUUID
- * Signature: ()Ljava/util/UUID;
- */
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_timeUUID
- (JNIEnv *, jobject);
-
-/*
- * Class: org_argeo_api_uuid_libuuid_LibuuidFactory
- * Method: nameUUIDv5
- * Signature: (Ljava/util/UUID;[B)Ljava/util/UUID;
- */
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_nameUUIDv5
- (JNIEnv *, jobject, jobject, jbyteArray);
-
-/*
- * Class: org_argeo_api_uuid_libuuid_LibuuidFactory
- * Method: nameUUIDv3
- * Signature: (Ljava/util/UUID;[B)Ljava/util/UUID;
- */
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_nameUUIDv3
- (JNIEnv *, jobject, jobject, jbyteArray);
-
-/*
- * Class: org_argeo_api_uuid_libuuid_LibuuidFactory
- * Method: randomUUIDStrong
- * Signature: ()Ljava/util/UUID;
- */
-JNIEXPORT jobject JNICALL Java_org_argeo_api_uuid_libuuid_LibuuidFactory_randomUUIDStrong
- (JNIEnv *, jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
--- /dev/null
+package org.argeo.api.acr;
+
+/** Namespaces declared by Argeo. */
+public enum ArgeoNamespace {
+ ;
+
+ public final static String CR_NAMESPACE_URI = "http://www.argeo.org/ns/cr";
+ public final static String CR_DEFAULT_PREFIX = "cr";
+ public final static String LDAP_NAMESPACE_URI = "http://www.argeo.org/ns/ldap";
+ public final static String LDAP_DEFAULT_PREFIX = "ldap";
+ public final static String ROLE_NAMESPACE_URI = "http://www.argeo.org/ns/role";
+ public final static String ROLE_DEFAULT_PREFIX = "role";
+
+}
return true;
}
+ /** AND */
+ default boolean isContentClass(QNamed... contentClass) {
+ List<QName> lst = new ArrayList<>();
+ for (QNamed qNamed : contentClass)
+ lst.add(qNamed.qName());
+ return isContentClass(lst.toArray(new QName[lst.size()]));
+ }
+
/** OR */
default boolean hasContentClass(QName... contentClass) {
List<QName> contentClasses = getContentClasses();
return false;
}
- default boolean hasContentClass(QNamed contentClass) {
- return hasContentClass(contentClass.qName());
+ /** OR */
+ default boolean hasContentClass(QNamed... contentClass) {
+ List<QName> lst = new ArrayList<>();
+ for (QNamed qNamed : contentClass)
+ lst.add(qNamed.qName());
+ return hasContentClass(lst.toArray(new QName[lst.size()]));
}
/*
// we do not support short and float, like recent additions to Java
// (e.g. optional primitives)
DATE_TIME(Instant.class, W3C_XML_SCHEMA_NS_URI, "dateTime", new InstantFormatter()), //
- UUID(UUID.class, CrName.CR_NAMESPACE_URI, "uuid", new UuidFormatter()), //
+ UUID(UUID.class, ArgeoNamespace.CR_NAMESPACE_URI, "uuid", new UuidFormatter()), //
ANY_URI(URI.class, W3C_XML_SCHEMA_NS_URI, "anyUri", new UriFormatter()), //
STRING(String.class, W3C_XML_SCHEMA_NS_URI, "string", new StringFormatter()), //
;
//
;
- public final static String CR_NAMESPACE_URI = "http://www.argeo.org/ns/cr";
- public final static String CR_DEFAULT_PREFIX = "cr";
-
- public final static String LDAP_NAMESPACE_URI = "http://www.argeo.org/ns/ldap";
- public final static String LDAP_DEFAULT_PREFIX = "ldap";
-
- public final static String ROLE_NAMESPACE_URI = "http://www.argeo.org/ns/role";
- public final static String ROLE_DEFAULT_PREFIX = "role";
+
// private final ContentName value;
@Override
public String getNamespace() {
- return CR_NAMESPACE_URI;
+ return ArgeoNamespace.CR_NAMESPACE_URI;
}
@Override
public String getDefaultPrefix() {
- return CR_DEFAULT_PREFIX;
+ return ArgeoNamespace.CR_DEFAULT_PREFIX;
}
}
register(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, XSD_INSTANCE_DEFAULT_PREFIX);
// Argeo specific
- register(CrName.CR_NAMESPACE_URI, CrName.CR_DEFAULT_PREFIX);
- register(CrName.LDAP_NAMESPACE_URI, CrName.LDAP_DEFAULT_PREFIX);
- register(CrName.ROLE_NAMESPACE_URI, CrName.ROLE_DEFAULT_PREFIX);
+ register(ArgeoNamespace.CR_NAMESPACE_URI, ArgeoNamespace.CR_DEFAULT_PREFIX);
+ register(ArgeoNamespace.LDAP_NAMESPACE_URI, ArgeoNamespace.LDAP_DEFAULT_PREFIX);
+ register(ArgeoNamespace.ROLE_NAMESPACE_URI, ArgeoNamespace.ROLE_DEFAULT_PREFIX);
}
public static NamespaceContext getNamespaceContext() {
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+/**
+ * An object that can be identified with an X.500 distinguished name.
+ *
+ * @see "https://tools.ietf.org/html/rfc1779"
+ */
+public interface Distinguished {
+ /** The related distinguished name. */
+ String dn();
+
+ /** The related distinguished name as an {@link LdapName}. */
+ default LdapName distinguishedName() {
+ try {
+ return new LdapName(dn());
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Distinguished name " + dn() + " is not properly formatted.", e);
+ }
+ }
+
+ /** List all DNs of an enumeration as strings. */
+ static Set<String> enumToDns(EnumSet<? extends Distinguished> enumSet) {
+ Set<String> res = new TreeSet<>();
+ for (Enum<? extends Distinguished> enm : enumSet) {
+ res.add(((Distinguished) enm).dn());
+ }
+ return res;
+ }
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+import java.util.Locale;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.Content;
+import org.argeo.api.acr.ContentName;
+
+/** Utilities around ACR and LDAP conventions. */
+public class LdapAcrUtils {
+
+ /** singleton */
+ private LdapAcrUtils() {
+ }
+
+ public static Object getLocalized(Content content, QName key, Locale locale) {
+ if (locale == null)
+ throw new IllegalArgumentException("A locale must be specified");
+ Object value = null;
+ if (locale.getCountry() != null && !locale.getCountry().equals(""))
+ value = content.get(new ContentName(key.getNamespaceURI(),
+ key.getLocalPart() + ";lang-" + locale.getLanguage() + "-" + locale.getCountry()));
+ if (value == null)
+ value = content
+ .get(new ContentName(key.getNamespaceURI(), key.getLocalPart() + ";lang-" + locale.getLanguage()));
+ if (value == null)
+ value = content.get(key);
+ return value;
+ }
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+import static org.argeo.api.acr.ArgeoNamespace.LDAP_DEFAULT_PREFIX;
+import static org.argeo.api.acr.ArgeoNamespace.LDAP_NAMESPACE_URI;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ContentName;
+import org.argeo.api.acr.QNamed;
+import org.argeo.api.acr.RuntimeNamespaceContext;
+
+/**
+ * Standard LDAP attributes as per:<br>
+ * - <a href= "https://www.ldap.com/ldap-oid-reference">Standard LDAP</a><br>
+ * - <a href=
+ * "https://github.com/krb5/krb5/blob/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema">Kerberos
+ * LDAP (partial)</a>
+ */
+public enum LdapAttr implements QNamed, SpecifiedName {
+ /** */
+ uid("0.9.2342.19200300.100.1.1", "RFC 4519"),
+ /** */
+ mail("0.9.2342.19200300.100.1.3", "RFC 4524"),
+ /** */
+ info("0.9.2342.19200300.100.1.4", "RFC 4524"),
+ /** */
+ drink("0.9.2342.19200300.100.1.5", "RFC 4524"),
+ /** */
+ roomNumber("0.9.2342.19200300.100.1.6", "RFC 4524"),
+ /** */
+ photo("0.9.2342.19200300.100.1.7", "RFC 2798"),
+ /** */
+ userClass("0.9.2342.19200300.100.1.8", "RFC 4524"),
+ /** */
+ host("0.9.2342.19200300.100.1.9", "RFC 4524"),
+ /** */
+ manager("0.9.2342.19200300.100.1.10", "RFC 4524"),
+ /** */
+ documentIdentifier("0.9.2342.19200300.100.1.11", "RFC 4524"),
+ /** */
+ documentTitle("0.9.2342.19200300.100.1.12", "RFC 4524"),
+ /** */
+ documentVersion("0.9.2342.19200300.100.1.13", "RFC 4524"),
+ /** */
+ documentAuthor("0.9.2342.19200300.100.1.14", "RFC 4524"),
+ /** */
+ documentLocation("0.9.2342.19200300.100.1.15", "RFC 4524"),
+ /** */
+ homePhone("0.9.2342.19200300.100.1.20", "RFC 4524"),
+ /** */
+ secretary("0.9.2342.19200300.100.1.21", "RFC 4524"),
+ /** */
+ dc("0.9.2342.19200300.100.1.25", "RFC 4519"),
+ /** */
+ associatedDomain("0.9.2342.19200300.100.1.37", "RFC 4524"),
+ /** */
+ associatedName("0.9.2342.19200300.100.1.38", "RFC 4524"),
+ /** */
+ homePostalAddress("0.9.2342.19200300.100.1.39", "RFC 4524"),
+ /** */
+ personalTitle("0.9.2342.19200300.100.1.40", "RFC 4524"),
+ /** */
+ mobile("0.9.2342.19200300.100.1.41", "RFC 4524"),
+ /** */
+ pager("0.9.2342.19200300.100.1.42", "RFC 4524"),
+ /** */
+ co("0.9.2342.19200300.100.1.43", "RFC 4524"),
+ /** */
+ uniqueIdentifier("0.9.2342.19200300.100.1.44", "RFC 4524"),
+ /** */
+ organizationalStatus("0.9.2342.19200300.100.1.45", "RFC 4524"),
+ /** */
+ buildingName("0.9.2342.19200300.100.1.48", "RFC 4524"),
+ /** */
+ audio("0.9.2342.19200300.100.1.55", "RFC 2798"),
+ /** */
+ documentPublisher("0.9.2342.19200300.100.1.56", "RFC 4524"),
+ /** */
+ jpegPhoto("0.9.2342.19200300.100.1.60", "RFC 2798"),
+ /** */
+ vendorName("1.3.6.1.1.4", "RFC 3045"),
+ /** */
+ vendorVersion("1.3.6.1.1.5", "RFC 3045"),
+ /** */
+ entryUUID("1.3.6.1.1.16.4", "RFC 4530"),
+ /** */
+ entryDN("1.3.6.1.1.20", "RFC 5020"),
+ /** */
+ labeledURI("1.3.6.1.4.1.250.1.57", "RFC 2798"),
+ /** */
+ numSubordinates("1.3.6.1.4.1.453.16.2.103", "draft-ietf-boreham-numsubordinates"),
+ /** */
+ namingContexts("1.3.6.1.4.1.1466.101.120.5", "RFC 4512"),
+ /** */
+ altServer("1.3.6.1.4.1.1466.101.120.6", "RFC 4512"),
+ /** */
+ supportedExtension("1.3.6.1.4.1.1466.101.120.7", "RFC 4512"),
+ /** */
+ supportedControl("1.3.6.1.4.1.1466.101.120.13", "RFC 4512"),
+ /** */
+ supportedSASLMechanisms("1.3.6.1.4.1.1466.101.120.14", "RFC 4512"),
+ /** */
+ supportedLDAPVersion("1.3.6.1.4.1.1466.101.120.15", "RFC 4512"),
+ /** */
+ ldapSyntaxes("1.3.6.1.4.1.1466.101.120.16", "RFC 4512"),
+ /** */
+ supportedAuthPasswordSchemes("1.3.6.1.4.1.4203.1.3.3", "RFC 3112"),
+ /** */
+ authPassword("1.3.6.1.4.1.4203.1.3.4", "RFC 3112"),
+ /** */
+ supportedFeatures("1.3.6.1.4.1.4203.1.3.5", "RFC 4512"),
+ /** */
+ inheritable("1.3.6.1.4.1.7628.5.4.1", "draft-ietf-ldup-subentry"),
+ /** */
+ blockInheritance("1.3.6.1.4.1.7628.5.4.2", "draft-ietf-ldup-subentry"),
+ /** */
+ objectClass("2.5.4.0", "RFC 4512"),
+ /** */
+ aliasedObjectName("2.5.4.1", "RFC 4512"),
+ /** */
+ cn("2.5.4.3", "RFC 4519"),
+ /** */
+ sn("2.5.4.4", "RFC 4519"),
+ /** */
+ serialNumber("2.5.4.5", "RFC 4519"),
+ /** */
+ c("2.5.4.6", "RFC 4519"),
+ /** */
+ l("2.5.4.7", "RFC 4519"),
+ /** */
+ st("2.5.4.8", "RFC 4519"),
+ /** */
+ street("2.5.4.9", "RFC 4519"),
+ /** */
+ o("2.5.4.10", "RFC 4519"),
+ /** */
+ ou("2.5.4.11", "RFC 4519"),
+ /** */
+ title("2.5.4.12", "RFC 4519"),
+ /** */
+ description("2.5.4.13", "RFC 4519"),
+ /** */
+ searchGuide("2.5.4.14", "RFC 4519"),
+ /** */
+ businessCategory("2.5.4.15", "RFC 4519"),
+ /** */
+ postalAddress("2.5.4.16", "RFC 4519"),
+ /** */
+ postalCode("2.5.4.17", "RFC 4519"),
+ /** */
+ postOfficeBox("2.5.4.18", "RFC 4519"),
+ /** */
+ physicalDeliveryOfficeName("2.5.4.19", "RFC 4519"),
+ /** */
+ telephoneNumber("2.5.4.20", "RFC 4519"),
+ /** */
+ telexNumber("2.5.4.21", "RFC 4519"),
+ /** */
+ teletexTerminalIdentifier("2.5.4.22", "RFC 4519"),
+ /** */
+ facsimileTelephoneNumber("2.5.4.23", "RFC 4519"),
+ /** */
+ x121Address("2.5.4.24", "RFC 4519"),
+ /** */
+ internationalISDNNumber("2.5.4.25", "RFC 4519"),
+ /** */
+ registeredAddress("2.5.4.26", "RFC 4519"),
+ /** */
+ destinationIndicator("2.5.4.27", "RFC 4519"),
+ /** */
+ preferredDeliveryMethod("2.5.4.28", "RFC 4519"),
+ /** */
+ member("2.5.4.31", "RFC 4519"),
+ /** */
+ owner("2.5.4.32", "RFC 4519"),
+ /** */
+ roleOccupant("2.5.4.33", "RFC 4519"),
+ /** */
+ seeAlso("2.5.4.34", "RFC 4519"),
+ /** */
+ userPassword("2.5.4.35", "RFC 4519"),
+ /** */
+ userCertificate("2.5.4.36", "RFC 4523"),
+ /** */
+ cACertificate("2.5.4.37", "RFC 4523"),
+ /** */
+ authorityRevocationList("2.5.4.38", "RFC 4523"),
+ /** */
+ certificateRevocationList("2.5.4.39", "RFC 4523"),
+ /** */
+ crossCertificatePair("2.5.4.40", "RFC 4523"),
+ /** */
+ name("2.5.4.41", "RFC 4519"),
+ /** */
+ givenName("2.5.4.42", "RFC 4519"),
+ /** */
+ initials("2.5.4.43", "RFC 4519"),
+ /** */
+ generationQualifier("2.5.4.44", "RFC 4519"),
+ /** */
+ x500UniqueIdentifier("2.5.4.45", "RFC 4519"),
+ /** */
+ dnQualifier("2.5.4.46", "RFC 4519"),
+ /** */
+ enhancedSearchGuide("2.5.4.47", "RFC 4519"),
+ /** */
+ distinguishedName("2.5.4.49", "RFC 4519"),
+ /** */
+ uniqueMember("2.5.4.50", "RFC 4519"),
+ /** */
+ houseIdentifier("2.5.4.51", "RFC 4519"),
+ /** */
+ supportedAlgorithms("2.5.4.52", "RFC 4523"),
+ /** */
+ deltaRevocationList("2.5.4.53", "RFC 4523"),
+ /** */
+ createTimestamp("2.5.18.1", "RFC 4512"),
+ /** */
+ modifyTimestamp("2.5.18.2", "RFC 4512"),
+ /** */
+ creatorsName("2.5.18.3", "RFC 4512"),
+ /** */
+ modifiersName("2.5.18.4", "RFC 4512"),
+ /** */
+ subschemaSubentry("2.5.18.10", "RFC 4512"),
+ /** */
+ dITStructureRules("2.5.21.1", "RFC 4512"),
+ /** */
+ dITContentRules("2.5.21.2", "RFC 4512"),
+ /** */
+ matchingRules("2.5.21.4", "RFC 4512"),
+ /** */
+ attributeTypes("2.5.21.5", "RFC 4512"),
+ /** */
+ objectClasses("2.5.21.6", "RFC 4512"),
+ /** */
+ nameForms("2.5.21.7", "RFC 4512"),
+ /** */
+ matchingRuleUse("2.5.21.8", "RFC 4512"),
+ /** */
+ structuralObjectClass("2.5.21.9", "RFC 4512"),
+ /** */
+ governingStructureRule("2.5.21.10", "RFC 4512"),
+ /** */
+ carLicense("2.16.840.1.113730.3.1.1", "RFC 2798"),
+ /** */
+ departmentNumber("2.16.840.1.113730.3.1.2", "RFC 2798"),
+ /** */
+ employeeNumber("2.16.840.1.113730.3.1.3", "RFC 2798"),
+ /** */
+ employeeType("2.16.840.1.113730.3.1.4", "RFC 2798"),
+ /** */
+ changeNumber("2.16.840.1.113730.3.1.5", "draft-good-ldap-changelog"),
+ /** */
+ targetDN("2.16.840.1.113730.3.1.6", "draft-good-ldap-changelog"),
+ /** */
+ changeType("2.16.840.1.113730.3.1.7", "draft-good-ldap-changelog"),
+ /** */
+ changes("2.16.840.1.113730.3.1.8", "draft-good-ldap-changelog"),
+ /** */
+ newRDN("2.16.840.1.113730.3.1.9", "draft-good-ldap-changelog"),
+ /** */
+ deleteOldRDN("2.16.840.1.113730.3.1.10", "draft-good-ldap-changelog"),
+ /** */
+ newSuperior("2.16.840.1.113730.3.1.11", "draft-good-ldap-changelog"),
+ /** */
+ ref("2.16.840.1.113730.3.1.34", "RFC 3296"),
+ /** */
+ changelog("2.16.840.1.113730.3.1.35", "draft-good-ldap-changelog"),
+ /** */
+ preferredLanguage("2.16.840.1.113730.3.1.39", "RFC 2798"),
+ /** */
+ userSMIMECertificate("2.16.840.1.113730.3.1.40", "RFC 2798"),
+ /** */
+ userPKCS12("2.16.840.1.113730.3.1.216", "RFC 2798"),
+ /** */
+ displayName("2.16.840.1.113730.3.1.241", "RFC 2798"),
+
+ // Sun memberOf
+ memberOf("1.2.840.113556.1.2.102", "389 DS memberOf"),
+
+ // KERBEROS (partial)
+ krbPrincipalName("2.16.840.1.113719.1.301.6.8.1", "Novell Kerberos Schema Definitions"),
+
+ // RFC 2985 and RFC 3039 (partial)
+ dateOfBirth("1.3.6.1.5.5.7.9.1", "RFC 2985"),
+ /** */
+ placeOfBirth("1.3.6.1.5.5.7.9.2", "RFC 2985"),
+ /** */
+ gender("1.3.6.1.5.5.7.9.3", "RFC 2985"),
+ /** */
+ countryOfCitizenship("1.3.6.1.5.5.7.9.4", "RFC 2985"),
+ /** */
+ countryOfResidence("1.3.6.1.5.5.7.9.5", "RFC 2985"),
+
+ // RFC 2307bis (partial)
+ /** */
+ uidNumber("1.3.6.1.1.1.1.0", "RFC 2307bis"),
+ /** */
+ gidNumber("1.3.6.1.1.1.1.1", "RFC 2307bis"),
+ /** */
+ homeDirectory("1.3.6.1.1.1.1.3", "RFC 2307bis"),
+ /** */
+ loginShell("1.3.6.1.1.1.1.4", "RFC 2307bis"),
+ /** */
+ memberUid("1.3.6.1.1.1.1.12", "RFC 2307bis"),
+
+ //
+ ;
+
+ public final static String DN = "dn";
+
+ private final String oid, spec;
+ private final QName value;
+
+ LdapAttr(String oid, String spec) {
+ this.oid = oid;
+ this.spec = spec;
+ this.value = new ContentName(LDAP_NAMESPACE_URI, name());
+ }
+
+ public QName qName() {
+ return value;
+ }
+
+ @Override
+ public String getID() {
+ return oid;
+ }
+
+ @Override
+ public String getSpec() {
+ return spec;
+ }
+
+ @Deprecated
+ public String property() {
+ return get();
+ }
+
+ @Deprecated
+ public String qualified() {
+ return get();
+ }
+
+ /** #deprecated use {@link #qName()} instead. */
+// @Deprecated
+ public String get() {
+ return RuntimeNamespaceContext.getNamespaceContext().getPrefix(LDAP_NAMESPACE_URI) + ":" + name();
+ }
+
+ @Override
+ public final String toString() {
+ // must return the name
+ return name();
+ }
+
+ @Override
+ public String getNamespace() {
+ return LDAP_NAMESPACE_URI;
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return LDAP_DEFAULT_PREFIX;
+ }
+
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+import static org.argeo.api.acr.ArgeoNamespace.LDAP_DEFAULT_PREFIX;
+import static org.argeo.api.acr.ArgeoNamespace.LDAP_NAMESPACE_URI;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ArgeoNamespace;
+import org.argeo.api.acr.ContentName;
+import org.argeo.api.acr.QNamed;
+import org.argeo.api.acr.RuntimeNamespaceContext;
+
+/**
+ * Standard LDAP object classes as per
+ * <a href="https://www.ldap.com/ldap-oid-reference">https://www.ldap.com/ldap-
+ * oid-reference</a>
+ */
+public enum LdapObj implements QNamed, SpecifiedName {
+ account("0.9.2342.19200300.100.4.5", "RFC 4524"),
+ /** */
+ document("0.9.2342.19200300.100.4.6", "RFC 4524"),
+ /** */
+ room("0.9.2342.19200300.100.4.7", "RFC 4524"),
+ /** */
+ documentSeries("0.9.2342.19200300.100.4.9", "RFC 4524"),
+ /** */
+ domain("0.9.2342.19200300.100.4.13", "RFC 4524"),
+ /** */
+ rFC822localPart("0.9.2342.19200300.100.4.14", "RFC 4524"),
+ /** */
+ domainRelatedObject("0.9.2342.19200300.100.4.17", "RFC 4524"),
+ /** */
+ friendlyCountry("0.9.2342.19200300.100.4.18", "RFC 4524"),
+ /** */
+ simpleSecurityObject("0.9.2342.19200300.100.4.19", "RFC 4524"),
+ /** */
+ uidObject("1.3.6.1.1.3.1", "RFC 4519"),
+ /** */
+ extensibleObject("1.3.6.1.4.1.1466.101.120.111", "RFC 4512"),
+ /** */
+ dcObject("1.3.6.1.4.1.1466.344", "RFC 4519"),
+ /** */
+ authPasswordObject("1.3.6.1.4.1.4203.1.4.7", "RFC 3112"),
+ /** */
+ namedObject("1.3.6.1.4.1.5322.13.1.1", "draft-howard-namedobject"),
+ /** */
+ inheritableLDAPSubEntry("1.3.6.1.4.1.7628.5.6.1.1", "draft-ietf-ldup-subentry"),
+ /** */
+ top("2.5.6.0", "RFC 4512"),
+ /** */
+ alias("2.5.6.1", "RFC 4512"),
+ /** */
+ country("2.5.6.2", "RFC 4519"),
+ /** */
+ locality("2.5.6.3", "RFC 4519"),
+ /** */
+ organization("2.5.6.4", "RFC 4519"),
+ /** */
+ organizationalUnit("2.5.6.5", "RFC 4519"),
+ /** */
+ person("2.5.6.6", "RFC 4519"),
+ /** */
+ organizationalPerson("2.5.6.7", "RFC 4519"),
+ /** */
+ organizationalRole("2.5.6.8", "RFC 4519"),
+ /** */
+ groupOfNames("2.5.6.9", "RFC 4519"),
+ /** */
+ residentialPerson("2.5.6.10", "RFC 4519"),
+ /** */
+ applicationProcess("2.5.6.11", "RFC 4519"),
+ /** */
+ device("2.5.6.14", "RFC 4519"),
+ /** */
+ strongAuthenticationUser("2.5.6.15", "RFC 4523"),
+ /** */
+ certificationAuthority("2.5.6.16", "RFC 4523"),
+ // /** Should be certificationAuthority-V2 */
+ // certificationAuthority_V2("2.5.6.16.2", "RFC 4523") {
+ // },
+ /** */
+ groupOfUniqueNames("2.5.6.17", "RFC 4519"),
+ /** */
+ userSecurityInformation("2.5.6.18", "RFC 4523"),
+ /** */
+ cRLDistributionPoint("2.5.6.19", "RFC 4523"),
+ /** */
+ pkiUser("2.5.6.21", "RFC 4523"),
+ /** */
+ pkiCA("2.5.6.22", "RFC 4523"),
+ /** */
+ deltaCRL("2.5.6.23", "RFC 4523"),
+ /** */
+ subschema("2.5.20.1", "RFC 4512"),
+ /** */
+ ldapSubEntry("2.16.840.1.113719.2.142.6.1.1", "draft-ietf-ldup-subentry"),
+ /** */
+ changeLogEntry("2.16.840.1.113730.3.2.1", "draft-good-ldap-changelog"),
+ /** */
+ inetOrgPerson("2.16.840.1.113730.3.2.2", "RFC 2798"),
+ /** */
+ referral("2.16.840.1.113730.3.2.6", "RFC 3296"),
+
+ // RFC 2307bis (partial)
+ /** */
+ posixAccount("1.3.6.1.1.1.2.0", "RFC 2307bis"),
+ /** */
+ posixGroup("1.3.6.1.1.1.2.2", "RFC 2307bis"),
+
+ //
+ ;
+
+ private final String oid, spec;
+ private final QName value;
+
+ private LdapObj(String oid, String spec) {
+ this.oid = oid;
+ this.spec = spec;
+ this.value = new ContentName(ArgeoNamespace.LDAP_NAMESPACE_URI, name());
+ }
+
+ public QName qName() {
+ return value;
+ }
+
+ public String getOid() {
+ return oid;
+ }
+
+ public String getSpec() {
+ return spec;
+ }
+
+ @Deprecated
+ public String property() {
+ return get();
+ }
+
+ /** #deprecated use {@link #qName()} instead. */
+// @Deprecated
+ public String get() {
+ return RuntimeNamespaceContext.getNamespaceContext().getPrefix(LDAP_NAMESPACE_URI) + ":" + name();
+ }
+
+ @Override
+ public String getNamespace() {
+ return LDAP_NAMESPACE_URI;
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return LDAP_DEFAULT_PREFIX;
+ }
+
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class NamingUtils {
+ /** As per https://tools.ietf.org/html/rfc4517#section-3.3.13 */
+ private final static DateTimeFormatter utcLdapDate = DateTimeFormatter.ofPattern("uuuuMMddHHmmssX")
+ .withZone(ZoneOffset.UTC);
+
+ /** @return null if not parseable */
+ public static Instant ldapDateToInstant(String ldapDate) {
+ try {
+ return OffsetDateTime.parse(ldapDate, utcLdapDate).toInstant();
+ } catch (DateTimeParseException e) {
+ return null;
+ }
+ }
+
+ /** @return null if not parseable */
+ public static ZonedDateTime ldapDateToZonedDateTime(String ldapDate) {
+ try {
+ return OffsetDateTime.parse(ldapDate, utcLdapDate).toZonedDateTime();
+ } catch (DateTimeParseException e) {
+ return null;
+ }
+ }
+
+ public static Calendar ldapDateToCalendar(String ldapDate) {
+ OffsetDateTime instant = OffsetDateTime.parse(ldapDate, utcLdapDate);
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.set(Calendar.DAY_OF_MONTH, instant.get(ChronoField.DAY_OF_MONTH));
+ calendar.set(Calendar.MONTH, instant.get(ChronoField.MONTH_OF_YEAR));
+ calendar.set(Calendar.YEAR, instant.get(ChronoField.YEAR));
+ return calendar;
+ }
+
+ public static String instantToLdapDate(ZonedDateTime instant) {
+ return utcLdapDate.format(instant.withZoneSameInstant(ZoneOffset.UTC));
+ }
+
+ public static String getQueryValue(Map<String, List<String>> query, String key) {
+ if (!query.containsKey(key))
+ return null;
+ List<String> val = query.get(key);
+ if (val.size() == 1)
+ return val.get(0);
+ else
+ throw new IllegalArgumentException("There are " + val.size() + " value(s) for " + key);
+ }
+
+ public static Map<String, List<String>> queryToMap(URI uri) {
+ return queryToMap(uri.getQuery());
+ }
+
+ private static Map<String, List<String>> queryToMap(String queryPart) {
+ try {
+ final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
+ if (queryPart == null)
+ return query_pairs;
+ final String[] pairs = queryPart.split("&");
+ for (String pair : pairs) {
+ final int idx = pair.indexOf("=");
+ final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8.name())
+ : pair;
+ if (!query_pairs.containsKey(key)) {
+ query_pairs.put(key, new LinkedList<String>());
+ }
+ final String value = idx > 0 && pair.length() > idx + 1
+ ? URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8.name())
+ : null;
+ query_pairs.get(key).add(value);
+ }
+ return query_pairs;
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException("Cannot convert " + queryPart + " to map", e);
+ }
+ }
+
+ private NamingUtils() {
+
+ }
+
+// public static void main(String args[]) {
+// ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(ZoneOffset.UTC);
+// String str = utcLdapDate.format(now);
+// System.out.println(str);
+// utcLdapDate.parse(str);
+// utcLdapDate.parse("19520512000000Z");
+// }
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+interface NodeOID {
+ String BASE = "1.3.6.1.4.1" + ".48308" + ".1";
+
+ // uuidgen --md5 --namespace @oid --name 1.3.6.1.4.1.48308
+ String BASE_UUID_V3 = "6869e86b-96b7-3d49-b6ab-ffffc5ad95fb";
+
+ // uuidgen --sha1 --namespace @oid --name 1.3.6.1.4.1.48308
+ String BASE_UUID_V5 = "58873947-460c-59a6-a7b4-28a97def5f27";
+
+ // ATTRIBUTE TYPES
+ String ATTRIBUTE_TYPES = BASE + ".4";
+
+ // OBJECT CLASSES
+ String OBJECT_CLASSES = BASE + ".6";
+}
--- /dev/null
+package org.argeo.api.acr.ldap;
+
+/**
+ * A name which has been specified and for which an id has been defined
+ * (typically an OID).
+ */
+interface SpecifiedName {
+ /** The name */
+ String name();
+
+ /** An RFC or the URLof some specification */
+ default String getSpec() {
+ return null;
+ }
+
+ /** Typically an OID */
+ default String getID() {
+ return getClass().getName() + "." + name();
+ }
+}
--- /dev/null
+package org.argeo.api.acr.spi;
+
+import java.net.URL;
+
+/** A namespace and its default prefix, possibly with a schema definition. */
+public interface ContentNamespace {
+ String getDefaultPrefix();
+
+ String getNamespaceURI();
+
+ URL getSchemaResource();
+
+}
/** A {@link ContentRepository} implementation. */
public interface ProvidedRepository extends ContentRepository {
- void registerTypes(String prefix, String namespaceURI, String schemaSystemId);
+ void registerTypes(ContentNamespace... namespaces);
ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types);
UUID getUuid();
- Content getSessionRunDir();
+// Content getSessionRunDir();
/*
* NAMESPACE CONTEXT
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+import java.util.List;
+
+/** Minimal tabular row wrapping an {@link Object} array */
+public class ArrayTabularRow implements TabularRow {
+ private final Object[] arr;
+
+ public ArrayTabularRow(List<?> objs) {
+ this.arr = objs.toArray();
+ }
+
+ public Object get(Integer col) {
+ return arr[col];
+ }
+
+ public int size() {
+ return arr.length;
+ }
+
+ public Object[] toArray() {
+ return arr;
+ }
+
+}
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+/** The column in a tabular content */
+public class TabularColumn {
+ private String name;
+ /**
+ * JCR types, see
+ * http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/index.html
+ * ?javax/jcr/PropertyType.html
+ */
+ private Integer type;
+
+ /** column with default type */
+ public TabularColumn(String name) {
+ super();
+ this.name = name;
+ }
+
+ public TabularColumn(String name, Integer type) {
+ super();
+ this.name = name;
+ this.type = type;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public void setType(Integer type) {
+ this.type = type;
+ }
+
+}
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+import java.util.List;
+
+/**
+ * Content organized as a table, possibly with headers. Only JCR types are
+ * supported even though there is not direct dependency on JCR.
+ */
+public interface TabularContent {
+ /** The headers of this table or <code>null</code> is none available. */
+ public List<TabularColumn> getColumns();
+
+ public TabularRowIterator read();
+}
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+/** A row of tabular data */
+public interface TabularRow {
+ /** The value at this column index */
+ public Object get(Integer col);
+
+ /** The raw objects (direct references) */
+ public Object[] toArray();
+
+ /** Number of columns */
+ public int size();
+}
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+import java.util.Iterator;
+
+/** Navigation of rows */
+public interface TabularRowIterator extends Iterator<TabularRow> {
+ /**
+ * Current row number, has to be incremented by each call to next() ; starts at 0, will
+ * therefore be 1 for the first row returned.
+ */
+ public Long getCurrentRowNumber();
+}
--- /dev/null
+package org.argeo.api.acr.tabular;
+
+
+/** Write to a tabular content */
+public interface TabularWriter {
+ /** Append a new row of data */
+ public void appendRow(Object[] row);
+
+ /** Finish persisting data and release resources */
+ public void close();
+}
--- /dev/null
+/** Tabular format API. */
+package org.argeo.api.acr.tabular;
\ No newline at end of file
package org.argeo.api.cli;
+/** Exception thrown when the provided arguments are not correct. */
public class CommandArgsException extends IllegalArgumentException {
private static final long serialVersionUID = -7271050747105253935L;
private String commandName;
/** Base class for a CLI managing sub commands. */
public abstract class CommandsCli implements DescribedCommand<Object> {
- public final static String HELP = "help";
-
private final String commandName;
private Map<String, Function<List<String>, ?>> commands = new TreeMap<>();
public Object apply(List<String> args) {
String cmd = null;
List<String> newArgs = new ArrayList<>();
+ boolean isHelpOption = false;
try {
CommandLineParser clParser = new DefaultParser();
CommandLine commonCl = clParser.parse(getOptions(), args.toArray(new String[args.size()]), true);
List<String> leftOvers = commonCl.getArgList();
for (String arg : leftOvers) {
+ if (arg.equals("--" + HelpCommand.HELP_OPTION.getLongOpt())) {
+ isHelpOption = true;
+ // TODO break?
+ }
+
if (!arg.startsWith("-") && cmd == null) {
cmd = arg;
} else {
}
Function<List<String>, ?> function = cmd != null ? getCommand(cmd) : getDefaultCommand();
+
+ // --help option
+ if (!(function instanceof CommandsCli))
+ if (function instanceof DescribedCommand<?> command)
+ if (isHelpOption) {
+ throw new PrintHelpRequestException(cmd, this);
+// StringWriter out = new StringWriter();
+// HelpCommand.printHelp(command, out);
+// System.out.println(out.toString());
+// return null;
+ }
+
if (function == null)
throw new IllegalArgumentException("Uknown command " + cmd);
try {
protected void addCommandsCli(CommandsCli commandsCli) {
addCommand(commandsCli.getCommandName(), commandsCli);
- commandsCli.addCommand(HELP, new HelpCommand(this, commandsCli));
+ commandsCli.addCommand(HelpCommand.HELP, new HelpCommand(this, commandsCli));
}
public String getCommandName() {
}
public HelpCommand getHelpCommand() {
- return (HelpCommand) getCommand(HELP);
+ return (HelpCommand) getCommand(HelpCommand.HELP);
}
public Function<List<String>, String> getDefaultCommand() {
/** In order to implement quickly a main method. */
public static void mainImpl(CommandsCli cli, String[] args) {
try {
- cli.addCommand(CommandsCli.HELP, new HelpCommand(null, cli));
+ cli.addCommand(HelpCommand.HELP, new HelpCommand(null, cli));
Object output = cli.apply(Arrays.asList(args));
- System.out.println(output);
+ if (output != null)
+ System.out.println(output);
System.exit(0);
+ } catch (PrintHelpRequestException e) {
+ StringWriter out = new StringWriter();
+ HelpCommand.printHelp(e.getCommandsCli(), e.getCommandName(), out);
+ System.out.println(out.toString());
} catch (CommandArgsException e) {
System.err.println("Wrong arguments " + Arrays.toString(args) + ": " + e.getMessage());
Throwable cause = e.getCause();
Object output = command.apply(Arrays.asList(args));
System.out.println(output);
System.exit(0);
+ } catch (PrintHelpRequestException e) {
+ StringWriter out = new StringWriter();
+ HelpCommand.printHelp(command, out);
+ System.out.println(out.toString());
+ System.exit(1);
} catch (IllegalArgumentException e) {
StringWriter out = new StringWriter();
HelpCommand.printHelp(command, out);
import java.util.function.Function;
import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
/** A special command that can describe {@link DescribedCommand}. */
public class HelpCommand implements DescribedCommand<String> {
+ /**
+ * System property forcing the root command to this value (typically the name of
+ * a script).
+ */
+ public final static String ROOT_COMMAND_PROPERTY = "org.argeo.api.cli.rootCommand";
+
+ final static String HELP = "help";
+ final static Option HELP_OPTION = Option.builder().longOpt(HELP).desc("print this help").build();
+
private CommandsCli commandsCli;
private CommandsCli parentCommandsCli;
if (hc.getParentCommandsCli() != null) {
return getCommandCall(hc.getParentCommandsCli()) + " " + commandsCli.getCommandName();
} else {
+ String rootCommand = System.getProperty(ROOT_COMMAND_PROPERTY);
+ if (rootCommand != null)
+ return rootCommand;
return commandsCli.getCommandName();
}
}
String usage = "java " + command.getClass().getName()
+ (command.getUsage() != null ? " " + command.getUsage() : "");
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), command.getOptions(),
- helpLeftPad, helpDescPad, command.getExamples(), false);
+ Options options = command.getOptions();
+ options.addOption(HelpCommand.HELP_OPTION);
+ formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), options, helpLeftPad,
+ helpDescPad, command.getExamples(), false);
}
public static void printHelp(CommandsCli commandsCli, String commandName, StringWriter out) {
+ if (commandName == null) {
+ printHelp(commandsCli, out);
+ return;
+ }
DescribedCommand<?> command = (DescribedCommand<?>) commandsCli.getCommand(commandName);
String usage = commandsCli.getHelpCommand().getCommandUsage(commandName, command);
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), command.getOptions(),
- helpLeftPad, helpDescPad, command.getExamples(), false);
+ Options options = command.getOptions();
+ options.addOption(HelpCommand.HELP_OPTION);
+ formatter.printHelp(new PrintWriter(out), helpWidth, usage, command.getDescription(), options, helpLeftPad,
+ helpDescPad, command.getExamples(), false);
}
--- /dev/null
+package org.argeo.api.cli;
+
+/** An exception indicating that help should be printed. */
+class PrintHelpRequestException extends RuntimeException {
+
+ private static final long serialVersionUID = -9029122270660656639L;
+
+ private String commandName;
+ private volatile CommandsCli commandsCli;
+
+ public PrintHelpRequestException(String commandName, CommandsCli commandsCli) {
+ super();
+ this.commandName = commandName;
+ this.commandsCli = commandsCli;
+ }
+
+ public static long getSerialversionuid() {
+ return serialVersionUID;
+ }
+
+ public String getCommandName() {
+ return commandName;
+ }
+
+ public CommandsCli getCommandsCli() {
+ return commandsCli;
+ }
+
+}
Import-Package: \
-javax.security.*
+javax.transaction.xa,\
+javax.security.*,\
+org.osgi.service.useradmin,\
Export-Package: org.argeo.api.cms.*
\ No newline at end of file
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import org.osgi.service.useradmin.Authorization;
+
+/** An authorisation to a CMS system. */
+public interface CmsAuthorization extends Authorization {
+ /** The role which did imply this role, <code>null</code> if a direct role. */
+ default String getImplyingRole(String role) {
+ return null;
+ }
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import java.util.Optional;
+
+import org.argeo.api.cms.transaction.WorkControl;
+
+/** An information directory (typically LDAP). */
+public interface CmsDirectory extends HierarchyUnit {
+ String getName();
+
+ /** Whether this directory is read only. */
+ boolean isReadOnly();
+
+ /** Whether this directory is disabled. */
+ boolean isDisabled();
+
+ /** The realm (typically Kerberos) of this directory. */
+ Optional<String> getRealm();
+
+ /** Sets the transaction control used by this directory when editing. */
+ void setTransactionControl(WorkControl transactionControl);
+
+ /*
+ * HIERARCHY
+ */
+
+ /** The hierarchy unit at this path. */
+ HierarchyUnit getHierarchyUnit(String path);
+
+ /** Create a new hierarchy unit. */
+ HierarchyUnit createHierarchyUnit(String path);
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import org.osgi.service.useradmin.Group;
+
+/** A group in a user directroy. */
+public interface CmsGroup extends Group, CmsUser {
+// List<LdapName> getMemberNames();
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import org.osgi.service.useradmin.User;
+
+/**
+ * An entity with credentials which can log in to a system. Can be a real person
+ * or not.
+ */
+public interface CmsUser extends User {
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import java.time.ZonedDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.xml.namespace.QName;
+
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
+/**
+ * Provide method interfaces to manage user concepts without accessing directly
+ * the userAdmin.
+ */
+public interface CmsUserManager {
+ Map<String, String> getKnownBaseDns(boolean onlyWritable);
+
+ Set<UserDirectory> getUserDirectories();
+
+ // CurrentUser
+ /** Returns the e-mail of the current logged in user */
+ String getMyMail();
+
+ // Other users
+ /** Returns a {@link User} given a username */
+ CmsUser getUser(String username);
+
+ /** Can be a group or a user */
+ String getUserDisplayName(String dn);
+
+ /** Can be a group or a user */
+ String getUserMail(String dn);
+
+ /** Lists all roles of the given user */
+ String[] getUserRoles(String dn);
+
+ /** Checks if the passed user belongs to the passed role */
+ boolean isUserInRole(String userDn, String roleDn);
+
+ // Search
+ /** Returns a filtered list of roles */
+ Role[] getRoles(String filter);
+
+ /** Recursively lists users in a given group. */
+ Set<CmsUser> listUsersInGroup(String groupDn, String filter);
+
+ /** Search among groups including system roles and users if needed */
+ List<CmsUser> listGroups(String filter, boolean includeUsers, boolean includeSystemRoles);
+
+// /**
+// * Lists functional accounts, that is users with regular access to the system
+// * under this functional hierarchy unit (which probably have technical direct
+// * sub hierarchy units), excluding groups which are not explicitly users.
+// */
+// Set<User> listAccounts(HierarchyUnit hierarchyUnit, boolean deep);
+
+ /*
+ * EDITION
+ */
+ /** Creates a new user. */
+ CmsUser createUser(String username, Map<String, Object> properties, Map<String, Object> credentials);
+
+ /** Created a new group. */
+ CmsGroup createGroup(String dn);
+
+ /** Creates a group. */
+ CmsGroup getOrCreateGroup(HierarchyUnit groups, String commonName);
+
+ /** Creates a new system role. */
+ CmsGroup getOrCreateSystemRole(HierarchyUnit roles, QName systemRole);
+
+ /** Add additional object classes to this role. */
+ void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties);
+
+ /** Add additional object classes to this hierarchy unit. */
+ void addObjectClasses(HierarchyUnit hierarchyUnit, Set<String> objectClasses,
+ Map<String, Object> additionalProperties);
+
+ /** Add a member to this group. */
+ void addMember(CmsGroup group, Role role);
+
+ /** Remove a member from this group. */
+ void removeMember(CmsGroup group, Role role);
+
+ void edit(Runnable action);
+
+ /* MISCELLANEOUS */
+ /** Returns the dn of a role given its local ID */
+ String buildDefaultDN(String localId, int type);
+
+ /** Exposes the main default domain name for this instance */
+ String getDefaultDomainName();
+
+ /**
+ * Search for a {@link User} (might also be a group) whose uid or cn is equals
+ * to localId within the various user repositories defined in the current
+ * context.
+ */
+ CmsUser getUserFromLocalId(String localId);
+
+ void changeOwnPassword(char[] oldPassword, char[] newPassword);
+
+ void resetPassword(String username, char[] newPassword);
+
+ @Deprecated
+ String addSharedSecret(String username, int hours);
+
+// String addSharedSecret(String username, String authInfo, String authToken);
+
+ void addAuthToken(String userDn, String token, Integer hours, String... roles);
+
+ void addAuthToken(String userDn, String token, ZonedDateTime expiryDate, String... roles);
+
+ void expireAuthToken(String token);
+
+ void expireAuthTokens(Subject subject);
+
+ UserDirectory getDirectory(Role role);
+
+ /** Create a new hierarchy unit. Does nothing if it already exists. */
+ HierarchyUnit getOrCreateHierarchyUnit(UserDirectory directory, String path);
+}
\ No newline at end of file
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.util.Arrays;
+
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+
+/** Utilities around digests, mostly those related to passwords. */
+public class DirectoryDigestUtils {
+ public final static String PASSWORD_SCHEME_SHA = "SHA";
+ public final static String PASSWORD_SCHEME_PBKDF2_SHA256 = "PBKDF2_SHA256";
+
+ public static byte[] sha1(byte[] bytes) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA1");
+ digest.update(bytes);
+ byte[] checksum = digest.digest();
+ return checksum;
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalStateException("Cannot SHA1 digest", e);
+ }
+ }
+
+ public static byte[] toPasswordScheme(String passwordScheme, char[] password, byte[] salt, Integer iterations,
+ Integer keyLength) {
+ try {
+ if (PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
+ MessageDigest digest = MessageDigest.getInstance("SHA1");
+ byte[] bytes = charsToBytes(password);
+ digest.update(bytes);
+ return digest.digest();
+ } else if (PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
+ KeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
+
+ SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
+ final int ITERATION_LENGTH = 4;
+ byte[] key = f.generateSecret(spec).getEncoded();
+ byte[] result = new byte[ITERATION_LENGTH + salt.length + key.length];
+ byte iterationsArr[] = new BigInteger(iterations.toString()).toByteArray();
+ if (iterationsArr.length < ITERATION_LENGTH) {
+ Arrays.fill(result, 0, ITERATION_LENGTH - iterationsArr.length, (byte) 0);
+ System.arraycopy(iterationsArr, 0, result, ITERATION_LENGTH - iterationsArr.length,
+ iterationsArr.length);
+ } else {
+ System.arraycopy(iterationsArr, 0, result, 0, ITERATION_LENGTH);
+ }
+ System.arraycopy(salt, 0, result, ITERATION_LENGTH, salt.length);
+ System.arraycopy(key, 0, result, ITERATION_LENGTH + salt.length, key.length);
+ return result;
+ } else {
+ throw new UnsupportedOperationException("Unkown password scheme " + passwordScheme);
+ }
+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
+ throw new IllegalStateException("Cannot digest", e);
+ }
+ }
+
+ public static char[] bytesToChars(Object obj) {
+ if (obj instanceof char[])
+ return (char[]) obj;
+ if (!(obj instanceof byte[]))
+ throw new IllegalArgumentException(obj.getClass() + " is not a byte array");
+ ByteBuffer fromBuffer = ByteBuffer.wrap((byte[]) obj);
+ CharBuffer toBuffer = StandardCharsets.UTF_8.decode(fromBuffer);
+ char[] res = Arrays.copyOfRange(toBuffer.array(), toBuffer.position(), toBuffer.limit());
+ // Arrays.fill(fromBuffer.array(), (byte) 0); // clear sensitive data
+ // Arrays.fill((byte[]) obj, (byte) 0); // clear sensitive data
+ // Arrays.fill(toBuffer.array(), '\u0000'); // clear sensitive data
+ return res;
+ }
+
+ public static byte[] charsToBytes(char[] chars) {
+ CharBuffer charBuffer = CharBuffer.wrap(chars);
+ ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
+ byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
+ // Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
+ // Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
+ return bytes;
+ }
+
+ public static String sha1str(String str) {
+ byte[] hash = sha1(str.getBytes(StandardCharsets.UTF_8));
+ return encodeHexString(hash);
+ }
+
+ final private static char[] hexArray = "0123456789abcdef".toCharArray();
+
+ /**
+ * From
+ * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
+ * -a-hex-string-in-java
+ */
+ public static String encodeHexString(byte[] bytes) {
+ char[] hexChars = new char[bytes.length * 2];
+ for (int j = 0; j < bytes.length; j++) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+ /** singleton */
+ private DirectoryDigestUtils() {
+ }
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import java.util.Dictionary;
+import java.util.Locale;
+
+/** A unit within the high-level organisational structure of a directory. */
+public interface HierarchyUnit {
+ /** Name to use in paths. */
+ String getHierarchyUnitName();
+
+ /** Name to use in UI. */
+ String getHierarchyUnitLabel(Locale locale);
+
+ /**
+ * The parent {@link HierarchyUnit}, or <code>null</code> if a
+ * {@link CmsDirectory}.
+ */
+ HierarchyUnit getParent();
+
+ /** Direct children {@link HierarchyUnit}s. */
+ Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly);
+
+ /**
+ * Whether this is an arbitrary named and placed {@link HierarchyUnit}.
+ *
+ * @return <code>true</code> if functional, <code>false</code> is technical
+ * (e.g. People, Groups, etc.)
+ */
+ default boolean isFunctional() {
+ return isType(Type.FUNCTIONAL);
+ }
+
+ boolean isType(Type type);
+
+ /** A technical direct child. */
+ HierarchyUnit getDirectChild(Type type);
+
+ /**
+ * The base of this organisational unit within the hierarchy. This would
+ * typically be an LDAP base DN.
+ */
+ String getBase();
+
+ /** The related {@link CmsDirectory}. */
+ CmsDirectory getDirectory();
+
+ /** Its metadata (typically LDAP attributes). */
+ Dictionary<String, Object> getProperties();
+
+ enum Type {
+ PEOPLE, //
+ GROUPS, //
+ ROLES, //
+ FUNCTIONAL;
+ }
+}
--- /dev/null
+package org.argeo.api.cms.directory;
+
+import org.osgi.service.useradmin.Role;
+
+/** Information about a user directory. */
+public interface UserDirectory extends CmsDirectory {
+
+ HierarchyUnit getHierarchyUnit(Role role);
+
+ Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep);
+
+ String getRolePath(Role role);
+
+ String getRoleSimpleName(Role role);
+
+ Role getRoleByPath(String path);
+}
--- /dev/null
+package org.argeo.api.cms.keyring;
+
+/**
+ * Marker interface for an advanced keyring based on cryptography.
+ */
+public interface CryptoKeyring extends Keyring {
+ public void changePassword(char[] oldPassword, char[] newPassword);
+
+ public void unlock(char[] password);
+}
--- /dev/null
+package org.argeo.api.cms.keyring;
+
+import java.io.InputStream;
+
+/**
+ * Access to private (typically encrypted) data. The keyring is responsible for
+ * retrieving the necessary credentials. <b>Experimental. This API may
+ * change.</b>
+ */
+public interface Keyring {
+ /**
+ * Returns the confidential information as chars. Must ask for it if it is
+ * not stored.
+ */
+ public char[] getAsChars(String path);
+
+ /**
+ * Returns the confidential information as a stream. Must ask for it if it
+ * is not stored.
+ */
+ public InputStream getAsStream(String path);
+
+ public void set(String path, char[] arr);
+
+ public void set(String path, InputStream in);
+}
--- /dev/null
+package org.argeo.api.cms.keyring;
+
+import javax.crypto.spec.PBEKeySpec;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.PasswordCallback;
+
+/**
+ * All information required to set up a {@link PBEKeySpec} bar the password
+ * itself (use a {@link PasswordCallback})
+ */
+public class PBEKeySpecCallback implements Callback {
+ private String secretKeyFactory;
+ private byte[] salt;
+ private Integer iterationCount;
+ /** Can be null for some algorithms */
+ private Integer keyLength;
+ /** Can be null, will trigger secret key encryption if not */
+ private String secretKeyEncryption;
+
+ private String encryptedPasswordHashCipher;
+ private byte[] encryptedPasswordHash;
+
+ public void set(String secretKeyFactory, byte[] salt,
+ Integer iterationCount, Integer keyLength,
+ String secretKeyEncryption) {
+ this.secretKeyFactory = secretKeyFactory;
+ this.salt = salt;
+ this.iterationCount = iterationCount;
+ this.keyLength = keyLength;
+ this.secretKeyEncryption = secretKeyEncryption;
+// this.encryptedPasswordHashCipher = encryptedPasswordHashCipher;
+// this.encryptedPasswordHash = encryptedPasswordHash;
+ }
+
+ public String getSecretKeyFactory() {
+ return secretKeyFactory;
+ }
+
+ public byte[] getSalt() {
+ return salt;
+ }
+
+ public Integer getIterationCount() {
+ return iterationCount;
+ }
+
+ public Integer getKeyLength() {
+ return keyLength;
+ }
+
+ public String getSecretKeyEncryption() {
+ return secretKeyEncryption;
+ }
+
+ public String getEncryptedPasswordHashCipher() {
+ return encryptedPasswordHashCipher;
+ }
+
+ public byte[] getEncryptedPasswordHash() {
+ return encryptedPasswordHash;
+ }
+
+}
--- /dev/null
+/** Argeo CMS reusable security components. */
+package org.argeo.api.cms.keyring;
\ No newline at end of file
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public abstract class AbstractWorkingCopy<DATA, ATTR, ID> implements WorkingCopy<DATA, ATTR, ID> {
+ private Map<ID, DATA> newData = new HashMap<ID, DATA>();
+ private Map<ID, ATTR> modifiedData = new HashMap<ID, ATTR>();
+ private Map<ID, DATA> deletedData = new HashMap<ID, DATA>();
+
+ protected abstract ID getId(DATA data);
+
+ protected abstract ATTR cloneAttributes(DATA data);
+
+ public void cleanUp() {
+ // clean collections
+ newData.clear();
+ newData = null;
+ modifiedData.clear();
+ modifiedData = null;
+ deletedData.clear();
+ deletedData = null;
+ }
+
+ public boolean noModifications() {
+ return newData.size() == 0 && modifiedData.size() == 0 && deletedData.size() == 0;
+ }
+
+ public void startEditing(DATA user) {
+ ID id = getId(user);
+ if (modifiedData.containsKey(id))
+ throw new IllegalStateException("Already editing " + id);
+ modifiedData.put(id, cloneAttributes(user));
+ }
+
+ public Map<ID, DATA> getNewData() {
+ return newData;
+ }
+
+ public Map<ID, DATA> getDeletedData() {
+ return deletedData;
+ }
+
+ public Map<ID, ATTR> getModifiedData() {
+ return modifiedData;
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+/** JTA transaction status. */
+public class JtaStatusAdapter implements TransactionStatusAdapter<Integer> {
+ private static final Integer STATUS_ACTIVE = 0;
+ private static final Integer STATUS_COMMITTED = 3;
+ private static final Integer STATUS_COMMITTING = 8;
+ private static final Integer STATUS_MARKED_ROLLBACK = 1;
+ private static final Integer STATUS_NO_TRANSACTION = 6;
+ private static final Integer STATUS_PREPARED = 2;
+ private static final Integer STATUS_PREPARING = 7;
+ private static final Integer STATUS_ROLLEDBACK = 4;
+ private static final Integer STATUS_ROLLING_BACK = 9;
+// private static final Integer STATUS_UNKNOWN = 5;
+
+ @Override
+ public Integer getActiveStatus() {
+ return STATUS_ACTIVE;
+ }
+
+ @Override
+ public Integer getPreparingStatus() {
+ return STATUS_PREPARING;
+ }
+
+ @Override
+ public Integer getMarkedRollbackStatus() {
+ return STATUS_MARKED_ROLLBACK;
+ }
+
+ @Override
+ public Integer getPreparedStatus() {
+ return STATUS_PREPARED;
+ }
+
+ @Override
+ public Integer getCommittingStatus() {
+ return STATUS_COMMITTING;
+ }
+
+ @Override
+ public Integer getCommittedStatus() {
+ return STATUS_COMMITTED;
+ }
+
+ @Override
+ public Integer getRollingBackStatus() {
+ return STATUS_ROLLING_BACK;
+ }
+
+ @Override
+ public Integer getRolledBackStatus() {
+ return STATUS_ROLLEDBACK;
+ }
+
+ @Override
+ public Integer getNoTransactionStatus() {
+ return STATUS_NO_TRANSACTION;
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+/** Internal unchecked rollback exception. */
+class SimpleRollbackException extends RuntimeException {
+ private static final long serialVersionUID = 8055601819719780566L;
+
+ public SimpleRollbackException() {
+ super();
+ }
+
+ public SimpleRollbackException(Throwable cause) {
+ super(cause);
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/** Simple implementation of an XA transaction. */
+class SimpleTransaction<T>
+//implements Transaction, Status
+{
+ private final Xid xid;
+ private T status;
+ private final List<XAResource> xaResources = new ArrayList<XAResource>();
+
+ private final SimpleTransactionManager transactionManager;
+ private TransactionStatusAdapter<T> tsa;
+
+ public SimpleTransaction(SimpleTransactionManager transactionManager, TransactionStatusAdapter<T> tsa) {
+ this.tsa = tsa;
+ this.status = tsa.getActiveStatus();
+ this.xid = new UuidXid();
+ this.transactionManager = transactionManager;
+ }
+
+ public synchronized void commit()
+// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+// SecurityException, IllegalStateException, SystemException
+ {
+ status = tsa.getPreparingStatus();
+ for (XAResource xaRes : xaResources) {
+ if (status.equals(tsa.getMarkedRollbackStatus()))
+ break;
+ try {
+ xaRes.prepare(xid);
+ } catch (XAException e) {
+ status = tsa.getMarkedRollbackStatus();
+ error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status.equals(tsa.getMarkedRollbackStatus())) {
+ rollback();
+ throw new SimpleRollbackException();
+ }
+ status = tsa.getPreparedStatus();
+
+ status = tsa.getCommittingStatus();
+ for (XAResource xaRes : xaResources) {
+ if (status.equals(tsa.getMarkedRollbackStatus()))
+ break;
+ try {
+ xaRes.commit(xid, false);
+ } catch (XAException e) {
+ status = tsa.getMarkedRollbackStatus();
+ error("Cannot prepare " + xaRes + " for " + xid, e);
+ }
+ }
+ if (status.equals(tsa.getMarkedRollbackStatus())) {
+ rollback();
+ throw new SimpleRollbackException();
+ }
+
+ // complete
+ status = tsa.getCommittedStatus();
+ clearResources(XAResource.TMSUCCESS);
+ transactionManager.unregister(xid);
+ }
+
+ public synchronized void rollback()
+// throws IllegalStateException, SystemException
+ {
+ status = tsa.getRollingBackStatus();
+ for (XAResource xaRes : xaResources) {
+ try {
+ xaRes.rollback(xid);
+ } catch (XAException e) {
+ error("Cannot rollback " + xaRes + " for " + xid, e);
+ }
+ }
+
+ // complete
+ status = tsa.getRolledBackStatus();
+ clearResources(XAResource.TMFAIL);
+ transactionManager.unregister(xid);
+ }
+
+ public synchronized boolean enlistResource(XAResource xaRes)
+// throws RollbackException, IllegalStateException, SystemException
+ {
+ if (xaResources.add(xaRes)) {
+ try {
+ xaRes.start(getXid(), XAResource.TMNOFLAGS);
+ return true;
+ } catch (XAException e) {
+ error("Cannot enlist " + xaRes, e);
+ return false;
+ }
+ } else
+ return false;
+ }
+
+ public synchronized boolean delistResource(XAResource xaRes, int flag)
+// throws IllegalStateException, SystemException
+ {
+ if (xaResources.remove(xaRes)) {
+ try {
+ xaRes.end(getXid(), flag);
+ } catch (XAException e) {
+ error("Cannot delist " + xaRes, e);
+ return false;
+ }
+ return true;
+ } else
+ return false;
+ }
+
+ protected void clearResources(int flag) {
+ for (XAResource xaRes : xaResources)
+ try {
+ xaRes.end(getXid(), flag);
+ } catch (XAException e) {
+ error("Cannot end " + xaRes, e);
+ }
+ xaResources.clear();
+ }
+
+ protected void error(Object obj, Exception e) {
+ System.err.println(obj);
+ e.printStackTrace();
+ }
+
+ public synchronized T getStatus()
+// throws SystemException
+ {
+ return status;
+ }
+
+// public void registerSynchronization(Synchronization sync)
+// throws RollbackException, IllegalStateException, SystemException {
+// throw new UnsupportedOperationException();
+// }
+
+ public void setRollbackOnly()
+// throws IllegalStateException, SystemException
+ {
+ status = tsa.getMarkedRollbackStatus();
+ }
+
+ @Override
+ public int hashCode() {
+ return xid.hashCode();
+ }
+
+ Xid getXid() {
+ return xid;
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/**
+ * Simple implementation of an XA transaction manager.
+ */
+public class SimpleTransactionManager
+// implements TransactionManager, UserTransaction
+ implements WorkControl, WorkTransaction {
+ private ThreadLocal<SimpleTransaction<Integer>> current = new ThreadLocal<SimpleTransaction<Integer>>();
+
+ private Map<Xid, SimpleTransaction<Integer>> knownTransactions = Collections
+ .synchronizedMap(new HashMap<Xid, SimpleTransaction<Integer>>());
+ private TransactionStatusAdapter<Integer> tsa = new JtaStatusAdapter();
+// private SyncRegistry syncRegistry = new SyncRegistry();
+
+ /*
+ * WORK IMPLEMENTATION
+ */
+ @Override
+ public <T> T required(Callable<T> work) {
+ T res;
+ begin();
+ try {
+ res = work.call();
+ commit();
+ } catch (Exception e) {
+ rollback();
+ throw new SimpleRollbackException(e);
+ }
+ return res;
+ }
+
+ @Override
+ public WorkContext getWorkContext() {
+ return new WorkContext() {
+
+ @Override
+ public void registerXAResource(XAResource resource, String recoveryId) {
+ getTransaction().enlistResource(resource);
+ }
+ };
+ }
+
+ /*
+ * WORK TRANSACTION IMPLEMENTATION
+ */
+
+ @Override
+ public boolean isNoTransactionStatus() {
+ return tsa.getNoTransactionStatus().equals(getStatus());
+ }
+
+ /*
+ * JTA IMPLEMENTATION
+ */
+
+ public void begin()
+// throws NotSupportedException, SystemException
+ {
+ if (getCurrent() != null)
+ throw new UnsupportedOperationException("Nested transactions are not supported");
+ SimpleTransaction<Integer> transaction = new SimpleTransaction<Integer>(this, tsa);
+ knownTransactions.put(transaction.getXid(), transaction);
+ current.set(transaction);
+ }
+
+ public void commit()
+// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
+// SecurityException, IllegalStateException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().commit();
+ }
+
+ public int getStatus()
+// throws SystemException
+ {
+ if (getCurrent() == null)
+ return tsa.getNoTransactionStatus();
+ return getTransaction().getStatus();
+ }
+
+ public SimpleTransaction<Integer> getTransaction()
+// throws SystemException
+ {
+ return getCurrent();
+ }
+
+ protected SimpleTransaction<Integer> getCurrent()
+// throws SystemException
+ {
+ SimpleTransaction<Integer> transaction = current.get();
+ if (transaction == null)
+ return null;
+ Integer status = transaction.getStatus();
+ if (status.equals(tsa.getCommittedStatus()) || status.equals(tsa.getRolledBackStatus())) {
+ current.remove();
+ return null;
+ }
+ return transaction;
+ }
+
+ void unregister(Xid xid) {
+ knownTransactions.remove(xid);
+ }
+
+ public void resume(SimpleTransaction<Integer> tobj)
+// throws InvalidTransactionException, IllegalStateException, SystemException
+ {
+ if (getCurrent() != null)
+ throw new IllegalStateException("Transaction " + current.get() + " already registered");
+ current.set(tobj);
+ }
+
+ public void rollback()
+// throws IllegalStateException, SecurityException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().rollback();
+ }
+
+ public void setRollbackOnly()
+// throws IllegalStateException, SystemException
+ {
+ if (getCurrent() == null)
+ throw new IllegalStateException("No transaction registered with the current thread.");
+ getCurrent().setRollbackOnly();
+ }
+
+ public void setTransactionTimeout(int seconds)
+// throws SystemException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public SimpleTransaction<Integer> suspend()
+// throws SystemException
+ {
+ SimpleTransaction<Integer> transaction = getCurrent();
+ current.remove();
+ return transaction;
+ }
+
+// public TransactionSynchronizationRegistry getTsr() {
+// return syncRegistry;
+// }
+//
+// private class SyncRegistry implements TransactionSynchronizationRegistry {
+// @Override
+// public Object getTransactionKey() {
+// try {
+// SimpleTransaction transaction = getCurrent();
+// if (transaction == null)
+// return null;
+// return getCurrent().getXid();
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get transaction key", e);
+// }
+// }
+//
+// @Override
+// public void putResource(Object key, Object value) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public Object getResource(Object key) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public void registerInterposedSynchronization(Synchronization sync) {
+// throw new UnsupportedOperationException();
+// }
+//
+// @Override
+// public int getTransactionStatus() {
+// try {
+// return getStatus();
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get status", e);
+// }
+// }
+//
+// @Override
+// public boolean getRollbackOnly() {
+// try {
+// return getStatus() == Status.STATUS_MARKED_ROLLBACK;
+// } catch (SystemException e) {
+// throw new IllegalStateException("Cannot get status", e);
+// }
+// }
+//
+// @Override
+// public void setRollbackOnly() {
+// try {
+// getCurrent().setRollbackOnly();
+// } catch (Exception e) {
+// throw new IllegalStateException("Cannot set rollback only", e);
+// }
+// }
+//
+// }
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+/** Abstract the various approaches to represent transaction status. */
+public interface TransactionStatusAdapter<T> {
+ T getActiveStatus();
+
+ T getPreparingStatus();
+
+ T getMarkedRollbackStatus();
+
+ T getPreparedStatus();
+
+ T getCommittingStatus();
+
+ T getCommittedStatus();
+
+ T getRollingBackStatus();
+
+ T getRolledBackStatus();
+
+ T getNoTransactionStatus();
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.io.Serializable;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.transaction.xa.Xid;
+
+/**
+ * Implementation of {@link Xid} based on {@link UUID}, using max significant
+ * bits as global transaction id, and least significant bits as branch
+ * qualifier.
+ */
+public class UuidXid implements Xid, Serializable {
+ private static final long serialVersionUID = -5380531989917886819L;
+ public final static int FORMAT = (int) serialVersionUID;
+
+ private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
+
+ private final int format;
+ private final byte[] globalTransactionId;
+ private final byte[] branchQualifier;
+ private final String uuid;
+ private final int hashCode;
+
+ public UuidXid() {
+ this(UUID.randomUUID());
+ }
+
+ public UuidXid(UUID uuid) {
+ this.format = FORMAT;
+ this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
+ this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
+ this.uuid = uuid.toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ public UuidXid(Xid xid) {
+ this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
+ .getBranchQualifier());
+ }
+
+ private UuidXid(int format, byte[] globalTransactionId,
+ byte[] branchQualifier) {
+ this.format = format;
+ this.globalTransactionId = globalTransactionId;
+ this.branchQualifier = branchQualifier;
+ this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
+ .toString();
+ this.hashCode = uuid.hashCode();
+ }
+
+ @Override
+ public int getFormatId() {
+ return format;
+ }
+
+ @Override
+ public byte[] getGlobalTransactionId() {
+ return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
+ }
+
+ @Override
+ public byte[] getBranchQualifier() {
+ return Arrays.copyOf(branchQualifier, branchQualifier.length);
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj instanceof UuidXid) {
+ UuidXid that = (UuidXid) obj;
+ return Arrays.equals(globalTransactionId, that.globalTransactionId)
+ && Arrays.equals(branchQualifier, that.branchQualifier);
+ }
+ if (obj instanceof Xid) {
+ Xid that = (Xid) obj;
+ return Arrays.equals(globalTransactionId,
+ that.getGlobalTransactionId())
+ && Arrays
+ .equals(branchQualifier, that.getBranchQualifier());
+ }
+ return uuid.equals(obj.toString());
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new UuidXid(format, globalTransactionId, branchQualifier);
+ }
+
+ @Override
+ public String toString() {
+ return uuid;
+ }
+
+ public UUID asUuid() {
+ return bytesToUUID(globalTransactionId, branchQualifier);
+ }
+
+ public static byte[] uuidToBytes(long bits) {
+ ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
+ buffer.putLong(0, bits);
+ return buffer.array();
+ }
+
+ public static UUID bytesToUUID(byte[] most, byte[] least) {
+ if (most.length < BYTES_PER_LONG)
+ most = Arrays.copyOf(most, BYTES_PER_LONG);
+ if (least.length < BYTES_PER_LONG)
+ least = Arrays.copyOf(least, BYTES_PER_LONG);
+ ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
+ buffer.put(most, 0, BYTES_PER_LONG);
+ buffer.put(least, 0, BYTES_PER_LONG);
+ buffer.flip();
+ return new UUID(buffer.getLong(), buffer.getLong());
+ }
+
+ // public static void main(String[] args) {
+ // UUID uuid = UUID.randomUUID();
+ // System.out.println(uuid);
+ // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
+ // uuidToBytes(uuid.getLeastSignificantBits()));
+ // System.out.println(uuid);
+ // }
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import javax.transaction.xa.XAResource;
+
+/**
+ * A minimalistic interface similar to OSGi transaction context in order to
+ * register XA resources.
+ */
+public interface WorkContext {
+ void registerXAResource(XAResource resource, String recoveryId);
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A minimalistic interface inspired by OSGi transaction control in order to
+ * commit units of work externally.
+ */
+public interface WorkControl {
+ <T> T required(Callable<T> work);
+
+ void setRollbackOnly();
+
+ WorkContext getWorkContext();
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+/**
+ * A minimalistic interface inspired by JTA user transaction in order to commit
+ * units of work externally.
+ */
+public interface WorkTransaction {
+ void begin();
+
+ void commit();
+
+ void rollback();
+
+ boolean isNoTransactionStatus();
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.Map;
+
+public interface WorkingCopy<DATA, ATTR, ID> {
+ void startEditing(DATA user);
+
+ boolean noModifications();
+
+ void cleanUp();
+
+ Map<ID, DATA> getNewData();
+
+ Map<ID, DATA> getDeletedData();
+
+ Map<ID, ATTR> getModifiedData();
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+public interface WorkingCopyProcessor<WC extends WorkingCopy<?, ?, ?>> {
+ void prepare(WC wc);
+
+ void commit(WC wc);
+
+ void rollback(WC wc);
+
+ WC newWorkingCopy();
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+/** {@link XAResource} for a user directory being edited. */
+public class WorkingCopyXaResource<WC extends WorkingCopy<?, ?, ?>> implements XAResource {
+ private final WorkingCopyProcessor<WC> processor;
+
+ private Map<Xid, WC> workingCopies = new HashMap<Xid, WC>();
+ private Xid editingXid = null;
+ private int transactionTimeout = 0;
+
+ public WorkingCopyXaResource(WorkingCopyProcessor<WC> processor) {
+ this.processor = processor;
+ }
+
+ @Override
+ public synchronized void start(Xid xid, int flags) throws XAException {
+ if (editingXid != null)
+ throw new IllegalStateException("Already editing " + editingXid);
+ WC wc = workingCopies.put(xid, processor.newWorkingCopy());
+ if (wc != null)
+ throw new IllegalStateException("There is already a working copy for " + xid);
+ this.editingXid = xid;
+ }
+
+ @Override
+ public void end(Xid xid, int flags) throws XAException {
+ checkXid(xid);
+ }
+
+ private WC wc(Xid xid) {
+ return workingCopies.get(xid);
+ }
+
+ public synchronized WC wc() {
+ if (editingXid == null)
+ return null;
+ WC wc = workingCopies.get(editingXid);
+ if (wc == null)
+ throw new IllegalStateException("No working copy found for " + editingXid);
+ return wc;
+ }
+
+ private synchronized void cleanUp(Xid xid) {
+ WC wc = workingCopies.get(xid);
+ if (wc != null) {
+ wc.cleanUp();
+ workingCopies.remove(xid);
+ }
+ editingXid = null;
+ }
+
+ @Override
+ public int prepare(Xid xid) throws XAException {
+ checkXid(xid);
+ WC wc = wc(xid);
+ if (wc.noModifications())
+ return XA_RDONLY;
+ try {
+ processor.prepare(wc);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new XAException(XAException.XAER_RMERR);
+ }
+ return XA_OK;
+ }
+
+ @Override
+ public void commit(Xid xid, boolean onePhase) throws XAException {
+ try {
+ checkXid(xid);
+ WC wc = wc(xid);
+ if (wc.noModifications())
+ return;
+ if (onePhase)
+ processor.prepare(wc);
+ processor.commit(wc);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new XAException(XAException.XAER_RMERR);
+ } finally {
+ cleanUp(xid);
+ }
+ }
+
+ @Override
+ public void rollback(Xid xid) throws XAException {
+ try {
+ checkXid(xid);
+ processor.rollback(wc(xid));
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new XAException(XAException.XAER_RMERR);
+ } finally {
+ cleanUp(xid);
+ }
+ }
+
+ @Override
+ public void forget(Xid xid) throws XAException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isSameRM(XAResource xares) throws XAException {
+ return xares == this;
+ }
+
+ @Override
+ public Xid[] recover(int flag) throws XAException {
+ return new Xid[0];
+ }
+
+ @Override
+ public int getTransactionTimeout() throws XAException {
+ return transactionTimeout;
+ }
+
+ @Override
+ public boolean setTransactionTimeout(int seconds) throws XAException {
+ transactionTimeout = seconds;
+ return true;
+ }
+
+ private void checkXid(Xid xid) throws XAException {
+ if (xid == null)
+ throw new XAException(XAException.XAER_OUTSIDE);
+ if (!xid.equals(xid))
+ throw new XAException(XAException.XAER_NOTA);
+ }
+
+}
--- /dev/null
+package org.argeo.api.cms.transaction;
+
+import javax.transaction.xa.XAResource;
+
+public interface XAResourceProvider {
+ XAResource getXaResource();
+}
--- /dev/null
+/** Minimalistic and partial XA transaction manager implementation. */
+package org.argeo.api.cms.transaction;
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
+ <attributes>
+ <attribute name="module" value="true"/>
+ </attributes>
+ </classpathentry>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.api.register</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+Import-Package: org.osgi.*;version=0.0.0,\
+!org.apache.commons.logging,\
+*
--- /dev/null
+source.. = src/
\ No newline at end of file
--- /dev/null
+package org.argeo.api.register;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+/**
+ * A wrapper for an object, whose dependencies and life cycle can be managed.
+ */
+public class Component<I> implements Supplier<I>, Comparable<Component<?>> {
+
+ private final I instance;
+
+ private final Runnable init;
+ private final Runnable close;
+
+ private final Map<Class<? super I>, PublishedType<? super I>> types;
+ private final Set<Dependency<?>> dependencies;
+ private final Map<String, Object> properties;
+
+ private CompletableFuture<Void> activationStarted = null;
+ private CompletableFuture<Void> activated = null;
+
+ private CompletableFuture<Void> deactivationStarted = null;
+ private CompletableFuture<Void> deactivated = null;
+
+ // internal
+ private Set<Dependency<?>> dependants = new HashSet<>();
+
+ private RankingKey rankingKey;
+
+ Component(ComponentRegister register, I instance, Runnable init, Runnable close, Set<Dependency<?>> dependencies,
+ Set<Class<? super I>> classes, Map<String, Object> properties) {
+ assert instance != null;
+ assert init != null;
+ assert close != null;
+ assert dependencies != null;
+ assert classes != null;
+
+ this.instance = instance;
+ this.init = init;
+ this.close = close;
+
+ // types
+ Map<Class<? super I>, PublishedType<? super I>> types = new HashMap<>(classes.size());
+ for (Class<? super I> clss : classes) {
+// if (!clss.isAssignableFrom(instance.getClass()))
+// throw new IllegalArgumentException(
+// "Type " + clss.getName() + " is not compatible with " + instance.getClass().getName());
+ types.put(clss, new PublishedType<>(this, clss));
+ }
+ this.types = Collections.unmodifiableMap(types);
+
+ // dependencies
+ this.dependencies = Collections.unmodifiableSet(new HashSet<>(dependencies));
+ for (Dependency<?> dependency : this.dependencies) {
+ dependency.setDependantComponent(this);
+ }
+
+ // deactivated by default
+ deactivated = CompletableFuture.completedFuture(null);
+ deactivationStarted = CompletableFuture.completedFuture(null);
+
+ // TODO check whether context is active, so that we start right away
+ prepareNextActivation();
+
+ long serviceId = register.register(this);
+ Map<String, Object> props = new HashMap<>(properties);
+ props.put(RankingKey.SERVICE_ID, serviceId);
+ this.properties = Collections.unmodifiableMap(props);
+ rankingKey = new RankingKey(properties);
+ }
+
+ private void prepareNextActivation() {
+ activationStarted = new CompletableFuture<Void>();
+ activated = activationStarted //
+ .thenComposeAsync(this::dependenciesActivated) //
+ .thenRun(this.init) //
+ .thenRun(() -> prepareNextDeactivation());
+ }
+
+ private void prepareNextDeactivation() {
+ deactivationStarted = new CompletableFuture<Void>();
+ deactivated = deactivationStarted //
+ .thenComposeAsync(this::dependantsDeactivated) //
+ .thenRun(this.close) //
+ .thenRun(() -> prepareNextActivation());
+ }
+
+ CompletableFuture<Void> getActivated() {
+ return activated;
+ }
+
+ CompletableFuture<Void> getDeactivated() {
+ return deactivated;
+ }
+
+ void startActivating() {
+ if (activated.isDone() || activationStarted.isDone())
+ return;
+ activationStarted.complete(null);
+ }
+
+ void startDeactivating() {
+ if (deactivated.isDone() || deactivationStarted.isDone())
+ return;
+ deactivationStarted.complete(null);
+ }
+
+ CompletableFuture<Void> dependenciesActivated(Void v) {
+ Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependencies.size());
+ for (Dependency<?> dependency : this.dependencies) {
+ CompletableFuture<Void> dependencyActivated = dependency.publisherActivated() //
+ .thenCompose(dependency::set);
+ constraints.add(dependencyActivated);
+ }
+ return CompletableFuture.allOf(constraints.toArray(new CompletableFuture[constraints.size()]));
+ }
+
+ CompletableFuture<Void> dependantsDeactivated(Void v) {
+ Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependants.size());
+ for (Dependency<?> dependant : this.dependants) {
+ CompletableFuture<Void> dependantDeactivated = dependant.dependantDeactivated() //
+ .thenCompose(dependant::unset);
+ constraints.add(dependantDeactivated);
+ }
+ CompletableFuture<Void> dependantsDeactivated = CompletableFuture
+ .allOf(constraints.toArray(new CompletableFuture[constraints.size()]));
+ return dependantsDeactivated;
+
+ }
+
+ void addDependant(Dependency<?> dependant) {
+ dependants.add(dependant);
+ }
+
+ @Override
+ public I get() {
+ return instance;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> PublishedType<T> getType(Class<T> clss) {
+ if (!types.containsKey(clss))
+ throw new IllegalArgumentException(clss.getName() + " is not a type published by this component");
+ return (PublishedType<T>) types.get(clss);
+ }
+
+ public <T> boolean isPublishedType(Class<T> clss) {
+ return types.containsKey(clss);
+ }
+
+ public Map<String, Object> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public int compareTo(Component<?> o) {
+ return rankingKey.compareTo(rankingKey);
+ }
+
+ @Override
+ public int hashCode() {
+ Long serviceId = (Long) properties.get(RankingKey.SERVICE_ID);
+ if (serviceId != null)
+ return serviceId.intValue();
+ else
+ return super.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ List<String> classes = new ArrayList<>();
+ for (Class<?> clss : types.keySet()) {
+ classes.add(clss.getName());
+ }
+ return "Component " + classes + " " + properties + "";
+ }
+
+ /** A type which has been explicitly exposed by a component. */
+ public static class PublishedType<T> {
+ private Component<? extends T> component;
+ private Class<T> clss;
+
+ private CompletableFuture<T> value;
+
+ public PublishedType(Component<? extends T> component, Class<T> clss) {
+ this.clss = clss;
+ this.component = component;
+ value = CompletableFuture.completedFuture((T) component.instance);
+ }
+
+ public Component<?> getPublisher() {
+ return component;
+ }
+
+ public Class<T> getType() {
+ return clss;
+ }
+
+ public CompletionStage<T> getValue() {
+ return value.minimalCompletionStage();
+ }
+ }
+
+ /** Builds a {@link Component}. */
+ public static class Builder<I> implements Supplier<I> {
+ private final I instance;
+
+ private Runnable init;
+ private Runnable close;
+
+ private Set<Dependency<?>> dependencies = new HashSet<>();
+ private Set<Class<? super I>> types = new HashSet<>();
+ private final Map<String, Object> properties = new HashMap<>();
+
+ public Builder(I instance) {
+ this.instance = instance;
+ }
+
+ public Component<I> build(ComponentRegister register) {
+ // default values
+ if (types.isEmpty()) {
+ types.add(getInstanceClass());
+ }
+
+ if (init == null)
+ init = () -> {
+ };
+ if (close == null)
+ close = () -> {
+ };
+
+ // instantiation
+ Component<I> component = new Component<I>(register, instance, init, close, dependencies, types, properties);
+ for (Dependency<?> dependency : dependencies) {
+ dependency.type.getPublisher().addDependant(dependency);
+ }
+ return component;
+ }
+
+ public Builder<I> addType(Class<? super I> clss) {
+ types.add(clss);
+ return this;
+ }
+
+ public Builder<I> addActivation(Runnable init) {
+ if (this.init != null)
+ throw new IllegalArgumentException("init method is already set");
+ this.init = init;
+ return this;
+ }
+
+ public Builder<I> addDeactivation(Runnable close) {
+ if (this.close != null)
+ throw new IllegalArgumentException("close method is already set");
+ this.close = close;
+ return this;
+ }
+
+ public <D> Builder<I> addDependency(PublishedType<D> type, Consumer<D> set, Consumer<D> unset) {
+ dependencies.add(new Dependency<D>(type, set, unset));
+ return this;
+ }
+
+ public void addProperty(String key, Object value) {
+ if (properties.containsKey(key))
+ throw new IllegalStateException("Key " + key + " is already set.");
+ properties.put(key, value);
+ }
+
+ @Override
+ public I get() {
+ return instance;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<I> getInstanceClass() {
+ return (Class<I>) instance.getClass();
+ }
+
+ }
+
+ static class Dependency<D> {
+ private PublishedType<D> type;
+ private Consumer<D> set;
+ private Consumer<D> unset;
+
+ // live
+ Component<?> dependantComponent;
+ CompletableFuture<Void> setStage;
+ CompletableFuture<Void> unsetStage;
+
+ public Dependency(PublishedType<D> types, Consumer<D> set, Consumer<D> unset) {
+ super();
+ this.type = types;
+ this.set = set != null ? set : t -> {
+ };
+ this.unset = unset != null ? unset : t -> {
+ };
+ }
+
+ // live
+ void setDependantComponent(Component<?> component) {
+ this.dependantComponent = component;
+ }
+
+ CompletableFuture<Void> publisherActivated() {
+ return type.getPublisher().activated.copy();
+ }
+
+ CompletableFuture<Void> dependantDeactivated() {
+ return dependantComponent.deactivated.copy();
+ }
+
+ CompletableFuture<Void> set(Void v) {
+ return type.value.thenAccept(set);
+ }
+
+ CompletableFuture<Void> unset(Void v) {
+ return type.value.thenAccept(unset);
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.api.register;
+
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.function.Predicate;
+
+/** A register of components which can coordinate their activation. */
+public interface ComponentRegister {
+ long register(Component<?> component);
+
+ <T> SortedSet<Component<? extends T>> find(Class<T> clss, Predicate<Map<String, Object>> filter);
+
+ default <T> Component.PublishedType<T> getSingleton(Class<T> type) {
+ SortedSet<Component<? extends T>> found = find(type, null);
+ if (found.size() == 0)
+ throw new IllegalStateException("No component found for " + type);
+ return found.first().getType(type);
+ }
+
+ default <T> T getObject(Class<T> clss) {
+ SortedSet<Component<? extends T>> found = find(clss, null);
+ if (found.size() == 0)
+ return null;
+ return found.first().get();
+ }
+
+ Component<?> get(Object instance);
+
+// default <T> PublishedType<T> getType(Class<T> clss) {
+// SortedSet<Component<? extends T>> components = find(clss, null);
+// if (components.size() == 0)
+// return null;
+// return components.first().getType(clss);
+// }
+
+ void activate();
+
+ void deactivate();
+
+ boolean isActive();
+
+ void clear();
+}
--- /dev/null
+package org.argeo.api.register;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Key used to classify and filter available components.
+ */
+public class RankingKey implements Comparable<RankingKey> {
+ public final static String SERVICE_PID = "service.pid";
+ public final static String SERVICE_ID = "service.id";
+ public final static String SERVICE_RANKING = "service.ranking";
+
+ private String pid;
+ private Integer ranking = 0;
+ private Long id = 0l;
+
+ public RankingKey(String pid, Integer ranking, Long id) {
+ super();
+ this.pid = pid;
+ this.ranking = ranking;
+ this.id = id;
+ }
+
+ public RankingKey(Map<String, Object> properties) {
+ this.pid = properties.containsKey(SERVICE_PID) ? properties.get(SERVICE_PID).toString() : null;
+ this.ranking = properties.containsKey(SERVICE_RANKING)
+ ? Integer.parseInt(properties.get(SERVICE_RANKING).toString())
+ : 0;
+ this.id = properties.containsKey(SERVICE_ID) ? (Long) properties.get(SERVICE_ID) : null;
+ }
+
+ @Override
+ public int hashCode() {
+ Integer result = 0;
+ if (pid != null)
+ result = +pid.hashCode();
+ if (ranking != null)
+ result = +ranking;
+ return result;
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new RankingKey(pid, ranking, id);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("");
+ if (pid != null)
+ sb.append(pid);
+ if (ranking != null && ranking != 0)
+ sb.append(' ').append(ranking);
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RankingKey))
+ return false;
+ RankingKey other = (RankingKey) obj;
+ return Objects.equals(pid, other.pid) && Objects.equals(ranking, other.ranking) && Objects.equals(id, other.id);
+ }
+
+ @Override
+ public int compareTo(RankingKey o) {
+ if (pid != null && o.pid != null) {
+ if (pid.equals(o.pid)) {
+ if (ranking.equals(o.ranking))
+ if (id != null && o.id != null)
+ return id.compareTo(o.id);
+ else
+ return 0;
+ else
+ return ranking.compareTo(o.ranking);
+ } else {
+ return pid.compareTo(o.pid);
+ }
+
+ } else {
+ }
+ return -1;
+ }
+
+ public String getPid() {
+ return pid;
+ }
+
+ public Integer getRanking() {
+ return ranking;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public static RankingKey minPid(String pid) {
+ return new RankingKey(pid, Integer.MIN_VALUE, null);
+ }
+
+ public static RankingKey maxPid(String pid) {
+ return new RankingKey(pid, Integer.MAX_VALUE, null);
+ }
+}
--- /dev/null
+package org.argeo.api.register;
+
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Predicate;
+
+/** A minimal component register. */
+public class SimpleRegister implements ComponentRegister {
+ private final AtomicBoolean started = new AtomicBoolean(false);
+ private final IdentityHashMap<Object, Component<?>> components = new IdentityHashMap<>();
+ private final AtomicLong nextServiceId = new AtomicLong(0l);
+
+ @Override
+ public long register(Component<?> component) {
+ return registerComponent(component);
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ @Override
+ public synchronized <T> SortedSet<Component<? extends T>> find(Class<T> clss,
+ Predicate<Map<String, Object>> filter) {
+ SortedSet<Component<? extends T>> result = new TreeSet<>();
+ instances: for (Object instance : components.keySet()) {
+ if (!clss.isAssignableFrom(instance.getClass()))
+ continue instances;
+ Component<? extends T> component = (Component<? extends T>) components.get(instance);
+
+ if (component.isPublishedType(clss)) {
+ if (filter != null) {
+ filter.test(component.getProperties());
+ }
+ result.add(component);
+ }
+ }
+ if (result.isEmpty())
+ return null;
+ return result;
+
+ }
+
+ synchronized long registerComponent(Component<?> component) {
+ if (started.get()) // TODO make it really dynamic
+ throw new IllegalStateException("Already activated");
+ if (components.containsKey(component.get()))
+ throw new IllegalArgumentException("Already registered as component");
+ components.put(component.get(), component);
+ return nextServiceId.incrementAndGet();
+ }
+
+ @Override
+ public synchronized Component<?> get(Object instance) {
+ if (!components.containsKey(instance))
+ throw new IllegalArgumentException("Not registered as component");
+ return components.get(instance);
+ }
+
+ @Override
+ public synchronized void activate() {
+ if (started.get())
+ throw new IllegalStateException("Already activated");
+ Set<CompletableFuture<?>> constraints = new HashSet<>();
+ for (Component<?> component : components.values()) {
+ component.startActivating();
+ constraints.add(component.getActivated());
+ }
+
+ // wait
+ try {
+ CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(true))
+ .get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Register activation has been interrupted", e);
+ } catch (ExecutionException e) {
+ if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
+ throw (RuntimeException) e.getCause();
+ } else {
+ throw new IllegalStateException("Cannot activate register", e.getCause());
+ }
+ }
+ }
+
+ @Override
+ public synchronized void deactivate() {
+ if (!started.get())
+ throw new IllegalStateException("Not activated");
+ Set<CompletableFuture<?>> constraints = new HashSet<>();
+ for (Component<?> component : components.values()) {
+ component.startDeactivating();
+ constraints.add(component.getDeactivated());
+ }
+
+ // wait
+ try {
+ CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(false))
+ .get();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Register deactivation has been interrupted", e);
+ } catch (ExecutionException e) {
+ if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
+ throw (RuntimeException) e.getCause();
+ } else {
+ throw new IllegalStateException("Cannot deactivate register", e.getCause());
+ }
+ }
+ }
+
+ @Override
+ public synchronized boolean isActive() {
+ return started.get();
+ }
+
+ @Override
+ public synchronized void clear() {
+ components.clear();
+ }
+}
@Override
public long getMostSignificantBits() {
long timestamp = useTimestamp();
- long mostSig = UuidFactory.MOST_SIG_VERSION1 | ((timestamp & 0xFFFFFFFFL) << 32) // time_low
- | (((timestamp >> 32) & 0xFFFFL) << 16) // time_mid
- | ((timestamp >> 48) & 0x0FFFL);// time_hi_and_version
+ long mostSig = TimeUuid.toMostSignificantBits(timestamp);
return mostSig;
}
Duration duration = Duration.between(TimeUuid.TIMESTAMP_ZERO, instant);
return durationToTimestamp(duration);
}
+
+ /**
+ * Crate a time UUID with this instant as timestamp and clock and node id set to
+ * zero.
+ */
+ public static UUID fromInstant(Instant instant) {
+ long timestamp = instantToTimestamp(instant);
+ long mostSig = toMostSignificantBits(timestamp);
+ UUID uuid = new UUID(mostSig, UuidFactory.LEAST_SIG_RFC4122_VARIANT);
+ return uuid;
+ }
+
+ /** Convert timestamp in UUID format to most significant bits of a time UUID. */
+ static long toMostSignificantBits(long timestamp) {
+ long mostSig = UuidFactory.MOST_SIG_VERSION1 | ((timestamp & 0xFFFFFFFFL) << 32) // time_low
+ | (((timestamp >> 32) & 0xFFFFL) << 16) // time_mid
+ | ((timestamp >> 48) & 0x0FFFL);// time_hi_and_version
+ return mostSig;
+ }
}
+Main-Class: org.argeo.cms.cli.ArgeoCli
+
+Class-Path: \
+org.argeo.api.acr.2.3.jar \
+org.argeo.api.cli.2.3.jar \
+org.argeo.api.cms.2.3.jar \
+org.argeo.api.uuid.2.3.jar \
+org.argeo.cms.2.3.jar \
+org.argeo.cms.ee.2.3.jar \
+../osgi/equinox/org.argeo.cms/org.argeo.cms.lib.equinox.2.3.jar \
+org.argeo.cms.lib.jetty.2.3.jar \
+org.argeo.cms.lib.sshd.2.3.jar \
+org.argeo.cms.ux.2.3.jar \
+org.argeo.init.2.3.jar \
+org.argeo.util.2.3.jar \
+../org.argeo.tp/com.fasterxml.jackson.core.jackson-annotations.2.13.jar \
+../org.argeo.tp/com.fasterxml.jackson.core.jackson-core.2.13.jar \
+../org.argeo.tp/com.fasterxml.jackson.core.jackson-databind.2.13.jar \
+../org.argeo.tp/com.googlecode.javaewah.JavaEWAH.1.1.jar \
+../org.argeo.tp/de.thjom.java.systemd.2.1.jar \
+../org.argeo.tp/javax.servlet.4.0.jar \
+../org.argeo.tp/javax.websocket.1.1.jar \
+../org.argeo.tp/org.apache.batik.1.16.jar \
+../org.argeo.tp/org.apache.batik.constants.1.16.jar \
+../org.argeo.tp/org.apache.batik.css.1.16.jar \
+../org.argeo.tp/org.apache.batik.i18n.1.16.jar \
+../org.argeo.tp/org.apache.batik.util.1.16.jar \
+../org.argeo.tp/org.apache.commons.cli.1.5.jar \
+../org.argeo.tp/org.apache.commons.fileupload.1.4.jar \
+../org.argeo.tp/org.apache.commons.io.2.11.jar \
+../org.argeo.tp/org.apache.httpcomponents.httpclient.4.5.jar \
+../org.argeo.tp/org.apache.httpcomponents.httpcore.4.4.jar \
+../org.argeo.tp/org.apache.httpcomponents.httpmime.4.5.jar \
+../org.argeo.tp/org.apache.xalan.2.7.jar \
+../org.argeo.tp/org.apache.xerces.2.12.jar \
+../org.argeo.tp/org.apache.xmlgraphics.2.7.jar \
+../org.argeo.tp/org.apache.xml.resolver.1.2.jar \
+../org.argeo.tp/org.argeo.ext.slf4j.2.3.jar \
+../org.argeo.tp/org.eclipse.jgit.6.3.jar \
+../org.argeo.tp/org.freeedesktop.dbus.4.2.jar \
+../org.argeo.tp/org.slf4j.api.1.7.jar \
+../org.argeo.tp/org.slf4j.commons.logging.1.7.jar \
+../org.argeo.tp/org.w3c.css.sac.1.3.jar \
+../org.argeo.tp/org.w3c.dom.smil.1.0.jar \
+../org.argeo.tp/org.w3c.dom.svg.1.1.jar \
+../org.argeo.tp.crypto/bcmail.1.72.jar \
+../org.argeo.tp.crypto/bcpg.1.72.jar \
+../org.argeo.tp.crypto/bcpkix.1.72.jar \
+../org.argeo.tp.crypto/bcprov.1.72.jar \
+../org.argeo.tp.crypto/bcutil.1.72.jar \
+../org.argeo.tp.crypto/net.i2p.crypto.eddsa.0.3.jar \
+../org.argeo.tp.crypto/org.apache.sshd.2.9.jar \
+../org.argeo.tp.crypto/org.apache.sshd.cli.2.9.jar \
+../org.argeo.tp.crypto/org.apache.sshd.git.2.9.jar \
+../org.argeo.tp.crypto/org.apache.sshd.putty.2.9.jar \
+../org.argeo.tp.crypto/org.apache.sshd.scp.2.9.jar \
+../org.argeo.tp.crypto/org.apache.sshd.sftp.2.9.jar \
+../org.argeo.tp.crypto/org.apache.tomcat.jni.9.0.jar \
Option.builder("D").hasArgs().argName("property=value").desc("use value for given property").build());
// common
+ addCommandsCli(new CmsCommands("cms"));
addCommandsCli(new SshCli("ssh"));
addCommandsCli(new PosixCommands("posix"));
addCommandsCli(new FsCommands("fs"));
@Override
public String getDescription() {
- return "Argeo utilities";
+ return "Argeo CMS utilities";
+ }
+
+ public static void main(String[] args) {
+ mainImpl(new ArgeoCli("argeo"), args);
}
}
--- /dev/null
+package org.argeo.cms.cli;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.Options;
+import org.argeo.api.cli.CommandsCli;
+import org.argeo.api.cli.DescribedCommand;
+import org.argeo.cms.client.CmsClient;
+import org.argeo.cms.client.WebSocketPing;
+
+/** Commands dealing with CMS. */
+public class CmsCommands extends CommandsCli {
+ final static Option connectOption = Option.builder().option("c").longOpt("connect").desc("server to connect to")
+ .hasArg(true).build();
+
+ public CmsCommands(String commandName) {
+ super(commandName);
+ addCommand("ping", new Ping());
+ addCommand("get", new Get());
+ addCommand("status", new Status());
+ addCommand("event", new EventCommands("event"));
+ }
+
+ @Override
+ public String getDescription() {
+ return "Utilities related to an Argeo CMS";
+ }
+
+ class Ping implements DescribedCommand<Void> {
+ @Override
+ public Options getOptions() {
+ Options options = new Options();
+ options.addOption(connectOption);
+ return options;
+ }
+
+ @Override
+ public Void apply(List<String> t) {
+ CommandLine line = toCommandLine(t);
+ String uriArg = line.getOptionValue(connectOption);
+ // TODO make it more robust (trailing /, etc.)
+ URI uri = URI.create(uriArg);
+ if ("".equals(uri.getPath())) {
+ uri = URI.create(uri.toString() + "/cms/status/ping");
+ }
+ new WebSocketPing(uri).run();
+ return null;
+ }
+
+ @Override
+ public String getUsage() {
+ return "[ws|wss]://host:port/";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Test whether an Argeo CMS is available, without auhtentication";
+ }
+
+ }
+
+ class Get implements DescribedCommand<String> {
+
+ @Override
+ public Options getOptions() {
+ Options options = new Options();
+ options.addOption(connectOption);
+ return options;
+ }
+
+ @Override
+ public String apply(List<String> t) {
+ CommandLine line = toCommandLine(t);
+ List<String> remaining = line.getArgList();
+ String additionalUri = null;
+ if (remaining.size() != 0) {
+ additionalUri = remaining.get(0);
+ }
+
+ String connectUri = line.getOptionValue(connectOption);
+ CmsClient cmsClient = new CmsClient(URI.create(connectUri));
+ return additionalUri != null ? cmsClient.getAsString(URI.create(additionalUri)) : cmsClient.getAsString();
+ }
+
+ @Override
+ public String getUsage() {
+ return "[URI]";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Retrieve this URI as a string";
+ }
+
+ }
+
+ class Status implements DescribedCommand<String> {
+
+ @Override
+ public Options getOptions() {
+ Options options = new Options();
+ options.addOption(connectOption);
+ return options;
+ }
+
+ @Override
+ public String apply(List<String> t) {
+ CommandLine line = toCommandLine(t);
+ String connectUri = line.getOptionValue(connectOption);
+ CmsClient cmsClient = new CmsClient(URI.create(connectUri));
+ return cmsClient.getAsString(URI.create("/cms/status"));
+ }
+
+ @Override
+ public String getUsage() {
+ return "[URI]";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Retrieve the CMS status as a string";
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.cms.cli;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Options;
+import org.argeo.api.cli.CommandArgsException;
+import org.argeo.api.cli.CommandsCli;
+import org.argeo.api.cli.DescribedCommand;
+import org.argeo.cms.client.WebSocketEventClient;
+
+/** Commands dealing with CMS events. */
+public class EventCommands extends CommandsCli {
+ public EventCommands(String commandName) {
+ super(commandName);
+ addCommand("listen", new EventListent());
+ }
+
+ @Override
+ public String getDescription() {
+ return "Utilities related to an Argeo CMS";
+ }
+
+ class EventListent implements DescribedCommand<Void> {
+
+ @Override
+ public Options getOptions() {
+ Options options = new Options();
+ options.addOption(CmsCommands.connectOption);
+ return options;
+ }
+
+ @Override
+ public Void apply(List<String> t) {
+ CommandLine line = toCommandLine(t);
+ List<String> remaining = line.getArgList();
+ if (remaining.size() == 0) {
+ throw new CommandArgsException("There must be at least one argument");
+ }
+ String topic = remaining.get(0);
+
+ String uriArg = line.getOptionValue(CmsCommands.connectOption);
+ // TODO make it more robust (trailing /, etc.)
+ URI uri = URI.create(uriArg);
+ if ("".equals(uri.getPath())) {
+ uri = URI.create(uri.toString() + "/cms/status/event/" + topic);
+ }
+ new WebSocketEventClient(uri).run();
+ return null;
+ }
+
+ @Override
+ public String getUsage() {
+ return "TOPIC";
+ }
+
+ @Override
+ public String getDescription() {
+ return "Listen to events on a topic";
+ }
+
+ }
+}
<service>
<provide interface="com.sun.net.httpserver.HttpHandler"/>
</service>
- <property name="context.path" type="String" value="/cms/status"/>
+ <property name="context.path" type="String" value="/cms/status/"/>
<reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
</scr:component>
Import-Package:\
-org.argeo.util.http,\
org.osgi.service.http;version=0.0.0,\
org.osgi.service.http.whiteboard;version=0.0.0,\
org.osgi.framework.namespace;version=0.0.0,\
import javax.servlet.http.HttpServletResponse;
import org.argeo.api.cms.CmsLog;
-import org.argeo.util.ExceptionsChain;
+import org.argeo.cms.util.ExceptionsChain;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.argeo.api.cms.CmsAuth;
import org.argeo.api.cms.CmsSessionId;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.auth.RemoteAuthCallback;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
import org.argeo.cms.servlet.ServletHttpRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.argeo.api.acr.ldap.NamingUtils;
import org.argeo.api.cms.CmsAuth;
-import org.argeo.cms.CmsUserManager;
+import org.argeo.api.cms.directory.CmsUserManager;
import org.argeo.cms.auth.RemoteAuthCallback;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
import org.argeo.cms.servlet.ServletHttpRequest;
import org.argeo.cms.servlet.ServletHttpResponse;
-import org.argeo.util.naming.NamingUtils;
import org.osgi.service.useradmin.Authorization;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.IOException;
import java.net.URL;
-import java.net.http.HttpHeaders;
-import java.security.PrivilegedAction;
import java.util.Map;
-import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.servlet.http.HttpServletRequest;
import org.argeo.cms.auth.RemoteAuthResponse;
import org.argeo.cms.auth.RemoteAuthUtils;
import org.argeo.cms.servlet.internal.HttpUtils;
-import org.argeo.util.http.HttpHeader;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.http.context.ServletContextHelper;
}
@Override
- public void setHeader(String keys, String value) {
- response.setHeader(keys, value);
+ public void setHeader(String headerName, String value) {
+ response.setHeader(headerName, value);
+ }
+
+ @Override
+ public void addHeader(String headerName, String value) {
+ response.addHeader(headerName, value);
}
}
--- /dev/null
+package org.argeo.cms.servlet;
+
+import static org.argeo.cms.http.HttpHeader.VIA;
+import static org.argeo.cms.http.HttpHeader.X_FORWARDED_HOST;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+/** Servlet utilities. */
+public class ServletUtils {
+
+ /**
+ * The base URL for this query (without any path component (not even an ending
+ * '/'), taking into account reverse proxies.
+ */
+ public static StringBuilder getRequestUrlBase(HttpServletRequest req) {
+ List<String> viaHosts = new ArrayList<>();
+ for (Enumeration<String> it = req.getHeaders(VIA.getHeaderName()); it.hasMoreElements();) {
+ String[] arr = it.nextElement().split(" ");
+ viaHosts.add(arr[1]);
+ }
+
+ String outerHost = viaHosts.isEmpty() ? null : viaHosts.get(0);
+ if (outerHost == null) {
+ // Try non-standard header
+ String forwardedHost = req.getHeader(X_FORWARDED_HOST.getHeaderName());
+ if (forwardedHost != null) {
+ String[] arr = forwardedHost.split(",");
+ outerHost = arr[0];
+ }
+ }
+
+ URI requestUrl = URI.create(req.getRequestURL().toString());
+
+ boolean isReverseProxy = outerHost != null && !outerHost.equals(requestUrl.getHost());
+ if (isReverseProxy) {
+ String protocol = req.isSecure() ? "https" : "http";
+ return new StringBuilder(protocol + "://" + outerHost);
+ } else {
+ return new StringBuilder(requestUrl.getScheme() + "://" + requestUrl.getHost()
+ + (requestUrl.getPort() > 0 ? ":" + requestUrl.getPort() : ""));
+ }
+ }
+
+ /** singleton */
+ private ServletUtils() {
+ }
+}
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpPrincipal;
+/**
+ * An {@link HttpServlet} which integrates an {@link HttpContext} and its
+ * {@link Authenticator} in a servlet container.
+ */
public class HttpContextServlet extends HttpServlet {
private static final long serialVersionUID = 2321612280413662738L;
import com.sun.net.httpserver.HttpPrincipal;
import com.sun.net.httpserver.HttpsExchange;
-public class ServletHttpExchange extends HttpsExchange {
+/** Integrates {@link HttpsExchange} in a servlet container. */
+class ServletHttpExchange extends HttpsExchange {
private final HttpContext httpContext;
private final HttpServletRequest httpServletRequest;
private final HttpServletResponse httpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.io.IOUtils;
+import org.argeo.cms.osgi.FilterRequirement;
import org.argeo.cms.osgi.PublishNamespace;
-import org.argeo.osgi.util.FilterRequirement;
+import org.argeo.cms.util.StreamUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
}
try (InputStream in = internalURL.openStream()) {
- IOUtils.copy(in, resp.getOutputStream());
+ StreamUtils.copy(in, resp.getOutputStream());
}
}
package org.argeo.cms.websocket.server;
import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
import java.util.Map;
import javax.websocket.OnClose;
+import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import org.argeo.api.cms.CmsEventBus;
import org.argeo.api.cms.CmsEventSubscriber;
+import org.argeo.api.cms.CmsLog;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
-@ServerEndpoint(value = "/event/{topic}", configurator = CmsWebSocketConfigurator.class)
+@ServerEndpoint(value = "/cms/status/event/{topic}", configurator = CmsWebSocketConfigurator.class)
public class EventEndpoint implements CmsEventSubscriber {
+ private final static CmsLog log = CmsLog.getLog(EventEndpoint.class);
private BundleContext bc = FrameworkUtil.getBundle(TestEndpoint.class).getBundleContext();
private RemoteEndpoint.Basic remote;
throw new IllegalStateException(e);
}
}
+
+ @OnError
+ public void onError(Throwable e) {
+ if (e instanceof ClosedChannelException) {
+ // ignore, as it probably means ping was closed on the other side
+ return;
+ }
+ log.error("Cannot process ping", e);
+ }
}
package org.argeo.cms.websocket.server;
+import java.nio.channels.ClosedChannelException;
+
import javax.websocket.OnError;
import javax.websocket.server.ServerEndpoint;
import org.argeo.api.cms.CmsLog;
-@ServerEndpoint(value = "/ping", configurator = PublicWebSocketConfigurator.class)
+@ServerEndpoint(value = "/cms/status/ping", configurator = PublicWebSocketConfigurator.class)
public class PingEndpoint {
private final static CmsLog log = CmsLog.getLog(PingEndpoint.class);
@OnError
public void onError(Throwable e) {
+ if (e instanceof ClosedChannelException) {
+ // ignore, as it probably means ping was closed on the other side
+ return;
+ }
log.error("Cannot process ping", e);
}
}
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
+import org.argeo.api.acr.ldap.NamingUtils;
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.integration.CmsExceptionsChain;
-import org.argeo.util.naming.NamingUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceRegistration;
import com.fasterxml.jackson.databind.ObjectMapper;
/** Provides WebSocket access. */
-@ServerEndpoint(value = "/test/{topic}", configurator = CmsWebSocketConfigurator.class)
+@ServerEndpoint(value = "/cms/status/test/{topic}", configurator = CmsWebSocketConfigurator.class)
public class TestEndpoint implements EventHandler {
private final static CmsLog log = CmsLog.getLog(TestEndpoint.class);
package org.argeo.cms.websocket.server;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.List;
import javax.websocket.HandshakeResponse;
}
@Override
- public void setHeader(String key, String value) {
- handshakeResponse.getHeaders().put(key, Collections.singletonList(value));
+ public void setHeader(String headerName, String value) {
+ handshakeResponse.getHeaders().put(headerName, Collections.singletonList(value));
+ }
+ @Override
+ public void addHeader(String headerName, String value) {
+ List<String> values = handshakeResponse.getHeaders().getOrDefault(headerName, new ArrayList<>());
+ values.add(value);
}
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-/bin/
-/target/
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.cms.lib.equinox</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ds.core.builder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-/MANIFEST.MF
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" activate="start" deactivate="stop" name="Jetty Service Factory">
- <implementation class="org.argeo.cms.equinox.http.jetty.EquinoxJettyServer"/>
- <property name="service.pid" type="String" value="org.argeo.equinox.jetty.config"/>
- <reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
- <service>
- <provide interface="com.sun.net.httpserver.HttpServer"/>
- </service>
-</scr:component>
+++ /dev/null
-Service-Component: \
-OSGI-INF/jettyServiceFactory.xml,\
+++ /dev/null
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
+++ /dev/null
-package org.argeo.cms.equinox.http.jetty;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
-import javax.servlet.Servlet;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionIdListener;
-import javax.servlet.http.HttpSessionListener;
-
-import org.argeo.cms.jetty.CmsJettyServer;
-import org.eclipse.equinox.http.servlet.HttpServiceServlet;
-import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.osgi.framework.Constants;
-
-public class EquinoxJettyServer extends CmsJettyServer {
- private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
-
- @Override
- protected void addServlets(ServletContextHandler rootContextHandler) throws ServletException {
- ServletHolder holder = new ServletHolder(new InternalHttpServiceServlet());
- holder.setInitOrder(0);
- holder.setInitParameter(Constants.SERVICE_VENDOR, "Eclipse.org"); //$NON-NLS-1$
- holder.setInitParameter(Constants.SERVICE_DESCRIPTION, "Equinox Jetty-based Http Service"); //$NON-NLS-1$
-
- // holder.setInitParameter(JettyConstants.CONTEXT_PATH,
- // httpContext.getContextPath());
- rootContextHandler.addServlet(holder, "/*");
-
- // post-start
- SessionHandler sessionManager = rootContextHandler.getSessionHandler();
- sessionManager.addEventListener((HttpSessionIdListener) holder.getServlet());
- }
-
- public static class InternalHttpServiceServlet implements HttpSessionListener, HttpSessionIdListener, Servlet {
- private final Servlet httpServiceServlet = new HttpServiceServlet();
- private ClassLoader contextLoader;
- private final Method sessionDestroyed;
- private final Method sessionIdChanged;
-
- public InternalHttpServiceServlet() {
- Class<?> clazz = httpServiceServlet.getClass();
-
- try {
- sessionDestroyed = clazz.getMethod("sessionDestroyed", new Class<?>[] { String.class }); //$NON-NLS-1$
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- try {
- sessionIdChanged = clazz.getMethod("sessionIdChanged", new Class<?>[] { String.class }); //$NON-NLS-1$
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- }
-
- @Override
- public void init(ServletConfig config) throws ServletException {
- ServletContext context = config.getServletContext();
- contextLoader = (ClassLoader) context.getAttribute(INTERNAL_CONTEXT_CLASSLOADER);
-
- Thread thread = Thread.currentThread();
- ClassLoader current = thread.getContextClassLoader();
- thread.setContextClassLoader(contextLoader);
- try {
- httpServiceServlet.init(config);
- } finally {
- thread.setContextClassLoader(current);
- }
- }
-
- @Override
- public void destroy() {
- Thread thread = Thread.currentThread();
- ClassLoader current = thread.getContextClassLoader();
- thread.setContextClassLoader(contextLoader);
- try {
- httpServiceServlet.destroy();
- } finally {
- thread.setContextClassLoader(current);
- }
- contextLoader = null;
- }
-
- @Override
- public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
- Thread thread = Thread.currentThread();
- ClassLoader current = thread.getContextClassLoader();
- thread.setContextClassLoader(contextLoader);
- try {
- httpServiceServlet.service(req, res);
- } finally {
- thread.setContextClassLoader(current);
- }
- }
-
- @Override
- public ServletConfig getServletConfig() {
- return httpServiceServlet.getServletConfig();
- }
-
- @Override
- public String getServletInfo() {
- return httpServiceServlet.getServletInfo();
- }
-
- @Override
- public void sessionCreated(HttpSessionEvent event) {
- // Nothing to do.
- }
-
- @Override
- public void sessionDestroyed(HttpSessionEvent event) {
- Thread thread = Thread.currentThread();
- ClassLoader current = thread.getContextClassLoader();
- thread.setContextClassLoader(contextLoader);
- try {
- sessionDestroyed.invoke(httpServiceServlet, event.getSession().getId());
- } catch (IllegalAccessException | IllegalArgumentException e) {
- // not likely
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e.getCause());
- } finally {
- thread.setContextClassLoader(current);
- }
- }
-
- @Override
- public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
- Thread thread = Thread.currentThread();
- ClassLoader current = thread.getContextClassLoader();
- thread.setContextClassLoader(contextLoader);
- try {
- sessionIdChanged.invoke(httpServiceServlet, oldSessionId);
- } catch (IllegalAccessException | IllegalArgumentException e) {
- // not likely
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e.getCause());
- } finally {
- thread.setContextClassLoader(current);
- }
- }
- }
-
-}
+++ /dev/null
-package org.argeo.cms.servlet.internal.jetty;
-
-import java.io.File;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.concurrent.ForkJoinPool;
-
-import javax.websocket.DeploymentException;
-import javax.websocket.server.ServerContainer;
-import javax.websocket.server.ServerEndpointConfig;
-
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.api.cms.CmsLog;
-import org.argeo.api.cms.CmsState;
-import org.argeo.cms.CmsDeployProperty;
-import org.argeo.cms.websocket.server.CmsWebSocketConfigurator;
-import org.argeo.cms.websocket.server.TestEndpoint;
-import org.argeo.util.LangUtils;
-import org.eclipse.equinox.http.jetty.JettyConfigurator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-public class JettyConfig {
- private final static CmsLog log = CmsLog.getLog(JettyConfig.class);
-
- final static String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer";
-
- private CmsState cmsState;
-
- private final BundleContext bc = FrameworkUtil.getBundle(JettyConfig.class).getBundleContext();
-
- // private static final String JETTY_PROPERTY_PREFIX =
- // "org.eclipse.equinox.http.jetty.";
-
- public void start() {
- // We need to start asynchronously so that Jetty bundle get started by lazy init
- // due to the non-configurable behaviour of its activator
- ForkJoinPool.commonPool().execute(() -> {
- Dictionary<String, Object> properties = getHttpServerConfig();
- startServer(properties);
- });
-
- ServiceTracker<ServerContainer, ServerContainer> serverSt = new ServiceTracker<ServerContainer, ServerContainer>(
- bc, ServerContainer.class, null) {
-
- @Override
- public ServerContainer addingService(ServiceReference<ServerContainer> reference) {
- ServerContainer serverContainer = super.addingService(reference);
-
- BundleContext bc = reference.getBundle().getBundleContext();
- ServiceReference<ServerEndpointConfig.Configurator> srConfigurator = bc
- .getServiceReference(ServerEndpointConfig.Configurator.class);
- ServerEndpointConfig.Configurator endpointConfigurator = bc.getService(srConfigurator);
- ServerEndpointConfig config = ServerEndpointConfig.Builder
- .create(TestEndpoint.class, "/ws/test/events/").configurator(endpointConfigurator).build();
- try {
- serverContainer.addEndpoint(config);
- } catch (DeploymentException e) {
- throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
- }
- return serverContainer;
- }
-
- };
- serverSt.open();
-
- // check initialisation
-// ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
-//
-// @Override
-// public HttpService addingService(ServiceReference<HttpService> sr) {
-// Object httpPort = sr.getProperty("http.port");
-// Object httpsPort = sr.getProperty("https.port");
-// log.info(httpPortsMsg(httpPort, httpsPort));
-// close();
-// return super.addingService(sr);
-// }
-// };
-// httpSt.open();
- }
-
- public void stop() {
- try {
- JettyConfigurator.stopServer(CmsConstants.DEFAULT);
- } catch (Exception e) {
- log.error("Cannot stop default Jetty server.", e);
- }
-
- }
-
- public void startServer(Dictionary<String, Object> properties) {
- // Explicitly configures Jetty so that the default server is not started by the
- // activator of the Equinox Jetty bundle.
- Map<String, String> config = LangUtils.dictToStringMap(properties);
- if (!config.isEmpty()) {
- config.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS);
-
- // TODO centralise with Jetty extender
- Object webSocketEnabled = config.get(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty());
- if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
- bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null);
- // config.put(WEBSOCKET_ENABLED, "true");
- }
- }
-
- properties.put(Constants.SERVICE_PID, "default");
- File jettyWorkDir = new File(bc.getDataFile(""), "jettywork"); //$NON-NLS-1$
- jettyWorkDir.mkdir();
-
-// HttpServerManager serverManager = new HttpServerManager(jettyWorkDir);
-// try {
-// serverManager.updated("default", properties);
-// } catch (ConfigurationException e) {
-// // TODO Auto-generated catch block
-// e.printStackTrace();
-// }
- Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
- Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
- log.info(httpPortsMsg(httpPort, httpsPort));
-
-// long begin = System.currentTimeMillis();
-// int tryCount = 60;
-// try {
-// while (tryCount > 0) {
-// try {
-// // FIXME deal with multiple ids
-// JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config));
-//
-// Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
-// Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
-// log.info(httpPortsMsg(httpPort, httpsPort));
-//
-// // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi
-// // configuration is not cleaned
-// FrameworkUtil.getBundle(JettyConfigurator.class).start();
-// return;
-// } catch (IllegalStateException e) {
-// // e.printStackTrace();
-// // Jetty may not be ready
-// try {
-// Thread.sleep(1000);
-// } catch (Exception e1) {
-// // silent
-// }
-// tryCount--;
-// }
-// }
-// long duration = System.currentTimeMillis() - begin;
-// log.error("Gave up with starting Jetty server after " + (duration / 1000) + " s");
-// } catch (Exception e) {
-// log.error("Cannot start default Jetty server with config " + properties, e);
-// }
-
- }
-
- private String httpPortsMsg(Object httpPort, Object httpsPort) {
- return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : "");
- }
-
- /** Override the provided config with the framework properties */
- public Dictionary<String, Object> getHttpServerConfig() {
- String httpPort = getFrameworkProp(CmsDeployProperty.HTTP_PORT);
- String httpsPort = getFrameworkProp(CmsDeployProperty.HTTPS_PORT);
- /// TODO make it more generic
- String httpHost = getFrameworkProp(CmsDeployProperty.HOST);
-// String httpsHost = getFrameworkProp(
-// JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
- String webSocketEnabled = getFrameworkProp(CmsDeployProperty.WEBSOCKET_ENABLED);
-
- final Hashtable<String, Object> props = new Hashtable<String, Object>();
- // try {
- if (httpPort != null || httpsPort != null) {
- boolean httpEnabled = httpPort != null;
- props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled);
- boolean httpsEnabled = httpsPort != null;
- props.put(JettyHttpConstants.HTTPS_ENABLED, httpsEnabled);
-
- if (httpEnabled) {
- props.put(JettyHttpConstants.HTTP_PORT, httpPort);
- if (httpHost != null)
- props.put(JettyHttpConstants.HTTP_HOST, httpHost);
- }
-
- if (httpsEnabled) {
- props.put(JettyHttpConstants.HTTPS_PORT, httpsPort);
- if (httpHost != null)
- props.put(JettyHttpConstants.HTTPS_HOST, httpHost);
-
- // keystore
- props.put(JettyHttpConstants.SSL_KEYSTORETYPE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORETYPE));
- props.put(JettyHttpConstants.SSL_KEYSTORE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORE));
- props.put(JettyHttpConstants.SSL_PASSWORD, getFrameworkProp(CmsDeployProperty.SSL_PASSWORD));
-
- // truststore
- props.put(JettyHttpConstants.SSL_TRUSTSTORETYPE,
- getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORETYPE));
- props.put(JettyHttpConstants.SSL_TRUSTSTORE, getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORE));
- props.put(JettyHttpConstants.SSL_TRUSTSTOREPASSWORD,
- getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTOREPASSWORD));
-
- // client certificate authentication
- String wantClientAuth = getFrameworkProp(CmsDeployProperty.SSL_WANTCLIENTAUTH);
- if (wantClientAuth != null)
- props.put(JettyHttpConstants.SSL_WANTCLIENTAUTH, Boolean.parseBoolean(wantClientAuth));
- String needClientAuth = getFrameworkProp(CmsDeployProperty.SSL_NEEDCLIENTAUTH);
- if (needClientAuth != null)
- props.put(JettyHttpConstants.SSL_NEEDCLIENTAUTH, Boolean.parseBoolean(needClientAuth));
- }
-
- // web socket
- if (webSocketEnabled != null && webSocketEnabled.equals("true"))
- props.put(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty(), true);
-
- props.put(CmsConstants.CN, CmsConstants.DEFAULT);
- }
- return props;
- }
-
- private String getFrameworkProp(CmsDeployProperty deployProperty) {
- return cmsState.getDeployProperty(deployProperty.getProperty());
- }
-
- public void setCmsState(CmsState cmsState) {
- this.cmsState = cmsState;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.servlet.internal.jetty;
-
-/** Compatible with Jetty. */
-interface JettyHttpConstants {
- static final String HTTP_ENABLED = "http.enabled";
- static final String HTTP_PORT = "http.port";
- static final String HTTP_HOST = "http.host";
- static final String HTTPS_ENABLED = "https.enabled";
- static final String HTTPS_HOST = "https.host";
- static final String HTTPS_PORT = "https.port";
- static final String SSL_KEYSTORE = "ssl.keystore";
- static final String SSL_PASSWORD = "ssl.password";
- static final String SSL_KEYPASSWORD = "ssl.keypassword";
- static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth";
- static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth";
- static final String SSL_PROTOCOL = "ssl.protocol";
- static final String SSL_ALGORITHM = "ssl.algorithm";
- static final String SSL_KEYSTORETYPE = "ssl.keystoretype";
-
- // Argeo
- static final String SSL_TRUSTSTORE = "ssl.truststore";
- static final String SSL_TRUSTSTOREPASSWORD = "ssl.truststorepassword";
- static final String SSL_TRUSTSTORETYPE = "ssl.truststoretype";
-
-}
+++ /dev/null
-package org.argeo.equinox.jetty;
-
-import java.util.Dictionary;
-
-import javax.servlet.ServletContext;
-import javax.websocket.DeploymentException;
-import javax.websocket.server.ServerContainer;
-
-import org.eclipse.equinox.http.jetty.JettyCustomizer;
-import org.eclipse.jetty.server.ConnectionFactory;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
-import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
-import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-/** Customises the Jetty HTTP server. */
-public class CmsJettyCustomizer extends JettyCustomizer {
- static final String SSL_TRUSTSTORE = "ssl.truststore";
- static final String SSL_TRUSTSTOREPASSWORD = "ssl.truststorepassword";
- static final String SSL_TRUSTSTORETYPE = "ssl.truststoretype";
-
- private BundleContext bc = FrameworkUtil.getBundle(CmsJettyCustomizer.class).getBundleContext();
-
- public final static String WEBSOCKET_ENABLED = "argeo.websocket.enabled";
-
- @Override
- public Object customizeContext(Object context, Dictionary<String, ?> settings) {
- // WebSocket
- Object webSocketEnabled = settings.get(WEBSOCKET_ENABLED);
- if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
- ServletContextHandler servletContextHandler = (ServletContextHandler) context;
- JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
-
- @Override
- public void accept(ServletContext servletContext, ServerContainer serverContainer)
- throws DeploymentException {
- bc.registerService(javax.websocket.server.ServerContainer.class, serverContainer, null);
- }
- });
- }
- return super.customizeContext(context, settings);
-
- }
-
- @Override
- public Object customizeHttpsConnector(Object connector, Dictionary<String, ?> settings) {
- ServerConnector httpsConnector = (ServerConnector) connector;
- if (httpsConnector != null)
- for (ConnectionFactory connectionFactory : httpsConnector.getConnectionFactories()) {
- if (connectionFactory instanceof SslConnectionFactory) {
- SslContextFactory.Server sslContextFactory = ((SslConnectionFactory) connectionFactory)
- .getSslContextFactory();
- sslContextFactory.setTrustStorePath((String) settings.get(SSL_TRUSTSTORE));
- sslContextFactory.setTrustStoreType((String) settings.get(SSL_TRUSTSTORETYPE));
- sslContextFactory.setTrustStorePassword((String) settings.get(SSL_TRUSTSTOREPASSWORD));
- }
- }
- return super.customizeHttpsConnector(connector, settings);
- }
-
-}
+++ /dev/null
-/** Equinox Jetty extensions. */
-package org.argeo.equinox.jetty;
\ No newline at end of file
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.concurrent.CompletableFuture;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
+/** A {@link JettyHttpServer} which is compatible with Equinox servlets. */
public class CmsJettyServer extends JettyHttpServer {
private static final String CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
// Equinox compatibility
private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
-// private static final CmsLog log = CmsLog.getLog(CmsJettyServer.class);
-
-// private Server server;
-// private Path tempDir;
-//
-// private ServerConnector httpConnector;
-// private ServerConnector httpsConnector;
private Path tempDir;
- // WebSocket
-// private ServerContainer wsServerContainer;
-// private ServerEndpointConfig.Configurator wsEndpointConfigurator;
-
-// private Authenticator defaultAuthenticator;
+ private CompletableFuture<ServerContainer> serverContainer = new CompletableFuture<>();
protected void addServlets(ServletContextHandler servletContextHandler) throws ServletException {
}
super.start();
}
+ @Override
protected ServletContextHandler createRootContextHandler() {
ServletContextHandler servletContextHandler = new ServletContextHandler();
servletContextHandler.setAttribute(INTERNAL_CONTEXT_CLASSLOADER,
handler.setMaxInactiveInterval(-1);
servletContextHandler.setSessionHandler(handler);
+ JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
+
+ @Override
+ public void accept(ServletContext servletContext, ServerContainer serverContainer)
+ throws DeploymentException {
+ CmsJettyServer.this.serverContainer.complete(serverContainer);
+ }
+ });
+
return servletContextHandler;
}
+ @Override
+ protected ServerContainer getRootServerContainer() {
+ return serverContainer.join();
+ }
+
@Override
protected void configureRootContextHandler(ServletContextHandler servletContextHandler) throws ServletException {
addServlets(servletContextHandler);
-// enableWebSocket(servletContextHandler);
-
}
-// @Override
-// public synchronized HttpContext createContext(String path) {
-// HttpContext httpContext = super.createContext(path);
-// httpContext.setAuthenticator(defaultAuthenticator);
-// return httpContext;
-// }
-
-// protected void enableWebSocket(ServletContextHandler servletContextHandler) {
-// String webSocketEnabled = getDeployProperty(CmsDeployProperty.WEBSOCKET_ENABLED);
-// // web socket
-// if (webSocketEnabled != null && webSocketEnabled.equals(Boolean.toString(true))) {
-//// JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
-////
-//// @Override
-//// public void accept(ServletContext servletContext, ServerContainer serverContainer)
-//// throws DeploymentException {
-////// wsServerContainer = serverContainer;
-////
-//// CmsWebSocketConfigurator wsEndpointConfigurator = new CmsWebSocketConfigurator();
-////
-//// ServerEndpointConfig config = ServerEndpointConfig.Builder
-//// .create(TestEndpoint.class, "/ws/test/events/{topic}").configurator(wsEndpointConfigurator)
-//// .build();
-//// try {
-//// serverContainer.addEndpoint(config);
-//// } catch (DeploymentException e) {
-//// throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
-//// }
-//// }
-//// });
-// }
-// }
-
-// public void setDefaultAuthenticator(Authenticator defaultAuthenticator) {
-// this.defaultAuthenticator = defaultAuthenticator;
-// }
+ /*
+ * WEB SOCKET
+ */
}
--- /dev/null
+package org.argeo.cms.jetty;
+
+import java.util.AbstractMap;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.jetty.server.handler.ContextHandler;
+
+/**
+ * A {@link Map} implementation wrapping the attributes of a Jetty
+ * {@link ContextHandler}.
+ */
+class ContextHandlerAttributes extends AbstractMap<String, Object> {
+ private ContextHandler contextHandler;
+
+ public ContextHandlerAttributes(ContextHandler contextHandler) {
+ super();
+ this.contextHandler = contextHandler;
+ }
+
+ @Override
+ public Set<Entry<String, Object>> entrySet() {
+ Set<Entry<String, Object>> entries = new HashSet<>();
+ for (Enumeration<String> keys = contextHandler.getAttributeNames(); keys.hasMoreElements();) {
+ entries.add(new ContextAttributeEntry(keys.nextElement()));
+ }
+ return entries;
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ Object previousValue = get(key);
+ contextHandler.setAttribute(key, value);
+ return previousValue;
+ }
+
+ private class ContextAttributeEntry implements Map.Entry<String, Object> {
+ private final String key;
+
+ public ContextAttributeEntry(String key) {
+ this.key = key;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public Object getValue() {
+ return contextHandler.getAttribute(key);
+ }
+
+ @Override
+ public Object setValue(Object value) {
+ Object previousValue = getValue();
+ contextHandler.setAttribute(key, value);
+ return previousValue;
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.cms.jetty;
+
+import java.util.AbstractMap;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.ServletContext;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+
+import org.argeo.cms.servlet.httpserver.HttpContextServlet;
+import org.argeo.cms.websocket.server.WebsocketEndpoints;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
+
+import com.sun.net.httpserver.HttpHandler;
+
+/**
+ * An @{HttpContext} implementation based on a Jetty
+ * {@link ServletContextHandler}.
+ */
+class ContextHandlerHttpContext extends JettyHttpContext {
+ private final ServletContextHandler servletContextHandler;
+ private final ContextHandlerAttributes attributes;
+
+ public ContextHandlerHttpContext(JettyHttpServer httpServer, String path) {
+ super(httpServer, path);
+
+ // Jetty context handler
+ this.servletContextHandler = new ServletContextHandler();
+ servletContextHandler.setContextPath(path);
+ HttpContextServlet servlet = new HttpContextServlet(this);
+ servletContextHandler.addServlet(new ServletHolder(servlet), "/*");
+ SessionHandler sessionHandler = new SessionHandler();
+ // FIXME find a better default
+ sessionHandler.setMaxInactiveInterval(-1);
+ servletContextHandler.setSessionHandler(sessionHandler);
+
+ attributes = new ContextHandlerAttributes(servletContextHandler);
+ }
+
+ @Override
+ public void setHandler(HttpHandler handler) {
+ super.setHandler(handler);
+
+ // web socket
+ if (handler instanceof WebsocketEndpoints) {
+ JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
+
+ @Override
+ public void accept(ServletContext servletContext, ServerContainer serverContainer)
+ throws DeploymentException {
+ for (Class<?> clss : ((WebsocketEndpoints) handler).getEndPoints()) {
+ serverContainer.addEndpoint(clss);
+ }
+ }
+ });
+ }
+
+ if (getJettyHttpServer().isStarted())
+ try {
+ servletContextHandler.start();
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot start context handler", e);
+ }
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ protected ServletContextHandler getServletContextHandler() {
+ return servletContextHandler;
+ }
+
+}
package org.argeo.cms.jetty;
-import java.util.AbstractMap;
import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import javax.servlet.ServletContext;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerContainer;
-import org.argeo.cms.servlet.httpserver.HttpContextServlet;
import org.argeo.cms.websocket.server.WebsocketEndpoints;
-import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
-/** Trivial implementation of @{HttpContext}. */
-class JettyHttpContext extends HttpContext {
+/**
+ * An @{HttpContext} implementation based on Jetty. It supports web sockets if
+ * the handler implements {@link WebsocketEndpoints}.
+ */
+abstract class JettyHttpContext extends HttpContext {
private final JettyHttpServer httpServer;
private final String path;
- private final ServletContextHandler contextHandler;
- private final ContextAttributes attributes;
private final List<Filter> filters = new ArrayList<>();
private HttpHandler handler;
public JettyHttpContext(JettyHttpServer httpServer, String path) {
this.httpServer = httpServer;
+ if (!path.endsWith("/"))
+ throw new IllegalArgumentException("Path " + path + " should end with a /");
this.path = path;
-
- // Jetty context handler
- ServletContextHandler servletContextHandler = new ServletContextHandler();
- servletContextHandler.setContextPath(path);
- HttpContextServlet servlet = new HttpContextServlet(this);
- servletContextHandler.addServlet(new ServletHolder(servlet), "/*");
- SessionHandler sessionHandler = new SessionHandler();
- // FIXME find a better default
- sessionHandler.setMaxInactiveInterval(-1);
- servletContextHandler.setSessionHandler(sessionHandler);
- contextHandler = servletContextHandler;
-
- attributes = new ContextAttributes();
}
+ protected abstract ServletContextHandler getServletContextHandler();
+
@Override
public HttpHandler getHandler() {
return handler;
throw new IllegalArgumentException("Handler is already set");
Objects.requireNonNull(handler);
this.handler = handler;
-
- // web socket
- if (handler instanceof WebsocketEndpoints) {
- JavaxWebSocketServletContainerInitializer.configure(contextHandler, new Configurator() {
-
- @Override
- public void accept(ServletContext servletContext, ServerContainer serverContainer)
- throws DeploymentException {
-// CmsWebSocketConfigurator wsEndpointConfigurator = new CmsWebSocketConfigurator();
-
- for (Class<?> clss : ((WebsocketEndpoints) handler).getEndPoints()) {
-// Class<?> clss = websocketEndpoints.get(path);
-// ServerEndpointConfig config = ServerEndpointConfig.Builder.create(clss, path)
-// .configurator(wsEndpointConfigurator).build();
- serverContainer.addEndpoint(clss);
- }
- }
- });
- }
-
- if (httpServer.isStarted())
- try {
- contextHandler.start();
- } catch (Exception e) {
- throw new IllegalStateException("Cannot start context handler", e);
- }
}
@Override
@Override
public HttpServer getServer() {
- return httpServer;
+ return getJettyHttpServer();
}
- @Override
- public Map<String, Object> getAttributes() {
- return attributes;
+ protected JettyHttpServer getJettyHttpServer() {
+ return httpServer;
}
@Override
return authenticator;
}
- ServletContextHandler getContextHandler() {
- return contextHandler;
- }
-
- private class ContextAttributes extends AbstractMap<String, Object> {
- @Override
- public Set<Entry<String, Object>> entrySet() {
- Set<Entry<String, Object>> entries = new HashSet<>();
- for (Enumeration<String> keys = contextHandler.getAttributeNames(); keys.hasMoreElements();) {
- entries.add(new ContextAttributeEntry(keys.nextElement()));
- }
- return entries;
- }
-
- @Override
- public Object put(String key, Object value) {
- Object previousValue = get(key);
- contextHandler.setAttribute(key, value);
- return previousValue;
- }
-
- private class ContextAttributeEntry implements Map.Entry<String, Object> {
- private final String key;
-
- public ContextAttributeEntry(String key) {
- this.key = key;
- }
-
- @Override
- public String getKey() {
- return key;
- }
-
- @Override
- public Object getValue() {
- return contextHandler.getAttribute(key);
- }
-
- @Override
- public Object setValue(Object value) {
- Object previousValue = getValue();
- contextHandler.setAttribute(key, value);
- return previousValue;
- }
-
- }
- }
}
import java.util.concurrent.ThreadPoolExecutor;
import javax.servlet.ServletException;
+import javax.websocket.server.ServerContainer;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsState;
import org.argeo.cms.CmsDeployProperty;
-import org.argeo.util.http.HttpServerUtils;
+import org.argeo.cms.http.server.HttpServerUtils;
import org.eclipse.jetty.http.UriCompliance;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
+/** An {@link HttpServer} implementation based on Jetty. */
public class JettyHttpServer extends HttpsServer {
private final static CmsLog log = CmsLog.getLog(JettyHttpServer.class);
private final Map<String, JettyHttpContext> contexts = new TreeMap<>();
+ private ServletContextHandler rootContextHandler;
protected final ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
private boolean started;
// holder
// context
- ServletContextHandler rootContextHandler = createRootContextHandler();
+ rootContextHandler = createRootContextHandler();
// httpContext.addServlet(holder, "/*");
if (rootContextHandler != null)
configureRootContextHandler(rootContextHandler);
-// server.setHandler(rootContextHandler);
-// ContextHandlerCollection contextHandlers = new ContextHandlerCollection();
if (rootContextHandler != null && !contexts.containsKey("/"))
contextHandlerCollection.addHandler(rootContextHandler);
-// for (String contextPath : contexts.keySet()) {
-// JettyHttpContext ctx = contexts.get(contextPath);
-// contextHandlers.addHandler(ctx.getContextHandler());
-// }
server.setHandler(contextHandlerCollection);
// Addresses
String httpHost = getDeployProperty(CmsDeployProperty.HOST);
String fallBackHostname = cmsState != null ? cmsState.getHostname() : "::1";
- if (httpConnector != null)
+ if (httpConnector != null) {
httpAddress = new InetSocketAddress(httpHost != null ? httpHost : fallBackHostname,
httpConnector.getLocalPort());
- if (httpsConnector != null)
+ } else if (httpsConnector != null) {
httpsAddress = new InetSocketAddress(httpHost != null ? httpHost : fallBackHostname,
httpsConnector.getLocalPort());
-
+ }
// Clean up
Runtime.getRuntime().addShutdownHook(new Thread(() -> stop(), "Jetty shutdown"));
log.info(httpPortsMsg());
started = true;
} catch (Exception e) {
- throw new IllegalStateException("Cannot start Jetty HTTPS server", e);
+ stop();
+ throw new IllegalStateException("Cannot start Jetty HTTP server", e);
+ }
+ }
+
+ protected void configureConnectors() {
+ String httpPortStr = getDeployProperty(CmsDeployProperty.HTTP_PORT);
+ String httpsPortStr = getDeployProperty(CmsDeployProperty.HTTPS_PORT);
+ if (httpPortStr != null && httpsPortStr != null)
+ throw new IllegalArgumentException("Either an HTTP or an HTTPS port should be configured, not both");
+ if (httpPortStr == null && httpsPortStr == null)
+ throw new IllegalArgumentException("Neither an HTTP or HTTPS port was configured");
+
+ /// TODO make it more generic
+ String httpHost = getDeployProperty(CmsDeployProperty.HOST);
+
+ // try {
+ if (httpPortStr != null || httpsPortStr != null) {
+ // TODO deal with hostname resolving taking too much time
+// String fallBackHostname = InetAddress.getLocalHost().getHostName();
+
+ boolean httpEnabled = httpPortStr != null;
+ boolean httpsEnabled = httpsPortStr != null;
+
+ if (httpEnabled) {
+ HttpConfiguration httpConfiguration = new HttpConfiguration();
+
+ if (httpsEnabled) {// not supported anymore to have both http and https, but it may change again
+ int httpsPort = Integer.parseInt(httpsPortStr);
+ httpConfiguration.setSecureScheme("https");
+ httpConfiguration.setSecurePort(httpsPort);
+ }
+
+ int httpPort = Integer.parseInt(httpPortStr);
+ httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration));
+ httpConnector.setPort(httpPort);
+ httpConnector.setHost(httpHost);
+ httpConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
+
+ }
+
+ if (httpsEnabled) {
+ SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
+ // sslContextFactory.setKeyStore(KeyS)
+
+ sslContextFactory.setKeyStoreType(getDeployProperty(CmsDeployProperty.SSL_KEYSTORETYPE));
+ sslContextFactory.setKeyStorePath(getDeployProperty(CmsDeployProperty.SSL_KEYSTORE));
+ sslContextFactory.setKeyStorePassword(getDeployProperty(CmsDeployProperty.SSL_PASSWORD));
+ // sslContextFactory.setKeyManagerPassword(getFrameworkProp(CmsDeployProperty.SSL_KEYPASSWORD));
+ sslContextFactory.setProtocol("TLS");
+
+ sslContextFactory.setTrustStoreType(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTORETYPE));
+ sslContextFactory.setTrustStorePath(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTORE));
+ sslContextFactory.setTrustStorePassword(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTOREPASSWORD));
+
+ String wantClientAuth = getDeployProperty(CmsDeployProperty.SSL_WANTCLIENTAUTH);
+ if (wantClientAuth != null && wantClientAuth.equals(Boolean.toString(true)))
+ sslContextFactory.setWantClientAuth(true);
+ String needClientAuth = getDeployProperty(CmsDeployProperty.SSL_NEEDCLIENTAUTH);
+ if (needClientAuth != null && needClientAuth.equals(Boolean.toString(true)))
+ sslContextFactory.setNeedClientAuth(true);
+
+ // HTTPS Configuration
+ HttpConfiguration httpsConfiguration = new HttpConfiguration();
+ httpsConfiguration.addCustomizer(new SecureRequestCustomizer());
+ httpsConfiguration.setUriCompliance(UriCompliance.LEGACY);
+
+ // HTTPS connector
+ httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"),
+ new HttpConnectionFactory(httpsConfiguration));
+ int httpsPort = Integer.parseInt(httpsPortStr);
+ httpsConnector.setPort(httpsPort);
+ httpsConnector.setHost(httpHost);
+ }
}
}
public void stop() {
try {
- // serverConnector.close();
server.stop();
// TODO delete temp dir
started = false;
} catch (Exception e) {
- e.printStackTrace();
+ log.error("Cannot stop Jetty HTTP server", e);
}
}
@Override
public synchronized HttpContext createContext(String path) {
+ if (!path.endsWith("/"))
+ path = path + "/";
if (contexts.containsKey(path))
throw new IllegalArgumentException("Context " + path + " already exists");
- JettyHttpContext httpContext = new JettyHttpContext(this, path);
+
+ JettyHttpContext httpContext = new ServletHttpContext(this, path);
contexts.put(path, httpContext);
- contextHandlerCollection.addHandler(httpContext.getContextHandler());
+ contextHandlerCollection.addHandler(httpContext.getServletContextHandler());
return httpContext;
}
if (!contexts.containsKey(path))
throw new IllegalArgumentException("Context " + path + " does not exist");
JettyHttpContext httpContext = contexts.remove(path);
- // TODO stop handler first?
- contextHandlerCollection.removeHandler(httpContext.getContextHandler());
+ if (httpContext instanceof ContextHandlerHttpContext contextHandlerHttpContext) {
+ // TODO stop handler first?
+ contextHandlerCollection.removeHandler(contextHandlerHttpContext.getServletContextHandler());
+ }
}
@Override
@Override
public InetSocketAddress getAddress() {
- return httpAddress;
+ InetSocketAddress res = httpAddress != null ? httpAddress : httpsAddress;
+ if (res == null)
+ throw new IllegalStateException("Neither an HTTP nor and HTTPS address is available");
+ return res;
}
@Override
return httpsConfigurator;
}
- protected void configureConnectors() {
- HttpConfiguration httpConfiguration = new HttpConfiguration();
-
- String httpPortStr = getDeployProperty(CmsDeployProperty.HTTP_PORT);
- String httpsPortStr = getDeployProperty(CmsDeployProperty.HTTPS_PORT);
-
- /// TODO make it more generic
- String httpHost = getDeployProperty(CmsDeployProperty.HOST);
-// String httpsHost = getFrameworkProp(
-// JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
-
- // try {
- if (httpPortStr != null || httpsPortStr != null) {
- // TODO deal with hostname resolving taking too much time
-// String fallBackHostname = InetAddress.getLocalHost().getHostName();
-
- boolean httpEnabled = httpPortStr != null;
- // props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled);
- boolean httpsEnabled = httpsPortStr != null;
- // props.put(JettyHttpConstants.HTTPS_ENABLED, httpsEnabled);
- if (httpsEnabled) {
- int httpsPort = Integer.parseInt(httpsPortStr);
- httpConfiguration.setSecureScheme("https");
- httpConfiguration.setSecurePort(httpsPort);
- }
-
- if (httpEnabled) {
- int httpPort = Integer.parseInt(httpPortStr);
- httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration));
- httpConnector.setPort(httpPort);
- httpConnector.setHost(httpHost);
- httpConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
-
- }
-
- if (httpsEnabled) {
-
- SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
- // sslContextFactory.setKeyStore(KeyS)
-
- sslContextFactory.setKeyStoreType(getDeployProperty(CmsDeployProperty.SSL_KEYSTORETYPE));
- sslContextFactory.setKeyStorePath(getDeployProperty(CmsDeployProperty.SSL_KEYSTORE));
- sslContextFactory.setKeyStorePassword(getDeployProperty(CmsDeployProperty.SSL_PASSWORD));
- // sslContextFactory.setKeyManagerPassword(getFrameworkProp(CmsDeployProperty.SSL_KEYPASSWORD));
- sslContextFactory.setProtocol("TLS");
-
- sslContextFactory.setTrustStoreType(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTORETYPE));
- sslContextFactory.setTrustStorePath(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTORE));
- sslContextFactory.setTrustStorePassword(getDeployProperty(CmsDeployProperty.SSL_TRUSTSTOREPASSWORD));
-
- String wantClientAuth = getDeployProperty(CmsDeployProperty.SSL_WANTCLIENTAUTH);
- if (wantClientAuth != null && wantClientAuth.equals(Boolean.toString(true)))
- sslContextFactory.setWantClientAuth(true);
- String needClientAuth = getDeployProperty(CmsDeployProperty.SSL_NEEDCLIENTAUTH);
- if (needClientAuth != null && needClientAuth.equals(Boolean.toString(true)))
- sslContextFactory.setNeedClientAuth(true);
-
- // HTTPS Configuration
- HttpConfiguration https_config = new HttpConfiguration(httpConfiguration);
- https_config.addCustomizer(new SecureRequestCustomizer());
- https_config.setUriCompliance(UriCompliance.LEGACY);
-
- // HTTPS connector
- httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"),
- new HttpConnectionFactory(https_config));
- int httpsPort = Integer.parseInt(httpsPortStr);
- httpsConnector.setPort(httpsPort);
- httpsConnector.setHost(httpHost);
- }
-
- }
-
- }
-
protected String getDeployProperty(CmsDeployProperty deployProperty) {
return cmsState != null ? cmsState.getDeployProperty(deployProperty.getProperty())
: System.getProperty(deployProperty.getProperty());
private String httpPortsMsg() {
- return (httpConnector != null ? "HTTP " + getHttpPort() + " " : " ")
+ return (httpConnector != null ? "HTTP " + getHttpPort() + " " : "")
+ (httpsConnector != null ? "HTTPS " + getHttpsPort() : "");
}
this.cmsState = cmsState;
}
- public boolean isStarted() {
+ boolean isStarted() {
return started;
}
+ ServletContextHandler getRootContextHandler() {
+ return rootContextHandler;
+ }
+
+ ServerContainer getRootServerContainer() {
+ throw new UnsupportedOperationException();
+ }
+
public static void main(String... args) {
JettyHttpServer httpServer = new JettyHttpServer();
System.setProperty("argeo.http.port", "8080");
--- /dev/null
+package org.argeo.cms.jetty;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.servlet.httpserver.HttpContextServlet;
+import org.argeo.cms.websocket.server.WebsocketEndpoints;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+
+import com.sun.net.httpserver.HttpHandler;
+
+/**
+ * A {@link JettyHttpContext} based on registering a servlet to the root handler
+ * of the {@link JettyHttpServer}, in order to integrate the sessions.
+ */
+public class ServletHttpContext extends JettyHttpContext {
+ private final static CmsLog log = CmsLog.getLog(ServletHttpContext.class);
+
+ private Map<String, Object> attributes = Collections.synchronizedMap(new HashMap<>());
+
+ public ServletHttpContext(JettyHttpServer httpServer, String path) {
+ super(httpServer, path);
+
+ ServletContextHandler rootContextHandler = httpServer.getRootContextHandler();
+ HttpContextServlet servlet = new HttpContextServlet(this);
+ rootContextHandler.addServlet(new ServletHolder(servlet), path + "*");
+ }
+
+ @Override
+ public void setHandler(HttpHandler handler) {
+ super.setHandler(handler);
+
+ // web socket
+ if (handler instanceof WebsocketEndpoints) {
+ ServerContainer serverContainer = getJettyHttpServer().getRootServerContainer();
+ for (Class<?> clss : ((WebsocketEndpoints) handler).getEndPoints()) {
+ try {
+ serverContainer.addEndpoint(clss);
+ log.debug(() -> "Added web socket " + clss + " to " + getPath());
+ } catch (DeploymentException e) {
+ log.error("Cannot deploy Web Socket " + clss, e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ protected ServletContextHandler getServletContextHandler() {
+ return getJettyHttpServer().getRootContextHandler();
+ }
+
+}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.cms.lib.pgsql</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-Import-Package: org.postgresql;version="[42,43)"
+++ /dev/null
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
+++ /dev/null
-package org.argeo.cms.sql.postgres;
-
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-
-import org.postgresql.Driver;
-
-/** Simple PostgreSQL check. */
-public class CheckPg {
-
- public List<String> listTables() {
- String osUser = System.getProperty("user.name");
-
- String url = "jdbc:postgresql://localhost/" + osUser;
- Properties props = new Properties();
- props.setProperty("user", osUser);
- props.setProperty("password", "changeit");
- List<String> result = new ArrayList<>();
-
- Driver driver = new Driver();
- try (Connection conn = driver.connect(url, props); Statement s = conn.createStatement();) {
- s.execute("SELECT * FROM pg_catalog.pg_tables");
- ResultSet rs = s.getResultSet();
- while (rs.next()) {
- result.add(rs.getString("tablename"));
- }
- return result;
- } catch (SQLException e) {
- throw new IllegalStateException(e);
- }
- }
-
- public static void main(String[] args) {
- new CheckPg().listTables().forEach(System.out::println);
- }
-
-}
+++ /dev/null
-[
-{
- "name":"java.lang.Boolean",
- "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.ClassLoader",
- "methods":[
- {"name":"getPlatformClassLoader","parameterTypes":[] },
- {"name":"loadClass","parameterTypes":["java.lang.String"] }
- ]
-},
-{
- "name":"java.lang.String",
- "methods":[
- {"name":"<init>","parameterTypes":["byte[]"] },
- {"name":"getBytes","parameterTypes":[] }
- ]
-},
-{
- "name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
-},
-{
- "name":"org.apache.tomcat.jni.FileInfo",
- "fields":[
- {"name":"atime"},
- {"name":"csize"},
- {"name":"ctime"},
- {"name":"device"},
- {"name":"filehand"},
- {"name":"filetype"},
- {"name":"fname"},
- {"name":"group"},
- {"name":"inode"},
- {"name":"mtime"},
- {"name":"name"},
- {"name":"nlink"},
- {"name":"pool"},
- {"name":"protection"},
- {"name":"size"},
- {"name":"user"},
- {"name":"valid"}
- ],
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.tomcat.jni.Sockaddr",
- "fields":[
- {"name":"family"},
- {"name":"hostname"},
- {"name":"next"},
- {"name":"pool"},
- {"name":"port"},
- {"name":"servname"}
- ],
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.graalvm.jniutils.JNIExceptionWrapperEntryPoints",
- "methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
-},
-{
- "name":"sun.management.VMManagementImpl",
- "fields":[
- {"name":"compTimeMonitoringSupport"},
- {"name":"currentThreadCpuTimeSupport"},
- {"name":"objectMonitorUsageSupport"},
- {"name":"otherThreadCpuTimeSupport"},
- {"name":"remoteDiagnosticCommandsSupport"},
- {"name":"synchronizerUsageSupport"},
- {"name":"threadAllocatedMemorySupport"},
- {"name":"threadContentionMonitoringSupport"}
- ]
-}
-]
+++ /dev/null
-[
- {
- "type":"agent-extracted",
- "classes":[
- ]
- }
-]
-
+++ /dev/null
-[
- {
- "interfaces":["org.apache.sshd.common.channel.ChannelListener"]}
- ,
- {
- "interfaces":["org.apache.sshd.common.forward.PortForwardingEventListener"]}
- ,
- {
- "interfaces":["org.apache.sshd.common.session.SessionListener"]}
-
-]
+++ /dev/null
-[
-{
- "name":"java.security.KeyFactory",
- "methods":[{"name":"getInstance","parameterTypes":["java.lang.String","java.lang.String"] }]
-},
-{
- "name":"java.security.KeyPairGenerator",
- "methods":[{"name":"getInstance","parameterTypes":["java.lang.String","java.lang.String"] }]
-},
-{
- "name":"java.security.MessageDigest",
- "methods":[{"name":"getInstance","parameterTypes":["java.lang.String","java.lang.String"] }]
-},
-{
- "name":"java.security.SecureRandomParameters"
-},
-{
- "name":"java.security.Signature",
- "methods":[{"name":"getInstance","parameterTypes":["java.lang.String","java.lang.String"] }]
-},
-{
- "name":"java.security.cert.PKIXRevocationChecker"
-},
-{
- "name":"javax.crypto.KeyAgreement",
- "methods":[{"name":"getInstance","parameterTypes":["java.lang.String","java.lang.String"] }]
-},
-{
- "name":"org.apache.sshd.common.SshConstants",
- "allPublicFields":true
-},
-{
- "name":"org.apache.sshd.common.io.nio2.Nio2ServiceFactoryFactory",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.sshd.common.session.SessionListener",
- "methods":[
- {"name":"sessionClosed","parameterTypes":["org.apache.sshd.common.session.Session"] },
- {"name":"sessionCreated","parameterTypes":["org.apache.sshd.common.session.Session"] },
- {"name":"sessionEstablished","parameterTypes":["org.apache.sshd.common.session.Session"] },
- {"name":"sessionEvent","parameterTypes":["org.apache.sshd.common.session.Session","org.apache.sshd.common.session.SessionListener$Event"] },
- {"name":"sessionNegotiationEnd","parameterTypes":["org.apache.sshd.common.session.Session","java.util.Map","java.util.Map","java.util.Map","java.lang.Throwable"] },
- {"name":"sessionNegotiationOptionsCreated","parameterTypes":["org.apache.sshd.common.session.Session","java.util.Map"] },
- {"name":"sessionNegotiationStart","parameterTypes":["org.apache.sshd.common.session.Session","java.util.Map","java.util.Map"] },
- {"name":"sessionPeerIdentificationLine","parameterTypes":["org.apache.sshd.common.session.Session","java.lang.String","java.util.List"] },
- {"name":"sessionPeerIdentificationReceived","parameterTypes":["org.apache.sshd.common.session.Session","java.lang.String","java.util.List"] },
- {"name":"sessionPeerIdentificationSend","parameterTypes":["org.apache.sshd.common.session.Session","java.lang.String","java.util.List"] }
- ]
-},
-{
- "name":"org.apache.sshd.common.util.security.bouncycastle.BouncyCastleSecurityProviderRegistrar",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.sshd.common.util.security.eddsa.EdDSASecurityProviderRegistrar",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.COMPOSITE$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.DH$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.DSA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.DSTU4145$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.EC$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.ECGOST$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.EXTERNAL$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.EdEC$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.ElGamal$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.GM$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.GOST$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.IES$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.LMS$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.SPHINCSPlus$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.X509$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.dh.KeyPairGeneratorSpi",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$EC",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi$EC",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi$ecDSA256",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyAgreementSpi$X25519",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyAgreementSpi$X448",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyFactorySpi$X25519",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyFactorySpi$X448",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$X25519",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.edec.KeyPairGeneratorSpi$X448",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.rsa.DigestSignatureSpi$SHA512",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyFactorySpi",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Blake2b$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Blake2s$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Blake3$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.DSTU7564$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.GOST3411$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Haraka$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Keccak$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.MD2$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.MD4$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.MD5$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.MD5$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD128$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD160$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD256$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.RIPEMD320$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA1$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA1$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA224$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA224$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA256$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA256$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA3$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA384$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA384$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA512$Digest",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SHA512$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.SM3$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Skein$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Tiger$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.digest.Whirlpool$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.drbg.DRBG$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.keystore.BC$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.keystore.BCFKS$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.keystore.PKCS12$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.AES$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.ARC4$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.ARIA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Blowfish$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.CAST5$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.CAST6$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Camellia$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.DES$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.DESede$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.DSTU7624$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.GOST28147$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.GOST3412_2015$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Grain128$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Grainv1$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.HC128$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.HC256$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.IDEA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Noekeon$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.OpenSSLPBKDF$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF1$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPBKDF2$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.PBEPKCS12$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Poly1305$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.RC2$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.RC5$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.RC6$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Rijndael$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.SCRYPT$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.SEED$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.SM4$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Salsa20$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Serpent$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Shacal2$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.SipHash$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.SipHash128$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Skipjack$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.TEA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.TLSKDF$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Threefish$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Twofish$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.VMPC$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.VMPCKSA3$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.XSalsa20$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.XTEA$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jcajce.provider.symmetric.Zuc$Mappings",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.bouncycastle.jce.provider.BouncyCastleProvider",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.NativePRNG",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.SHA",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-}
-]
+++ /dev/null
-{
- "resources":{
- "includes":[
- {
- "pattern":"\\Qorg/apache/sshd/sshd-version.properties\\E"
- },
- {
- "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E"
- }
- ]},
- "bundles":[]
-}
+++ /dev/null
-{
- "types":[
- ],
- "lambdaCapturingTypes":[
- ]
-}
import org.apache.sshd.server.config.keys.DefaultAuthorizedKeysAuthenticator;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.shell.ProcessShellFactory;
-import org.argeo.util.OS;
+import org.argeo.cms.util.OS;
/** A simple SSH server with some defaults. Supports SCP. */
public class BasicSshServer {
import java.util.Map;
import java.util.Scanner;
-import org.apache.commons.io.IOUtils;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.local.LocalAgentFactory;
import org.apache.sshd.sftp.client.fs.SftpFileSystem;
import org.apache.sshd.sftp.client.fs.SftpFileSystemProvider;
import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.util.StreamUtils;
public class SshSync {
private final static CmsLog log = CmsLog.getLog(SshSync.class);
log.debug("Relative copied file " + relativeCopiedFile);
try (OutputStream out = Files.newOutputStream(copiedFile);
InputStream in = Files.newInputStream(testPath)) {
- IOUtils.copy(in, out);
+ StreamUtils.copy(in, out);
}
log.debug("Copied " + testPath + " to " + copiedFile);
Files.delete(testPath);
import org.argeo.api.cli.CommandsCli;
+/** SSH command line interface. */
public class SshCli extends CommandsCli {
public SshCli(String commandName) {
super(commandName);
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
-import org.apache.commons.io.FilenameUtils;
public class SvgToPng {
public void convertSvgDir(Path sourceDir, Path targetDir, int width) {
- System.out.println("##\n## " + width + "px - " + sourceDir+"\n##");
+ System.out.println("##\n## " + width + "px - " + sourceDir + "\n##");
try {
if (targetDir == null)
targetDir = sourceDir.getParent().resolve(Integer.toString(width));
transcoder.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, (float) width);
for (Path source : Files.newDirectoryStream(sourceDir, "*.svg")) {
- String baseName = FilenameUtils.getBaseName(source.toString());
+ // FIXME extract base name
+ String baseName = null; // = FilenameUtils.getBaseName(source.toString());
Path target = targetDir.resolve(baseName + ".png");
convertSvgFile(transcoder, source, target);
}
import org.argeo.api.acr.ContentSession;
import org.argeo.api.cms.ux.Cms2DSize;
import org.argeo.api.cms.ux.CmsView;
-import org.argeo.util.CurrentSubject;
+import org.argeo.cms.util.CurrentSubject;
public class CmsUxUtils {
public static ContentSession getContentSession(ContentRepository contentRepository, CmsView cmsView) {
import java.util.List;
import org.argeo.api.acr.Content;
-import org.argeo.api.acr.NamespaceUtils;
-import org.argeo.cms.ux.widgets.AbstractDataPart;
+import org.argeo.cms.ux.widgets.AbstractHierarchicalPart;
import org.argeo.cms.ux.widgets.HierarchicalPart;
-public class ContentHierarchicalPart extends AbstractDataPart<Content, Content> implements HierarchicalPart<Content> {
+public class ContentHierarchicalPart extends AbstractHierarchicalPart<Content> implements HierarchicalPart<Content> {
@Override
public List<Content> getChildren(Content content) {
List<Content> res = new ArrayList<>();
protected boolean isLeaf(Content content) {
return false;
}
-
- @Override
- public String getText(Content model) {
- try {
- return NamespaceUtils.toPrefixedName(model.getName());
- } catch (IllegalStateException e) {
- return model.getName().toString();
- }
- }
-
}
--- /dev/null
+package org.argeo.cms.ux.widgets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractColumnsPart<INPUT, TYPE> extends AbstractDataPart<INPUT, TYPE> implements ColumnsPart<INPUT, TYPE> {
+
+ private List<Column<TYPE>> columns = new ArrayList<>();
+
+ @Override
+ public Column<TYPE> getColumn(int index) {
+ if (index >= columns.size())
+ throw new IllegalArgumentException("There a only " + columns.size());
+ return columns.get(index);
+ }
+
+ @Override
+ public void addColumn(Column<TYPE> column) {
+ columns.add(column);
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columns.size();
+ }
+}
import java.util.IdentityHashMap;
import java.util.function.Consumer;
-public abstract class AbstractDataPart<INPUT, T> implements DataPart<INPUT, T> {
+public abstract class AbstractDataPart<INPUT, TYPE> implements DataPart<INPUT, TYPE> {
+ private Consumer<TYPE> onSelected;
+ private Consumer<TYPE> onAction;
- private Consumer<T> onSelected;
- private Consumer<T> onAction;
-
- private IdentityHashMap<DataView<INPUT, T>, Object> views = new IdentityHashMap<>();
+ private IdentityHashMap<DataView<INPUT, TYPE>, Object> views = new IdentityHashMap<>();
private INPUT data;
}
@Override
- public void onSelected(Consumer<T> onSelected) {
+ public void onSelected(Consumer<TYPE> onSelected) {
this.onSelected = onSelected;
}
@Override
- public void onAction(Consumer<T> onAction) {
+ public void onAction(Consumer<TYPE> onAction) {
this.onAction = onAction;
}
- public Consumer<T> getOnSelected() {
+ public Consumer<TYPE> getOnSelected() {
return onSelected;
}
- public Consumer<T> getOnAction() {
+ public Consumer<TYPE> getOnAction() {
return onAction;
}
@Override
public void refresh() {
- for (DataView<INPUT, T> view : views.keySet()) {
+ for (DataView<INPUT, TYPE> view : views.keySet()) {
view.refresh();
}
}
+ protected void notifyItemCountChange() {
+ for (DataView<INPUT, TYPE> view : views.keySet()) {
+ view.notifyItemCountChange();
+ }
+ }
+
@Override
- public void addView(DataView<INPUT, T> view) {
+ public void addView(DataView<INPUT, TYPE> view) {
views.put(view, new Object());
}
@Override
- public void removeView(DataView<INPUT, T> view) {
+ public void removeView(DataView<INPUT, TYPE> view) {
views.remove(view);
}
-
}
package org.argeo.cms.ux.widgets;
-public abstract class AbstractHierarchicalPart<T> extends AbstractDataPart<T, T> implements HierarchicalPart<T> {
+public abstract class AbstractHierarchicalPart<T> extends AbstractColumnsPart<T, T> implements HierarchicalPart<T> {
}
package org.argeo.cms.ux.widgets;
-import java.util.ArrayList;
-import java.util.List;
+public abstract class AbstractTabularPart<INPUT, TYPE> extends AbstractColumnsPart<INPUT, TYPE>
+ implements TabularPart<INPUT, TYPE> {
-public abstract class AbstractTabularPart<INPUT, T> extends AbstractDataPart<INPUT, T> implements TabularPart<INPUT, T> {
-
- private List<Column<T>> columns = new ArrayList<>();
-
- @Override
- public Column<T> getColumn(int index) {
- if (index >= columns.size())
- throw new IllegalArgumentException("There a only " + columns.size());
- return columns.get(index);
- }
-
- public void addColumn(Column<T> column) {
- columns.add(column);
- }
-
- @Override
- public int getColumnCount() {
- return columns.size();
- }
}
--- /dev/null
+package org.argeo.cms.ux.widgets;
+
+public interface CmsDialog {
+
+ // must be the same value as org.eclipse.jface.window.Window#OK
+ int OK = 0;
+ // must be the same value as org.eclipse.jface.window.Window#CANCEL
+ int CANCEL = 1;
+
+}
import org.argeo.api.cms.ux.CmsIcon;
-public interface Column<T> {
- String getText(T model);
+/** A column in a data representation. */
+@FunctionalInterface
+public interface Column<TYPE> {
+ String getText(TYPE model);
default int getWidth() {
return 200;
}
- default CmsIcon getIcon(T model) {
+ default CmsIcon getIcon(TYPE model) {
return null;
}
package org.argeo.cms.ux.widgets;
+/** A presentation of data in columns. */
public interface ColumnsPart<INPUT, TYPE> extends DataPart<INPUT, TYPE> {
+ Column<TYPE> getColumn(int index);
+
+ void addColumn(Column<TYPE> column);
+
+ int getColumnCount();
+
}
import java.util.function.Consumer;
-public interface DataPart<INPUT, T> {
+public interface DataPart<INPUT, TYPE> {
void setInput(INPUT data);
INPUT getInput();
- void onSelected(Consumer<T> onSelected);
+ void onSelected(Consumer<TYPE> onSelected);
- Consumer<T> getOnSelected();
+ Consumer<TYPE> getOnSelected();
- void onAction(Consumer<T> onAction);
+ void onAction(Consumer<TYPE> onAction);
- Consumer<T> getOnAction();
+ Consumer<TYPE> getOnAction();
void refresh();
- void addView(DataView<INPUT, T> view);
+ void addView(DataView<INPUT, TYPE> view);
+
+ void removeView(DataView<INPUT, TYPE> view);
+
+// void select(TYPE data);
+//
+// TYPE getSelected();
- void removeView(DataView<INPUT, T> view);
}
public interface DataView<INPUT,TYPE> {
void refresh();
+
+ void notifyItemCountChange();
}
import java.util.List;
-import org.argeo.api.cms.ux.CmsIcon;
-
+/** A hierarchical representation of data. */
public interface HierarchicalPart<T> extends ColumnsPart<T, T> {
List<T> getChildren(T parent);
-
- String getText(T model);
-
- default CmsIcon getIcon(T model) {
- return null;
- }
-
}
package org.argeo.cms.ux.widgets;
-public interface TabularPart<INPUT, T> extends ColumnsPart<INPUT, T> {
+/** A tabular presentation of data. */
+public interface TabularPart<INPUT, TYPE> extends ColumnsPart<INPUT, TYPE> {
int getItemCount();
- T getData(int row);
-
- Column<T> getColumn(int index);
-
- int getColumnCount();
+ TYPE getData(int row);
}
+++ /dev/null
-[
-{
- "name":"java.lang.Boolean",
- "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.ClassLoader",
- "methods":[
- {"name":"getPlatformClassLoader","parameterTypes":[] },
- {"name":"loadClass","parameterTypes":["java.lang.String"] }
- ]
-},
-{
- "name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
-},
-{
- "name":"org.graalvm.jniutils.JNIExceptionWrapperEntryPoints",
- "methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
-},
-{
- "name":"sun.management.VMManagementImpl",
- "fields":[
- {"name":"compTimeMonitoringSupport"},
- {"name":"currentThreadCpuTimeSupport"},
- {"name":"objectMonitorUsageSupport"},
- {"name":"otherThreadCpuTimeSupport"},
- {"name":"remoteDiagnosticCommandsSupport"},
- {"name":"synchronizerUsageSupport"},
- {"name":"threadAllocatedMemorySupport"},
- {"name":"threadContentionMonitoringSupport"}
- ]
-}
-]
+++ /dev/null
-[
- {
- "type":"agent-extracted",
- "classes":[
- ]
- }
-]
-
+++ /dev/null
-[
-{
- "name":"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"java.security.SecureRandomParameters"
-},
-{
- "name":"javax.security.auth.login.Configuration$Parameters"
-},
-{
- "name":"org.apache.xerces.impl.dv.dtd.DTDDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.dtd.XML11DTDDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.xs.ExtendedSchemaDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.xs.SchemaDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.xs.XSMessageFormatter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.parsers.XIncludeAwareParserConfiguration",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.DataAdminLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.ConfigFile$Spi",
- "methods":[{"name":"<init>","parameterTypes":["javax.security.auth.login.Configuration$Parameters"] }]
-},
-{
- "name":"sun.security.provider.DRBG",
- "methods":[{"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
-},
-{
- "name":"sun.security.provider.NativePRNG",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.SHA",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.SHA2$SHA256",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-}
-]
+++ /dev/null
-{
- "resources":{
- "includes":[
- {
- "pattern":"\\QMETA-INF/services/javax.xml.validation.SchemaFactory\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/DSMLv2.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/SVG.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/XForms-11-Schema.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/XMLSchema.dtd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/XMLSchema.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/cr.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/datatypes.dtd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/docbook.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/schema-for-xslt20.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xlink.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xml-events-attribs-1.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xml.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/internal/runtime/jaas.cfg\\E"
- }
- ]},
- "bundles":[
- {
- "name":"org.apache.xerces.impl.msg.XMLSchemaMessages",
- "locales":[
- "en",
- "und"
- ]
- },
- {
- "name":"org.apache.xerces.impl.xpath.regex.message",
- "locales":[
- "",
- "en",
- "und"
- ]
- },
- {
- "name":"sun.security.util.Resources",
- "classNames":["sun.security.util.Resources"]
- }
- ]
-}
+++ /dev/null
-{
- "types":[
- ],
- "lambdaCapturingTypes":[
- ]
-}
<service>
<provide interface="com.sun.net.httpserver.HttpHandler"/>
</service>
- <property name="context.path" type="String" value="/api/acr" />
+ <property name="context.path" type="String" value="/api/acr/" />
<reference bind="setContentRepository" cardinality="1..1" interface="org.argeo.api.acr.spi.ProvidedRepository" name="ProvidedRepository" policy="static"/>
</scr:component>
</service>
<reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
<reference bind="setUuidFactory" cardinality="1..1" interface="org.argeo.api.uuid.UuidFactory" name="UuidFactory" policy="static"/>
- <reference bind="setUserManager" cardinality="1..1" interface="org.argeo.cms.CmsUserManager" name="CmsUserManager" policy="static"/>
+ <reference bind="setUserManager" cardinality="1..1" interface="org.argeo.api.cms.directory.CmsUserManager" name="CmsUserManager" policy="static"/>
</scr:component>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start" deactivate="stop" immediate="false" name="Node User Admin">
<implementation class="org.argeo.cms.internal.runtime.CmsUserAdmin"/>
<property name="service.pid" type="String" value="org.argeo.api.userAdmin"/>
- <reference bind="setTransactionManager" cardinality="1..1" interface="org.argeo.util.transaction.WorkControl" name="WorkControl" policy="static"/>
- <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.util.transaction.WorkTransaction" name="WorkTransaction" policy="static"/>
+ <reference bind="setTransactionManager" cardinality="1..1" interface="org.argeo.api.cms.transaction.WorkControl" name="WorkControl" policy="static"/>
+ <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.api.cms.transaction.WorkTransaction" name="WorkTransaction" policy="static"/>
<reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
<service>
<provide interface="org.osgi.service.useradmin.UserAdmin"/>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start" deactivate="stop" immediate="true" name="User Admin Service">
- <implementation class="org.argeo.cms.internal.auth.CmsUserManagerImpl"/>
+ <implementation class="org.argeo.cms.internal.runtime.CmsUserManagerImpl"/>
<service>
- <provide interface="org.argeo.cms.CmsUserManager"/>
+ <provide interface="org.argeo.api.cms.directory.CmsUserManager"/>
</service>
<reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
- <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.util.transaction.WorkTransaction" name="UserTransaction" policy="static"/>
+ <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.api.cms.transaction.WorkTransaction" name="UserTransaction" policy="static"/>
</scr:component>
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="Simple Transaction Manager">
- <implementation class="org.argeo.util.transaction.SimpleTransactionManager"/>
+ <implementation class="org.argeo.api.cms.transaction.SimpleTransactionManager"/>
<service>
- <provide interface="org.argeo.util.transaction.WorkControl"/>
- <provide interface="org.argeo.util.transaction.WorkTransaction"/>
+ <provide interface="org.argeo.api.cms.transaction.WorkControl"/>
+ <provide interface="org.argeo.api.cms.transaction.WorkTransaction"/>
</service>
</scr:component>
--- /dev/null
+package org.argeo.cms;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.CharArrayWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.Writer;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import javax.crypto.SecretKey;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.argeo.api.cms.CmsAuth;
+import org.argeo.api.cms.keyring.PBEKeySpecCallback;
+import org.argeo.cms.util.CurrentSubject;
+import org.argeo.cms.util.StreamUtils;
+import org.argeo.api.cms.keyring.CryptoKeyring;
+import org.argeo.api.cms.keyring.Keyring;
+
+/** username / password based keyring. TODO internationalize */
+public abstract class AbstractKeyring implements Keyring, CryptoKeyring {
+ // public final static String DEFAULT_KEYRING_LOGIN_CONTEXT = "KEYRING";
+
+ // private String loginContextName = DEFAULT_KEYRING_LOGIN_CONTEXT;
+ private CallbackHandler defaultCallbackHandler;
+
+ private String charset = "UTF-8";
+
+ /**
+ * Default provider is bouncy castle, in order to have consistent behaviour
+ * across implementations
+ */
+ private String securityProviderName = "BC";
+
+ /**
+ * Whether the keyring has already been created in the past with a master
+ * password
+ */
+ protected abstract Boolean isSetup();
+
+ /**
+ * Setup the keyring persistently, {@link #isSetup()} must return true
+ * afterwards
+ */
+ protected abstract void setup(char[] password);
+
+ /** Populates the key spec callback */
+ protected abstract void handleKeySpecCallback(PBEKeySpecCallback pbeCallback);
+
+ protected abstract void encrypt(String path, InputStream unencrypted);
+
+ protected abstract InputStream decrypt(String path);
+
+ /** Triggers lazy initialization */
+ protected SecretKey getSecretKey(char[] password) {
+ Subject subject = CurrentSubject.current();
+ if (subject == null)
+ throw new IllegalStateException("Current subject cannot be null");
+ // we assume only one secrete key is available
+ Iterator<SecretKey> iterator = subject.getPrivateCredentials(SecretKey.class).iterator();
+ if (!iterator.hasNext() || password != null) {// not initialized
+ CallbackHandler callbackHandler = password == null ? new KeyringCallbackHandler()
+ : new PasswordProvidedCallBackHandler(password);
+ ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ try {
+ LoginContext loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_KEYRING, subject, callbackHandler);
+ loginContext.login();
+ // FIXME will login even if password is wrong
+ iterator = subject.getPrivateCredentials(SecretKey.class).iterator();
+ return iterator.next();
+ } catch (LoginException e) {
+ throw new IllegalStateException("Keyring login failed", e);
+ } finally {
+ Thread.currentThread().setContextClassLoader(currentContextClassLoader);
+ }
+
+ } else {
+ SecretKey secretKey = iterator.next();
+ if (iterator.hasNext())
+ throw new IllegalStateException("More than one secret key in private credentials");
+ return secretKey;
+ }
+ }
+
+ public InputStream getAsStream(String path) {
+ return decrypt(path);
+ }
+
+ public void set(String path, InputStream in) {
+ encrypt(path, in);
+ }
+
+ public char[] getAsChars(String path) {
+ // InputStream in = getAsStream(path);
+ // CharArrayWriter writer = null;
+ // Reader reader = null;
+ try (InputStream in = getAsStream(path);
+ CharArrayWriter writer = new CharArrayWriter();
+ Reader reader = new InputStreamReader(in, charset);) {
+ StreamUtils.copy(reader, writer);
+ return writer.toCharArray();
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot decrypt to char array", e);
+ } finally {
+ // IOUtils.closeQuietly(reader);
+ // IOUtils.closeQuietly(in);
+ // IOUtils.closeQuietly(writer);
+ }
+ }
+
+ public void set(String path, char[] arr) {
+ // ByteArrayOutputStream out = new ByteArrayOutputStream();
+ // ByteArrayInputStream in = null;
+ // Writer writer = null;
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(out, charset);) {
+ // writer = new OutputStreamWriter(out, charset);
+ writer.write(arr);
+ writer.flush();
+ // in = new ByteArrayInputStream(out.toByteArray());
+ try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());) {
+ set(path, in);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot encrypt to char array", e);
+ } finally {
+ // IOUtils.closeQuietly(writer);
+ // IOUtils.closeQuietly(out);
+ // IOUtils.closeQuietly(in);
+ }
+ }
+
+ public void unlock(char[] password) {
+ if (!isSetup())
+ setup(password);
+ SecretKey secretKey = getSecretKey(password);
+ if (secretKey == null)
+ throw new IllegalStateException("Could not unlock keyring");
+ }
+
+ protected Provider getSecurityProvider() {
+ return Security.getProvider(securityProviderName);
+ }
+
+ public void setDefaultCallbackHandler(CallbackHandler defaultCallbackHandler) {
+ this.defaultCallbackHandler = defaultCallbackHandler;
+ }
+
+ public void setCharset(String charset) {
+ this.charset = charset;
+ }
+
+ public void setSecurityProviderName(String securityProviderName) {
+ this.securityProviderName = securityProviderName;
+ }
+
+ // @Deprecated
+ // protected static byte[] hash(char[] password, byte[] salt, Integer
+ // iterationCount) {
+ // ByteArrayOutputStream out = null;
+ // OutputStreamWriter writer = null;
+ // try {
+ // out = new ByteArrayOutputStream();
+ // writer = new OutputStreamWriter(out, "UTF-8");
+ // writer.write(password);
+ // MessageDigest pwDigest = MessageDigest.getInstance("SHA-256");
+ // pwDigest.reset();
+ // pwDigest.update(salt);
+ // byte[] btPass = pwDigest.digest(out.toByteArray());
+ // for (int i = 0; i < iterationCount; i++) {
+ // pwDigest.reset();
+ // btPass = pwDigest.digest(btPass);
+ // }
+ // return btPass;
+ // } catch (Exception e) {
+ // throw new CmsException("Cannot hash", e);
+ // } finally {
+ // IOUtils.closeQuietly(out);
+ // IOUtils.closeQuietly(writer);
+ // }
+ //
+ // }
+
+ /**
+ * Convenience method using the underlying callback to ask for a password
+ * (typically used when the password is not saved in the keyring)
+ */
+ protected char[] ask() {
+ PasswordCallback passwordCb = new PasswordCallback("Password", false);
+ Callback[] dialogCbs = new Callback[] { passwordCb };
+ try {
+ defaultCallbackHandler.handle(dialogCbs);
+ char[] password = passwordCb.getPassword();
+ return password;
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot ask for a password", e);
+ }
+
+ }
+
+ class KeyringCallbackHandler implements CallbackHandler {
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ // checks
+ if (callbacks.length != 2)
+ throw new IllegalArgumentException(
+ "Keyring requires 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}");
+ if (!(callbacks[0] instanceof PasswordCallback))
+ throw new UnsupportedCallbackException(callbacks[0]);
+ if (!(callbacks[1] instanceof PBEKeySpecCallback))
+ throw new UnsupportedCallbackException(callbacks[0]);
+
+ PasswordCallback passwordCb = (PasswordCallback) callbacks[0];
+ PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1];
+
+ if (isSetup()) {
+ Callback[] dialogCbs = new Callback[] { passwordCb };
+ defaultCallbackHandler.handle(dialogCbs);
+ } else {// setup keyring
+ TextOutputCallback textCb1 = new TextOutputCallback(TextOutputCallback.INFORMATION,
+ "Enter a master password which will protect your private data");
+ TextOutputCallback textCb2 = new TextOutputCallback(TextOutputCallback.INFORMATION,
+ "(for example your credentials to third-party services)");
+ TextOutputCallback textCb3 = new TextOutputCallback(TextOutputCallback.INFORMATION,
+ "Don't forget this password since the data cannot be read without it");
+ PasswordCallback confirmPasswordCb = new PasswordCallback("Confirm password", false);
+ // first try
+ Callback[] dialogCbs = new Callback[] { textCb1, textCb2, textCb3, passwordCb, confirmPasswordCb };
+ defaultCallbackHandler.handle(dialogCbs);
+
+ // if passwords different, retry (except if cancelled)
+ while (passwordCb.getPassword() != null
+ && !Arrays.equals(passwordCb.getPassword(), confirmPasswordCb.getPassword())) {
+ TextOutputCallback textCb = new TextOutputCallback(TextOutputCallback.ERROR,
+ "The passwords do not match");
+ dialogCbs = new Callback[] { textCb, passwordCb, confirmPasswordCb };
+ defaultCallbackHandler.handle(dialogCbs);
+ }
+
+ if (passwordCb.getPassword() != null) {// not cancelled
+ setup(passwordCb.getPassword());
+ }
+ }
+
+ if (passwordCb.getPassword() != null)
+ handleKeySpecCallback(pbeCb);
+ }
+
+ }
+
+ class PasswordProvidedCallBackHandler implements CallbackHandler {
+ private final char[] password;
+
+ public PasswordProvidedCallBackHandler(char[] password) {
+ this.password = password;
+ }
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ // checks
+ if (callbacks.length != 2)
+ throw new IllegalArgumentException(
+ "Keyring requires 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}");
+ if (!(callbacks[0] instanceof PasswordCallback))
+ throw new UnsupportedCallbackException(callbacks[0]);
+ if (!(callbacks[1] instanceof PBEKeySpecCallback))
+ throw new UnsupportedCallbackException(callbacks[0]);
+
+ PasswordCallback passwordCb = (PasswordCallback) callbacks[0];
+ passwordCb.setPassword(password);
+ PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1];
+ handleKeySpecCallback(pbeCb);
+ }
+
+ }
+}
+++ /dev/null
-package org.argeo.cms;
-
-import java.time.ZonedDateTime;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-
-import org.argeo.cms.auth.SystemRole;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.directory.HierarchyUnit;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/**
- * Provide method interfaces to manage user concepts without accessing directly
- * the userAdmin.
- */
-public interface CmsUserManager {
- Map<String, String> getKnownBaseDns(boolean onlyWritable);
-
- Set<UserDirectory> getUserDirectories();
-
- // CurrentUser
- /** Returns the e-mail of the current logged in user */
- String getMyMail();
-
- // Other users
- /** Returns a {@link User} given a username */
- User getUser(String username);
-
- /** Can be a group or a user */
- String getUserDisplayName(String dn);
-
- /** Can be a group or a user */
- String getUserMail(String dn);
-
- /** Lists all roles of the given user */
- String[] getUserRoles(String dn);
-
- /** Checks if the passed user belongs to the passed role */
- boolean isUserInRole(String userDn, String roleDn);
-
- // Search
- /** Returns a filtered list of roles */
- Role[] getRoles(String filter) throws InvalidSyntaxException;
-
- /** Recursively lists users in a given group. */
- Set<User> listUsersInGroup(String groupDn, String filter);
-
- /** Search among groups including system roles and users if needed */
- List<User> listGroups(String filter, boolean includeUsers, boolean includeSystemRoles);
-
-// /**
-// * Lists functional accounts, that is users with regular access to the system
-// * under this functional hierarchy unit (which probably have technical direct
-// * sub hierarchy units), excluding groups which are not explicitly users.
-// */
-// Set<User> listAccounts(HierarchyUnit hierarchyUnit, boolean deep);
-
- /*
- * EDITION
- */
- /** Creates a new user. */
- User createUser(String username, Map<String, Object> properties, Map<String, Object> credentials);
-
- /** Creates a group. */
- Group getOrCreateGroup(HierarchyUnit groups, String commonName);
-
- /** Creates a new system role. */
- Group getOrCreateSystemRole(HierarchyUnit roles, SystemRole systemRole);
-
- /** Add additional object classes to this role. */
- void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties);
-
- /** Add additional object classes to this hierarchy unit. */
- void addObjectClasses(HierarchyUnit hierarchyUnit, Set<String> objectClasses,
- Map<String, Object> additionalProperties);
-
- /** Add a member to this group. */
- void addMember(Group group, Role role);
-
- void edit(Runnable action);
-
- /* MISCELLANEOUS */
- /** Returns the dn of a role given its local ID */
- String buildDefaultDN(String localId, int type);
-
- /** Exposes the main default domain name for this instance */
- String getDefaultDomainName();
-
- /**
- * Search for a {@link User} (might also be a group) whose uid or cn is equals
- * to localId within the various user repositories defined in the current
- * context.
- */
- User getUserFromLocalId(String localId);
-
- void changeOwnPassword(char[] oldPassword, char[] newPassword);
-
- void resetPassword(String username, char[] newPassword);
-
- @Deprecated
- String addSharedSecret(String username, int hours);
-
-// String addSharedSecret(String username, String authInfo, String authToken);
-
- void addAuthToken(String userDn, String token, Integer hours, String... roles);
-
- void addAuthToken(String userDn, String token, ZonedDateTime expiryDate, String... roles);
-
- void expireAuthToken(String token);
-
- void expireAuthTokens(Subject subject);
-
- UserDirectory getDirectory(Role role);
-
- /** Create a new hierarchy unit. Does nothing if it already exists. */
- HierarchyUnit getOrCreateHierarchyUnit(UserDirectory directory, String path);
-}
\ No newline at end of file
--- /dev/null
+package org.argeo.cms;
+
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.auth.x500.X500Principal;
+
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsSession;
+import org.argeo.api.cms.CmsSessionId;
+import org.argeo.cms.internal.auth.CmsSessionImpl;
+import org.argeo.cms.internal.auth.ImpliedByPrincipal;
+import org.argeo.cms.internal.runtime.CmsContextImpl;
+import org.argeo.cms.util.CurrentSubject;
+import org.osgi.service.useradmin.Authorization;
+
+/**
+ * Programmatic access to the currently authenticated user, within a CMS
+ * context.
+ */
+public final class CurrentUser {
+ /**
+ * Technical username of the currently authenticated user.
+ *
+ * @return the authenticated username or null if not authenticated / anonymous
+ */
+ public static String getUsername() {
+ return getUsername(currentSubject());
+ }
+
+ /**
+ * Human readable name of the currently authenticated user (typically first name
+ * and last name).
+ */
+ public static String getDisplayName() {
+ return getDisplayName(currentSubject());
+ }
+
+ /** Whether a user is currently authenticated. */
+ public static boolean isAnonymous() {
+ return isAnonymous(currentSubject());
+ }
+
+ /** Locale of the current user */
+ public static Locale locale() {
+ return locale(currentSubject());
+ }
+
+ /** Roles of the currently logged-in user */
+ public static Set<String> roles() {
+ return roles(currentSubject());
+ }
+
+ /** Returns true if the current user is in the specified role */
+ public static boolean isInRole(String role) {
+ Set<String> roles = roles();
+ return roles.contains(role);
+ }
+
+ /** Implies this {@link SystemRole} in this context. */
+ public static boolean implies(SystemRole role, String context) {
+ return role.implied(currentSubject(), context);
+ }
+
+ /** Implies this role name, also independently of the context. */
+ public static boolean implies(String role, String context) {
+ return SystemRole.implied(NamespaceUtils.parsePrefixedName(role), currentSubject(), context);
+ }
+
+ /** Get the primary context this user belongs to. */
+ public static boolean isUserContext(String context) {
+ // TODO have the role context as a separated credential in the Subjecto?
+ return RoleNameUtils.getContext(getUsername()).equalsIgnoreCase(context);
+ }
+
+ /** Executes as the current user */
+ public static <T> T doAs(PrivilegedAction<T> action) {
+ return Subject.doAs(currentSubject(), action);
+ }
+
+ /** Executes as the current user */
+ public static <T> T tryAs(PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
+ return Subject.doAs(currentSubject(), action);
+ }
+
+ /*
+ * WRAPPERS
+ */
+
+ public static String getUsername(Subject subject) {
+ if (subject == null)
+ throw new IllegalArgumentException("Subject cannot be null");
+ if (subject.getPrincipals(X500Principal.class).size() != 1)
+ return CmsConstants.ROLE_ANONYMOUS;
+ Principal principal = subject.getPrincipals(X500Principal.class).iterator().next();
+ return principal.getName();
+ }
+
+ public static String getDisplayName(Subject subject) {
+ return getAuthorization(subject).toString();
+ }
+
+ public static Set<String> roles(Subject subject) {
+ Set<String> roles = new HashSet<String>();
+ roles.add(getUsername(subject));
+ for (Principal group : subject.getPrincipals(ImpliedByPrincipal.class)) {
+ roles.add(group.getName());
+ }
+ return roles;
+ }
+
+ public static Locale locale(Subject subject) {
+ Set<Locale> locales = subject.getPublicCredentials(Locale.class);
+ if (locales.isEmpty()) {
+ Locale defaultLocale = CmsContextImpl.getCmsContext().getDefaultLocale();
+ return defaultLocale;
+ } else
+ return locales.iterator().next();
+ }
+
+ /** Whether this user is currently authenticated. */
+ public static boolean isAnonymous(Subject subject) {
+ if (subject == null)
+ return true;
+ String username = getUsername(subject);
+ return username == null || username.equalsIgnoreCase(CmsConstants.ROLE_ANONYMOUS);
+ }
+
+ public static CmsSession getCmsSession() {
+ Subject subject = currentSubject();
+ Iterator<CmsSessionId> it = subject.getPrivateCredentials(CmsSessionId.class).iterator();
+ if (!it.hasNext())
+ throw new IllegalStateException("No CMS session id available for " + subject);
+ CmsSessionId cmsSessionId = it.next();
+ if (it.hasNext())
+ throw new IllegalStateException("More than one CMS session id available for " + subject);
+ return CmsContextImpl.getCmsContext().getCmsSessionByUuid(cmsSessionId.getUuid());
+ }
+
+ public static boolean isAvailable() {
+ return CurrentSubject.current() != null;
+ }
+
+ /*
+ * HELPERS
+ */
+ private static Subject currentSubject() {
+ Subject subject = CurrentSubject.current();
+ if (subject == null)
+ throw new IllegalStateException("Cannot find related subject");
+ return subject;
+ }
+
+ private static Authorization getAuthorization(Subject subject) {
+ return subject.getPrivateCredentials(Authorization.class).iterator().next();
+ }
+
+ public static boolean logoutCmsSession(Subject subject) {
+ UUID nodeSessionId;
+ if (subject.getPrivateCredentials(CmsSessionId.class).size() == 1)
+ nodeSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next().getUuid();
+ else
+ return false;
+ CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByUuid(nodeSessionId);
+
+ // FIXME logout all views
+ // TODO check why it is sometimes null
+ if (cmsSession != null)
+ cmsSession.close();
+ // if (log.isDebugEnabled())
+ // log.debug("Logged out CMS session " + cmsSession.getUuid());
+ return true;
+ }
+
+ /** singleton */
+ private CurrentUser() {
+ }
+}
import java.util.ResourceBundle;
import org.argeo.api.cms.CmsLog;
-import org.argeo.cms.auth.CurrentUser;
/** Utilities simplifying the development of localization enums. */
public class LocaleUtils {
--- /dev/null
+package org.argeo.cms;
+
+import static org.argeo.api.acr.RuntimeNamespaceContext.getNamespaceContext;
+
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.ArgeoNamespace;
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.cms.directory.ldap.LdapNameUtils;
+
+/** Simplifies analysis of system roles. */
+public class RoleNameUtils {
+ public static String getLastRdnValue(String dn) {
+ return LdapNameUtils.getLastRdnValue(dn);
+// // we don't use LdapName for portability with Android
+// // TODO make it more robust
+// String[] parts = dn.split(",");
+// String[] rdn = parts[0].split("=");
+// return rdn[1];
+ }
+
+ public static QName getLastRdnAsName(String dn) {
+ String cn = getLastRdnValue(dn);
+ QName roleName = NamespaceUtils.parsePrefixedName(getNamespaceContext(), cn);
+ return roleName;
+ }
+
+ public static boolean isSystemRole(QName roleName) {
+ return roleName.getNamespaceURI().equals(ArgeoNamespace.ROLE_NAMESPACE_URI);
+ }
+
+ public static String getParent(String dn) {
+ int index = dn.indexOf(',');
+ return dn.substring(index + 1);
+ }
+
+ /** Up two levels. */
+ public static String getContext(String dn) {
+ return getParent(getParent(dn));
+ }
+}
--- /dev/null
+package org.argeo.cms;
+
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.xml.namespace.QName;
+
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.cms.internal.auth.ImpliedByPrincipal;
+
+/** A programmatic role. */
+public interface SystemRole {
+ QName qName();
+
+ /** Whether this role is implied for this authenticated user. */
+ default boolean implied(Subject subject, String context) {
+ return implied(qName(), subject, context);
+ }
+
+ /** Whether this role is implied for this distinguished name. */
+ default boolean implied(String dn, String context) {
+ String roleContext = RoleNameUtils.getContext(dn);
+ QName roleName = RoleNameUtils.getLastRdnAsName(dn);
+ return roleContext.equalsIgnoreCase(context) && qName().equals(roleName);
+ }
+
+ /**
+ * Whether this role is implied for this authenticated subject. If context is
+ * <code>null</code>, it is not considered; this should be used to build user
+ * interfaces, but not to authorise.
+ */
+ static boolean implied(QName name, Subject subject, String context) {
+ Set<ImpliedByPrincipal> roles = subject.getPrincipals(ImpliedByPrincipal.class);
+ for (ImpliedByPrincipal role : roles) {
+ if (role.isSystemRole()) {
+ if (role.getRoleName().equals(name)) {
+ // !! if context is not specified, it is considered irrelevant
+ if (context == null)
+ return true;
+ if (role.getContext().equalsIgnoreCase(context)
+ || role.getContext().equals(CmsConstants.NODE_BASEDN))
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.util.LangUtils;
+import org.argeo.cms.util.LangUtils;
/** Partial reference implementation of a {@link ProvidedContent}. */
public abstract class AbstractContent extends AbstractMap<QName, Object> implements ProvidedContent {
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.Content;
import org.argeo.api.acr.CrName;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.RuntimeNamespaceContext;
+import org.argeo.api.acr.spi.ContentNamespace;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedRepository;
}
}
- public void registerTypes(String prefix, String namespaceURI, String schemaSystemId) {
- typesManager.registerTypes(prefix, namespaceURI, schemaSystemId);
+ @Override
+ public void registerTypes(ContentNamespace... namespaces) {
+ typesManager.registerTypes(namespaces);
}
/*
// document = dBuilder.parse(inputSource);
// } else {
document = dBuilder.newDocument();
- Element root = document.createElementNS(CrName.CR_NAMESPACE_URI,
+ Element root = document.createElementNS(ArgeoNamespace.CR_NAMESPACE_URI,
NamespaceUtils.toPrefixedName(CrName.root.qName()));
for (String prefix : RuntimeNamespaceContext.getPrefixes().keySet()) {
--- /dev/null
+package org.argeo.cms.acr;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Objects;
+
+import org.argeo.api.acr.ArgeoNamespace;
+import org.argeo.api.acr.spi.ContentNamespace;
+
+/** Content namespaces supported by CMS. */
+public enum CmsContentNamespace implements ContentNamespace {
+ //
+ // ARGEO
+ //
+ CR(ArgeoNamespace.CR_DEFAULT_PREFIX, ArgeoNamespace.CR_NAMESPACE_URI, "cr.xsd", null),
+ //
+ SLC("slc", "http://www.argeo.org/ns/slc", null, null),
+ //
+ ARGEO("argeo", "http://www.argeo.org/ns/argeo", null, null),
+ //
+ // EXTERNAL
+ //
+ XSD("xs", "http://www.w3.org/2001/XMLSchema", "XMLSchema.xsd", "http://www.w3.org/2001/XMLSchema.xsd"),
+ //
+ XML("xml", "http://www.w3.org/XML/1998/namespace", "xml.xsd", "http://www.w3.org/2001/xml.xsd"),
+ //
+ XLINK("xlink", "http://www.w3.org/1999/xlink", "xlink.xsd", "https://www.w3.org/1999/xlink.xsd"),
+ //
+ WEBDAV("D", "DAV:", null, "https://raw.githubusercontent.com/lookfirst/sardine/master/webdav.xsd"),
+ //
+ XSLT("xsl", "http://www.w3.org/1999/XSL/Transform", "schema-for-xslt20.xsd",
+ "https://www.w3.org/2007/schema-for-xslt20.xsd"),
+ //
+ SVG("svg", "http://www.w3.org/2000/svg", "SVG.xsd",
+ "https://raw.githubusercontent.com/oreillymedia/HTMLBook/master/schema/svg/SVG.xsd"),
+ //
+ DSML("dsml", "urn:oasis:names:tc:DSML:2:0:core", "DSMLv2.xsd",
+ "https://www.oasis-open.org/committees/dsml/docs/DSMLv2.xsd"),
+ //
+ ;
+
+ private final static String RESOURCE_BASE = "/org/argeo/cms/acr/schemas/";
+
+ private String defaultPrefix;
+ private String namespace;
+ private URL resource;
+ private URL publicUrl;
+
+ CmsContentNamespace(String defaultPrefix, String namespace, String resourceFileName, String publicUrl) {
+ Objects.requireNonNull(namespace);
+ this.defaultPrefix = defaultPrefix;
+ Objects.requireNonNull(namespace);
+ this.namespace = namespace;
+ if (resourceFileName != null) {
+ resource = getClass().getResource(RESOURCE_BASE + resourceFileName);
+ Objects.requireNonNull(resource);
+ }
+ if (publicUrl != null)
+ try {
+ this.publicUrl = new URL(publicUrl);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Cannot interpret public URL", e);
+ }
+ }
+
+ @Override
+ public String getDefaultPrefix() {
+ return defaultPrefix;
+ }
+
+ @Override
+ public String getNamespaceURI() {
+ return namespace;
+ }
+
+ @Override
+ public URL getSchemaResource() {
+ return resource;
+ }
+
+ public URL getPublicUrl() {
+ return publicUrl;
+ }
+
+}
import org.argeo.api.cms.CmsState;
import org.argeo.api.cms.DataAdminPrincipal;
import org.argeo.api.uuid.UuidFactory;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.util.CurrentSubject;
+import org.argeo.cms.util.CurrentSubject;
/**
* Multi-session {@link ProvidedRepository}, integrated with a CMS.
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentSession;
-import org.argeo.api.acr.CrName;
import org.argeo.api.acr.DName;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
}
/*
- * NAMESPACE CONTEXT
+ * EDITION
*/
-
-// @Override
-// public String getNamespaceURI(String prefix) {
-// return RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix);
-//// return NamespaceUtils.getNamespaceURI((p) -> contentRepository.getTypesManager().getPrefixes().get(p), prefix);
-// }
-//
-// @Override
-// public Iterator<String> getPrefixes(String namespaceURI) {
-// return RuntimeNamespaceContext.getNamespaceContext().getPrefixes(namespaceURI);
-//// return NamespaceUtils.getPrefixes((ns) -> contentRepository.getTypesManager().getPrefixes().entrySet().stream()
-//// .filter(e -> e.getValue().equals(ns)).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()),
-//// namespaceURI);
-// }
-
@Override
public CompletionStage<ContentSession> edit(Consumer<ContentSession> work) {
edition = CompletableFuture.supplyAsync(() -> {
return uuid;
}
- @Override
+// @Override
public Content getSessionRunDir() {
if (sessionRunDir == null) {
String runDirPath = CmsContentRepository.RUN_BASE + '/' + uuid.toString();
else {
Content runDir = get(CmsContentRepository.RUN_BASE);
// TODO deal with no run dir available?
- sessionRunDir = runDir.add(uuid.toString(),DName.collection.qName());
+ sessionRunDir = runDir.add(uuid.toString(), DName.collection.qName());
}
}
return sessionRunDir;
}
-
-// @Override
-// public String findNamespace(String prefix) {
-// return prefixes.get(prefix);
-// }
-//
-// @Override
-// public Set<String> findPrefixes(String namespaceURI) {
-// Set<String> res = prefixes.entrySet().stream().filter(e -> e.getValue().equals(namespaceURI))
-// .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet());
-//
-// return res;
-// }
-//
-// @Override
-// public String findPrefix(String namespaceURI) {
-// if (CrName.CR_NAMESPACE_URI.equals(namespaceURI) && prefixes.containsKey(CrName.CR_DEFAULT_PREFIX))
-// return CrName.CR_DEFAULT_PREFIX;
-// return ProvidedSession.super.findPrefix(namespaceURI);
-// }
-
}
\ No newline at end of file
+++ /dev/null
-package org.argeo.cms.acr;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Objects;
-
-import org.argeo.api.acr.CrName;
-
-public enum CmsContentTypes {
- //
- // ARGEO
- //
- CR_2(CrName.CR_DEFAULT_PREFIX, CrName.CR_NAMESPACE_URI, "cr.xsd", null),
- //
- SLC("slc", "http://www.argeo.org/ns/slc", null, null),
- //
- ARGEO_LEGACY("argeo", "http://www.argeo.org/ns/argeo", null, null),
- //
- // EXTERNAL
- //
- XSD_2001("xs", "http://www.w3.org/2001/XMLSchema", "XMLSchema.xsd", "http://www.w3.org/2001/XMLSchema.xsd"),
- //
- XML_1998("xml", "http://www.w3.org/XML/1998/namespace", "xml.xsd", "http://www.w3.org/2001/xml.xsd"),
- //
- XLINK_1999("xlink", "http://www.w3.org/1999/xlink", "xlink.xsd", "http://www.w3.org/XML/2008/06/xlink.xsd"),
- //
- WEBDAV("D", "DAV:", null, "https://raw.githubusercontent.com/lookfirst/sardine/master/webdav.xsd"),
- //
- XSLT_2_0("xsl", "http://www.w3.org/1999/XSL/Transform", "schema-for-xslt20.xsd",
- "https://www.w3.org/2007/schema-for-xslt20.xsd"),
- //
- SVG_1_1("svg", "http://www.w3.org/2000/svg", "SVG.xsd",
- "https://raw.githubusercontent.com/oreillymedia/HTMLBook/master/schema/svg/SVG.xsd"),
- //
- DOCBOOK_5_0_1("dbk", "http://docbook.org/ns/docbook", "docbook.xsd",
- "http://docbook.org/xml/5.0.1/xsd/docbook.xsd"),
- //
- XML_EVENTS_2001("ev", "http://www.w3.org/2001/xml-events", "xml-events-attribs-1.xsd",
- "http://www.w3.org/MarkUp/SCHEMA/xml-events-attribs-1.xsd"),
- //
- XFORMS_2002("xforms", "http://www.w3.org/2002/xforms", "XForms-11-Schema.xsd",
- "https://www.w3.org/MarkUp/Forms/2007/XForms-11-Schema.xsd"),
- //
- DSML_v2("dsml", "urn:oasis:names:tc:DSML:2:0:core", "DSMLv2.xsd",
- "https://www.oasis-open.org/committees/dsml/docs/DSMLv2.xsd"),
- //
- // JCR (to be moved elsewhere)
- //
- JCR("jcr", "http://www.jcp.org/jcr/1.0", null,
- "https://jackrabbit.apache.org/archive/wiki/JCR/NamespaceRegistry_115513459.html"),
- //
- JCR_MIX("mix", "http://www.jcp.org/jcr/mix/1.0", null,
- "https://jackrabbit.apache.org/archive/wiki/JCR/NamespaceRegistry_115513459.html"),
- //
- JCR_NT("nt", "http://www.jcp.org/jcr/nt/1.0", null,
- "https://jackrabbit.apache.org/archive/wiki/JCR/NamespaceRegistry_115513459.html"),
- //
- JACKRABBIT("rep", "internal", null,
- "https://jackrabbit.apache.org/archive/wiki/JCR/NamespaceRegistry_115513459.html"),
- //
- JCRX("jcrx", "http://www.argeo.org/ns/jcrx", null, null),
- //
- ;
-
- private final static String RESOURCE_BASE = "/org/argeo/cms/acr/schemas/";
-
- private String defaultPrefix;
- private String namespace;
- private URL resource;
- private URL publicUrl;
-
- CmsContentTypes(String defaultPrefix, String namespace, String resourceFileName, String publicUrl) {
- Objects.requireNonNull(namespace);
- this.defaultPrefix = defaultPrefix;
- Objects.requireNonNull(namespace);
- this.namespace = namespace;
- if (resourceFileName != null) {
- resource = getClass().getResource(RESOURCE_BASE + resourceFileName);
- Objects.requireNonNull(resource);
- }
- if (publicUrl != null)
- try {
- this.publicUrl = new URL(publicUrl);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException("Cannot interpret public URL", e);
- }
- }
-
- public String getDefaultPrefix() {
- return defaultPrefix;
- }
-
- public String getNamespace() {
- return namespace;
- }
-
- public URL getResource() {
- return resource;
- }
-
- public URL getPublicUrl() {
- return publicUrl;
- }
-
-}
import org.argeo.api.acr.ContentSession;
import org.argeo.api.acr.DName;
import org.argeo.api.cms.CmsAuth;
-import org.argeo.cms.CmsUserManager;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.CurrentSubject;
-import org.argeo.util.directory.Directory;
-import org.argeo.util.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.CmsUserManager;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.UserDirectory;
+import org.argeo.cms.util.CurrentSubject;
import org.osgi.service.useradmin.Role;
/** Utilities and routines around {@link Content}. */
}
public static Content hierarchyUnitToContent(ContentSession contentSession, HierarchyUnit hierarchyUnit) {
- Directory directory = hierarchyUnit.getDirectory();
+ CmsDirectory directory = hierarchyUnit.getDirectory();
StringJoiner relativePath = new StringJoiner(SLASH_STRING);
buildHierarchyUnitPath(hierarchyUnit, relativePath);
String path = directoryPath(directory) + relativePath.toString();
return content;
}
- /** The path to this {@link Directory}. Ends with a /. */
- private static String directoryPath(Directory directory) {
+ /** The path to this {@link CmsDirectory}. Ends with a /. */
+ private static String directoryPath(CmsDirectory directory) {
return CmsContentRepository.DIRECTORY_BASE + SLASH + directory.getName() + SLASH;
}
import javax.security.auth.x500.X500Principal;
import org.argeo.api.acr.ContentSession;
+import org.argeo.api.acr.ldap.LdapAttr;
import org.argeo.api.acr.spi.ProvidedRepository;
import org.argeo.api.uuid.MacAddressUuidFactory;
import org.argeo.api.uuid.UuidFactory;
import org.argeo.cms.acr.fs.FsContentProvider;
-import org.argeo.util.naming.LdapAttrs;
/**
* A standalone {@link ProvidedRepository} with a single {@link Subject} (which
public static void main(String... args) {
Path homePath = Paths.get(System.getProperty("user.home"));
String username = System.getProperty("user.name");
- X500Principal principal = new X500Principal(LdapAttrs.uid + "=" + username + ",dc=localhost");
+ X500Principal principal = new X500Principal(LdapAttr.uid + "=" + username + ",dc=localhost");
Subject subject = new Subject();
subject.getPrincipals().add(principal);
@Override
public String getNamespace() {
- return CmsContentTypes.SVG_1_1.getNamespace();
+ return CmsContentNamespace.SVG.getNamespaceURI();
}
@Override
public String getDefaultPrefix() {
- return CmsContentTypes.SVG_1_1.getDefaultPrefix();
+ return CmsContentNamespace.SVG.getDefaultPrefix();
}
}
package org.argeo.cms.acr;
import java.io.IOException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.argeo.api.acr.CrAttributeType;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.RuntimeNamespaceContext;
+import org.argeo.api.acr.spi.ContentNamespace;
import org.argeo.api.cms.CmsLog;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
private SchemaFactory schemaFactory;
/** Schema sources. */
- private List<Source> sources = new ArrayList<>();
+ private List<URL> sources = new ArrayList<>();
// cached
private Schema schema;
private XSModel xsModel;
private SortedMap<QName, Map<QName, CrAttributeType>> types;
- private boolean validating = true;
+ private boolean validating = false;
+ private boolean creatingXsModel = false;
private final static boolean limited = false;
}
public void init() {
- for (CmsContentTypes cs : CmsContentTypes.values()) {
- if (cs.getResource() != null) {
- StreamSource source = new StreamSource(cs.getResource().toExternalForm());
- sources.add(source);
- }
- RuntimeNamespaceContext.register(cs.getNamespace(), cs.getDefaultPrefix());
- }
-
- reload();
+ registerTypes(CmsContentNamespace.values());
}
- public void registerTypes(String defaultPrefix, String namespace, String xsdSystemId) {
+ public void registerTypes(ContentNamespace... namespaces) {
// if (prefixes.containsKey(defaultPrefix))
// throw new IllegalStateException(
// "Prefix " + defaultPrefix + " is already mapped with " + prefixes.get(defaultPrefix));
// prefixes.put(defaultPrefix, namespace);
- RuntimeNamespaceContext.register(namespace, defaultPrefix);
+ for (ContentNamespace contentNamespace : namespaces) {
+ RuntimeNamespaceContext.register(contentNamespace.getNamespaceURI(), contentNamespace.getDefaultPrefix());
- if (xsdSystemId != null) {
- sources.add(new StreamSource(xsdSystemId));
- reload();
- log.debug(() -> "Registered types " + namespace + " from " + xsdSystemId);
+ if (contentNamespace.getSchemaResource() != null) {
+ sources.add(contentNamespace.getSchemaResource());
+ log.debug(() -> "Registered types " + contentNamespace.getNamespaceURI() + " from "
+ + contentNamespace.getSchemaResource().toExternalForm());
+ }
}
+ reload();
}
public Set<QName> listTypes() {
private synchronized void reload() {
try {
// schema
- schema = schemaFactory.newSchema(sources.toArray(new Source[sources.size()]));
+ if (validating) {
+ List<StreamSource> sourcesToUse = new ArrayList<>();
+ for (URL sourceUrl : sources) {
+ sourcesToUse.add(new StreamSource(sourceUrl.toExternalForm()));
+ }
+ schema = schemaFactory.newSchema(sourcesToUse.toArray(new Source[sourcesToUse.size()]));
+// for (StreamSource source : sourcesToUse) {
+// try {
+// source.getInputStream().close();
+// } catch (IOException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+// }
+ }
// document builder factory
// we force usage of Xerces for predictability
documentBuilderFactory.setNamespaceAware(true);
if (!limited) {
documentBuilderFactory.setXIncludeAware(true);
- documentBuilderFactory.setSchema(getSchema());
- documentBuilderFactory.setValidating(validating);
+ if (validating) {
+ documentBuilderFactory.setSchema(getSchema());
+ documentBuilderFactory.setValidating(validating);
+ }
}
- // XS model
- // TODO use JVM implementation?
+ if (creatingXsModel) {
+ // XS model
+ // TODO use JVM implementation?
// DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
// XSImplementation implementation = (XSImplementation) registry.getDOMImplementation("XS-Loader");
- XSImplementation xsImplementation = new XSImplementationImpl();
- XSLoader xsLoader = xsImplementation.createXSLoader(null);
- List<String> systemIds = new ArrayList<>();
- for (Source source : sources) {
- systemIds.add(source.getSystemId());
- }
- StringList sl = new StringListImpl(systemIds.toArray(new String[systemIds.size()]), systemIds.size());
- xsModel = xsLoader.loadURIList(sl);
+ XSImplementation xsImplementation = new XSImplementationImpl();
+ XSLoader xsLoader = xsImplementation.createXSLoader(null);
+ List<String> systemIds = new ArrayList<>();
+ for (URL sourceUrl : sources) {
+ systemIds.add(sourceUrl.toExternalForm());
+ }
+ StringList sl = new StringListImpl(systemIds.toArray(new String[systemIds.size()]), systemIds.size());
+ xsModel = xsLoader.loadURIList(sl);
- // types
+ // types
// XSNamedMap map = xsModel.getComponents(XSConstants.ELEMENT_DECLARATION);
// for (int i = 0; i < map.getLength(); i++) {
// XSElementDeclaration eDec = (XSElementDeclaration) map.item(i);
// QName type = new QName(eDec.getNamespace(), eDec.getName());
// types.add(type);
// }
- collectTypes();
+ collectTypes();
+
+ log.debug("Created XS model");
+ }
} catch (XSException | SAXException e) {
throw new IllegalStateException("Cannot reload types", e);
}
}
public void printTypes() {
- try {
-
- // Convert top level complex type definitions to node types
- log.debug("\n## TYPES");
- XSNamedMap map = xsModel.getComponents(XSConstants.TYPE_DEFINITION);
- for (int i = 0; i < map.getLength(); i++) {
- XSTypeDefinition tDef = (XSTypeDefinition) map.item(i);
- log.debug(tDef);
- }
- // Convert local (anonymous) complex type defs found in top level
- // element declarations
- log.debug("\n## ELEMENTS");
- map = xsModel.getComponents(XSConstants.ELEMENT_DECLARATION);
- for (int i = 0; i < map.getLength(); i++) {
- XSElementDeclaration eDec = (XSElementDeclaration) map.item(i);
- XSTypeDefinition tDef = eDec.getTypeDefinition();
- log.debug(eDec + ", " + tDef);
- }
- log.debug("\n## ATTRIBUTES");
- map = xsModel.getComponents(XSConstants.ATTRIBUTE_DECLARATION);
- for (int i = 0; i < map.getLength(); i++) {
- XSAttributeDeclaration eDec = (XSAttributeDeclaration) map.item(i);
- XSTypeDefinition tDef = eDec.getTypeDefinition();
- log.debug(eDec.getNamespace() + ":" + eDec.getName() + ", " + tDef);
+ if (xsModel != null)
+ try {
+
+ // Convert top level complex type definitions to node types
+ log.debug("\n## TYPES");
+ XSNamedMap map = xsModel.getComponents(XSConstants.TYPE_DEFINITION);
+ for (int i = 0; i < map.getLength(); i++) {
+ XSTypeDefinition tDef = (XSTypeDefinition) map.item(i);
+ log.debug(tDef);
+ }
+ // Convert local (anonymous) complex type defs found in top level
+ // element declarations
+ log.debug("\n## ELEMENTS");
+ map = xsModel.getComponents(XSConstants.ELEMENT_DECLARATION);
+ for (int i = 0; i < map.getLength(); i++) {
+ XSElementDeclaration eDec = (XSElementDeclaration) map.item(i);
+ XSTypeDefinition tDef = eDec.getTypeDefinition();
+ log.debug(eDec + ", " + tDef);
+ }
+ log.debug("\n## ATTRIBUTES");
+ map = xsModel.getComponents(XSConstants.ATTRIBUTE_DECLARATION);
+ for (int i = 0; i < map.getLength(); i++) {
+ XSAttributeDeclaration eDec = (XSAttributeDeclaration) map.item(i);
+ XSTypeDefinition tDef = eDec.getTypeDefinition();
+ log.debug(eDec.getNamespace() + ":" + eDec.getName() + ", " + tDef);
+ }
+ } catch (ClassCastException | XSException e) {
+ throw new RuntimeException(e);
}
- } catch (ClassCastException | XSException e) {
- throw new RuntimeException(e);
- }
}
// return prefixes;
// }
- public List<Source> getSources() {
- return sources;
- }
+// public List<Source> getSources() {
+// return sources;
+// }
public Schema getSchema() {
return schema;
import org.argeo.cms.acr.AbstractContent;
import org.argeo.cms.acr.ContentUtils;
import org.argeo.cms.dav.DavResponse;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpStatus;
public class DavContent extends AbstractContent {
private final DavContentProvider provider;
import org.argeo.api.acr.spi.ProvidedSession;
import org.argeo.cms.dav.DavClient;
import org.argeo.cms.dav.DavResponse;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpStatus;
public class DavContentProvider implements ContentProvider {
private String mountPath;
import javax.xml.namespace.QName;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.ContentName;
import org.argeo.api.acr.CrAttributeType;
-import org.argeo.api.acr.CrName;
import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.acr.ldap.LdapObj;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedSession;
import org.argeo.cms.acr.AbstractContent;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
abstract class AbstractDirectoryContent extends AbstractContent {
protected final DirectoryContentProvider provider;
Set<QName> keys = new TreeSet<>(NamespaceUtils.QNAME_COMPARATOR);
keys: for (Enumeration<String> it = properties.keys(); it.hasMoreElements();) {
String key = it.nextElement();
- if (key.equalsIgnoreCase(LdapAttrs.objectClass.name()))
+ if (key.equalsIgnoreCase(LdapAttr.objectClass.name()))
continue keys;
- if (key.equalsIgnoreCase(LdapAttrs.objectClasses.name()))
+ if (key.equalsIgnoreCase(LdapAttr.objectClasses.name()))
continue keys;
- ContentName name = new ContentName(CrName.LDAP_NAMESPACE_URI, key, provider);
+ ContentName name = new ContentName(ArgeoNamespace.LDAP_NAMESPACE_URI, key, provider);
keys.add(name);
}
return keys;
public List<QName> getContentClasses() {
Dictionary<String, Object> properties = doGetProperties();
List<QName> contentClasses = new ArrayList<>();
- String objectClass = properties.get(LdapAttrs.objectClass.name()).toString();
- contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, objectClass, provider));
+ String objectClass = properties.get(LdapAttr.objectClass.name()).toString();
+ contentClasses.add(new ContentName(ArgeoNamespace.LDAP_NAMESPACE_URI, objectClass, provider));
- String[] objectClasses = properties.get(LdapAttrs.objectClasses.name()).toString().split("\\n");
+ String[] objectClasses = properties.get(LdapAttr.objectClasses.name()).toString().split("\\n");
objectClasses: for (String oc : objectClasses) {
- if (LdapObjs.top.name().equalsIgnoreCase(oc))
+ if (LdapObj.top.name().equalsIgnoreCase(oc))
continue objectClasses;
if (objectClass.equalsIgnoreCase(oc))
continue objectClasses;
- contentClasses.add(new ContentName(CrName.LDAP_NAMESPACE_URI, oc, provider));
+ contentClasses.add(new ContentName(ArgeoNamespace.LDAP_NAMESPACE_URI, oc, provider));
}
return contentClasses;
}
@Override
public Object put(QName key, Object value) {
Object previous = get(key);
- // TODO deal with typing
- doGetProperties().put(key.getLocalPart(), value);
+ provider.getUserManager().edit(() -> doGetProperties().put(key.getLocalPart(), value));
return previous;
}
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentName;
import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.util.directory.Directory;
-import org.argeo.util.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.HierarchyUnit;
class DirectoryContent extends AbstractDirectoryContent {
- private Directory directory;
+ private CmsDirectory directory;
- public DirectoryContent(ProvidedSession session, DirectoryContentProvider provider, Directory directory) {
+ public DirectoryContent(ProvidedSession session, DirectoryContentProvider provider, CmsDirectory directory) {
super(session, provider);
this.directory = directory;
}
return provider.getRootContent(getSession());
}
+ @SuppressWarnings("unchecked")
+ @Override
+ public <A> A adapt(Class<A> clss) {
+ if (clss.equals(HierarchyUnit.class))
+ return (A) directory;
+ if (clss.equals(CmsDirectory.class))
+ return (A) directory;
+ return super.adapt(clss);
+ }
+
}
import javax.xml.namespace.QName;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentName;
import org.argeo.api.acr.ContentNotFoundException;
-import org.argeo.api.acr.CrName;
import org.argeo.api.acr.spi.ContentProvider;
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.cms.CmsUserManager;
+import org.argeo.api.cms.directory.CmsUserManager;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.UserDirectory;
import org.argeo.cms.acr.AbstractContent;
import org.argeo.cms.acr.ContentUtils;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.directory.HierarchyUnit;
import org.osgi.service.useradmin.User;
public class DirectoryContentProvider implements ContentProvider {
@Override
public String getNamespaceURI(String prefix) {
- if (CrName.LDAP_DEFAULT_PREFIX.equals(prefix))
- return CrName.LDAP_NAMESPACE_URI;
- throw new IllegalArgumentException("Only prefix " + CrName.LDAP_DEFAULT_PREFIX + " is supported");
+ if (ArgeoNamespace.LDAP_DEFAULT_PREFIX.equals(prefix))
+ return ArgeoNamespace.LDAP_NAMESPACE_URI;
+ throw new IllegalArgumentException("Only prefix " + ArgeoNamespace.LDAP_DEFAULT_PREFIX + " is supported");
}
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
- if (CrName.LDAP_NAMESPACE_URI.equals(namespaceURI))
- return Collections.singletonList(CrName.LDAP_DEFAULT_PREFIX).iterator();
- throw new IllegalArgumentException("Only namespace URI " + CrName.LDAP_NAMESPACE_URI + " is supported");
+ if (ArgeoNamespace.LDAP_NAMESPACE_URI.equals(namespaceURI))
+ return Collections.singletonList(ArgeoNamespace.LDAP_DEFAULT_PREFIX).iterator();
+ throw new IllegalArgumentException("Only namespace URI " + ArgeoNamespace.LDAP_NAMESPACE_URI + " is supported");
}
public void setUserManager(CmsUserManager userManager) {
this.userManager = userManager;
}
+ public CmsUserManager getUserManager() {
+ return userManager;
+ }
+
UserManagerContent getRootContent(ProvidedSession session) {
return new UserManagerContent(session);
}
import org.argeo.api.acr.CrName;
import org.argeo.api.acr.DName;
import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.directory.Directory;
-import org.argeo.util.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.UserDirectory;
import org.osgi.service.useradmin.Role;
class HierarchyUnitContent extends AbstractDirectoryContent {
@Override
public Content getParent() {
HierarchyUnit parentHu = hierarchyUnit.getParent();
- if (parentHu instanceof Directory) {
+ if (parentHu instanceof CmsDirectory) {
return new DirectoryContent(getSession(), provider, hierarchyUnit.getDirectory());
}
return new HierarchyUnitContent(getSession(), provider, parentHu);
import org.argeo.api.acr.Content;
import org.argeo.api.acr.ContentName;
import org.argeo.api.acr.spi.ProvidedSession;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.osgi.service.useradmin.Group;
+import org.argeo.api.cms.directory.UserDirectory;
import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
class RoleContent extends AbstractDirectoryContent {
@SuppressWarnings("unchecked")
@Override
public <A> A adapt(Class<A> clss) {
- if (clss.equals(Group.class))
- return (A) role;
- else if (clss.equals(User.class))
- return (A) role;
- else if (clss.equals(Role.class))
+ if (Role.class.isAssignableFrom(clss))
return (A) role;
return super.adapt(clss);
}
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.acr.AbstractContent;
import org.argeo.cms.acr.ContentUtils;
-import org.argeo.util.FsUtils;
+import org.argeo.cms.util.FsUtils;
/** Content persisted as a filesystem {@link Path}. */
public class FsContent extends AbstractContent implements ProvidedContent {
import java.util.TreeMap;
import java.util.stream.Collectors;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.ContentResourceException;
-import org.argeo.api.acr.CrName;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.api.acr.RuntimeNamespaceContext;
import org.argeo.api.acr.spi.ContentProvider;
}
// defaults
- addDefaultNamespace(udfav, CrName.CR_DEFAULT_PREFIX, CrName.CR_NAMESPACE_URI);
- addDefaultNamespace(udfav, "basic", CrName.CR_NAMESPACE_URI);
- addDefaultNamespace(udfav, "owner", CrName.CR_NAMESPACE_URI);
- addDefaultNamespace(udfav, "posix", CrName.CR_NAMESPACE_URI);
+ addDefaultNamespace(udfav, ArgeoNamespace.CR_DEFAULT_PREFIX, ArgeoNamespace.CR_NAMESPACE_URI);
+ addDefaultNamespace(udfav, "basic", ArgeoNamespace.CR_NAMESPACE_URI);
+ addDefaultNamespace(udfav, "owner", ArgeoNamespace.CR_NAMESPACE_URI);
+ addDefaultNamespace(udfav, "posix", ArgeoNamespace.CR_NAMESPACE_URI);
} catch (IOException e) {
throw new RuntimeException("Cannot read namespaces from " + rootPath, e);
}
+++ /dev/null
-<?xml version="1.0"?>
-<xsd:schema targetNamespace="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" elementFormDefault="qualified">
- <!--
- Changes:
-26-Aug MJD fixed typo where more than one child allowed on <instance>
-04-Sep MJD fixed typo on <send> : attribute 'submission' is required
-04-Sep MJD fixed typo on <rebuild><recalculate><revalidate><refresh>: '' attribute is required
-06-Sep MJD clarified specific allowed values of @level on <message>
-06-Sep MJD removed UI Common attributes from <help><hint><alert><label>
-09-Sep MJD changed minOccurrs and maxOccurs to use XPath expressions, default values
-09-Sep MJD fixed typo: added linking attributes to <message>
-09-Sep MJD removed <extension> from content models of <mode> and UI common elements
-09-Sep MJD fixed typo: removed 'format' attribute
-17-Sep MJD fixed typo: <output> now uses the attribute group for binding attributes, instead of similarly named individual attrs
-17-Sep MJD added XPathExpression simpleType for internal use. This doesn't actually change anything, but makes
-the Schema a better documentation resource (instead of using xsd:string for everything)
-17-Sep MJD removed 'mediatype' attribute from <submission>, as it was unused
-17-Sep MJD fixed typo: only 'ref' and 'bind' attributes, not 'model' on <submission>
-17-Sep MJD added XML Events attributes to <model>
-17-Sep MJD in accordance with 3.2.1, removed all id attributes
-19-Sep MJD fixed typo: clarified that nested <action>s are permitted.
-19-Sep MJD factor UI.Inline into <group>. Renamed <group>s and <attributeGroup>s to match the prose names
-19-Sep MJD changed to agreed-upon namespace for CR
-25-Sep MJD fixed typo: added UI.Inlne to content model of <message>, enabled mixed content
-29-Sep MJD fixed typo: 'model' required on <reset>
-29-Sep MJD fixed typo: binding attributes allowed on <submit>
-29-Sep MJD fixed typo: explicit enumerated values for 'show' on <load>
-04-Oct MJD 'resource' attribute not required
-
-12-Nov 2002 : Published as CR
-
-13-Jan MJD added new attribute includenamespaceprefixes on <submission>
-13-Jan MJD added UI Common elements to content model of <group>
-03-Feb MJD synchoninzed duration types with 15 Nov Query Operators document
-31-Mar MJD added mediatype attribute on <submission>
-14-May MJD typo : "xsd:NCName"
-26-Jun MJD removed 'accesskey' and 'navindex' (over to host language definition)
-
-01-Aug 2003 : Published as PR
-
-15-Sep MJD final namespace
-15-Sep MJD corrected content model of <value>
-15-Sep MJD changed the name of the import for XML Events to highlight that only the attributes are used
-
-1.0 Second Edition errata
-
-16-Apr 2005 RAM - erratum E4 - optional @model
-16-Apr 2005 RAM - erratum E22 - default value for @show
-16-Apr 2005 RAM - erratum E54 - remove xforms:minOccurs and xforms:maxOccurs
-26-Jun 2005 RAM - erratum E71 - allow an empty case element
-
-16-Jun 2006 JMB - erratum E69 - instance attribute in submission; id in common attributes
-
-15-Aug-2006 CFW - erratum E18 on 2nd ed. Added Action to content model for Case
-
-09-Sep 2006 JMB - non-substantive: explicitly declared some use="optional" settings,
- substantive: erratum E18 on 2nd ed. Declared default false for selected attribute of case
- substantive: erratum E21 on 2nd ed. Added multipart-post to enumeration of method attribute
-23-Nov 2006 JMB - substantive: erratum E32 on 2nd ed. switch in repeat
-17-Jul 2007 JMB - substantive: erratum E41 on 2nd ed. version attribute and associated simple types
-
-XForms 1.1
-
-25 Oct 2007 CFW, NvdB and JMB - Updated to XForms 1.1
-21 Nov 2007 JMB: Fixed description of card-number datatype
-08 Apr 2008 JMB: Fixed NCName (was NCNAME)
-30 MAY 2008 JMB: Changed card-number to allow zero or more digits
-22 JUN 2008 JMB: Renamed UI.Inline to UI.Content
-07 SEP 2008 LLK: Added element header attribute combine. header now allows one name, multiple value.
-09 MAR 2009 JMB: Changed @separator default to ampersand
-19 MAY 2009 JMB: Added submission/@targetref, dispatch/@targetid and dispatch/targetid
-10 JUN 2009 JMB: Moved switch/case from global space to being local to switch for clarity
-13 JAN 2010 JMB: Put maxOccurs=1 on instance content to limit to one child element in an instance
-16 SEP 2010 JBM: Added xforms:duration datatype (1.1 Erratum #1), added UICommon before ListUICommon on select/select1 (1.1 Erratum #2)
--->
- <xsd:import namespace="http://www.w3.org/2001/xml-events" schemaLocation="xml-events-attribs-1.xsd"/>
- <xsd:import namespace="http://www.w3.org/2001/XMLSchema" schemaLocation="XMLSchema.xsd"/>
-
- <!--
-structural elements
--->
- <xsd:attributeGroup name="Common.Attributes">
- <xsd:annotation>
- <xsd:documentation>Attributes for _every_ element in XForms</xsd:documentation>
- </xsd:annotation>
- <xsd:attribute name="id" type="xsd:ID" use="optional"/>
- <xsd:anyAttribute namespace="##other"/>
- </xsd:attributeGroup>
-
- <xsd:attributeGroup name="Single.Node.Binding.Attributes">
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attribute name="ref" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
- </xsd:attributeGroup>
-
- <xsd:attributeGroup name="Nodeset.Binding.Attributes">
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attribute name="nodeset" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
- </xsd:attributeGroup>
-
- <xsd:attributeGroup name="Linking.Attributes">
- <xsd:attribute name="src" type="xsd:anyURI"/>
- </xsd:attributeGroup>
-
- <xsd:element name="model">
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:choice>
- <xsd:element ref="xforms:instance"/>
- <xsd:element ref="xsd:schema"/>
- <xsd:element ref="xforms:submission"/>
- <xsd:element ref="xforms:bind"/>
- <xsd:group ref="xforms:Action"/>
- </xsd:choice>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attribute name="functions" type="xforms:QNameList" use="optional"/>
- <xsd:attribute name="schema" type="xforms:anyURIList" use="optional"/>
- <xsd:attribute name="version" type="xforms:versionList" use="optional"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="instance">
- <xsd:annotation>
- <xsd:documentation>instance container.</xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Linking.Attributes"/>
- <xsd:attribute name="resource" type="xsd:anyURI" use="optional"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="bind">
- <xsd:annotation>
- <xsd:documentation>Definition of bind container.</xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:element ref="xforms:bind"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="nodeset" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="calculate" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="type" type="xsd:QName" use="optional"/>
- <xsd:attribute name="required" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="constraint" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="relevant" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="readonly" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="p3ptype" type="xsd:string" use="optional"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="extension">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:any namespace="##other"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- </xsd:complexType>
- </xsd:element>
-
- <!--
-User Interface form controls
--->
- <xsd:group name="Core.Form.Controls">
- <xsd:choice>
- <xsd:element ref="xforms:input"/>
- <xsd:element ref="xforms:secret"/>
- <xsd:element ref="xforms:textarea"/>
- <xsd:element ref="xforms:output"/>
- <xsd:element ref="xforms:upload"/>
- <xsd:element ref="xforms:select1"/>
- <xsd:element ref="xforms:select"/>
- <xsd:element ref="xforms:range"/>
- <xsd:element ref="xforms:submit"/>
- <xsd:element ref="xforms:trigger"/>
- </xsd:choice>
- </xsd:group>
-
- <xsd:group name="Container.Form.Controls">
- <xsd:choice>
- <xsd:element ref="xforms:group"/>
- <xsd:element ref="xforms:switch"/>
- <xsd:element ref="xforms:repeat"/>
- </xsd:choice>
- </xsd:group>
-
- <xsd:attributeGroup name="UI.Common.Attrs">
- <xsd:attribute name="appearance" type="xforms:appearanceType" use="optional"/>
- </xsd:attributeGroup>
-
- <xsd:group name="UI.Content">
- <xsd:sequence>
- <xsd:choice minOccurs="0">
- <xsd:element ref="xforms:output"/>
- <!-- containing document language to add additional allowed content here -->
- </xsd:choice>
- </xsd:sequence>
- </xsd:group>
-
- <xsd:group name="UI.Common">
- <xsd:sequence>
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element ref="xforms:help"/>
- <xsd:element ref="xforms:hint"/>
- <xsd:element ref="xforms:alert"/>
- <xsd:group ref="xforms:Action"/>
- </xsd:choice>
- </xsd:sequence>
- </xsd:group>
-
- <xsd:element name="label">
- <xsd:complexType mixed="true">
- <xsd:group ref="xforms:UI.Content"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="hint">
- <xsd:complexType mixed="true">
- <xsd:group ref="xforms:UI.Content"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="help">
- <xsd:complexType mixed="true">
- <xsd:group ref="xforms:UI.Content"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="alert">
- <xsd:complexType mixed="true">
- <xsd:group ref="xforms:UI.Content"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:group name="List.UI.Common">
- <xsd:sequence>
- <xsd:choice>
- <xsd:element ref="xforms:item"/>
- <xsd:element ref="xforms:itemset"/>
- <xsd:element ref="xforms:choices"/>
- </xsd:choice>
- </xsd:sequence>
- </xsd:group>
- <xsd:element name="item">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:element ref="xforms:value"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="itemset">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:choice>
- <xsd:element ref="xforms:value"/>
- <xsd:element ref="xforms:copy"/>
- </xsd:choice>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="choices">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label" minOccurs="0"/>
- <xsd:sequence maxOccurs="unbounded">
- <xsd:choice>
- <xsd:element ref="xforms:choices"/>
- <xsd:element ref="xforms:item"/>
- <xsd:element ref="xforms:itemset"/>
- </xsd:choice>
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="value">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="copy">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
-<!--
- <xsd:element name="filename">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="mediatype">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- </xsd:element>
--->
- <xsd:complexType name="filename">
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- <xsd:complexType name="mediatype">
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- </xsd:complexType>
- <xsd:complexType name="mediatypeWithValue">
- <xsd:complexContent>
- <xsd:extension base="xforms:mediatype">
- <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:element name="input">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="secret">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="textarea">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="inputmode" type="xsd:string" use="optional"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="upload">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <!--
- <xsd:element ref="xforms:filename" minOccurs="0"/>
- <xsd:element ref="xforms:mediatype" minOccurs="0"/>
- -->
- <xsd:element name="filename" type="xforms:filename" minOccurs="0"/>
- <xsd:element name="mediatype" type="xforms:mediatype" minOccurs="0"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="mediatype" type="xsd:string" use="optional"/>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="select1">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:group ref="xforms:List.UI.Common" maxOccurs="unbounded"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="selection" use="optional" default="closed">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="open"/>
- <xsd:enumeration value="closed"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="true"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="select">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:group ref="xforms:List.UI.Common" maxOccurs="unbounded"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="selection" use="optional" default="closed">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="open"/>
- <xsd:enumeration value="closed"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="true"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="range">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="start" type="xsd:string" use="optional"/>
- <xsd:attribute name="end" type="xsd:string" use="optional"/>
- <xsd:attribute name="step" type="xsd:string" use="optional"/>
- <xsd:attribute name="incremental" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="trigger">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="output">
- <xsd:complexType>
- <xsd:sequence minOccurs="0">
- <xsd:element ref="xforms:label"/>
- <!--
- <xsd:element ref="xforms:mediatype" minOccurs="0"/>
- -->
- <xsd:element name="mediatype" type="xforms:mediatypeWithValue" minOccurs="0"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="appearance" type="xforms:appearanceType" use="optional"/>
- <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="mediatype" type="xsd:string" use="optional"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="submit">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label"/>
- <xsd:group ref="xforms:UI.Common" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="submission" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- </xsd:complexType>
- </xsd:element>
-
- <!--
-Advanced User Interface
--->
- <xsd:attribute name="repeat-nodeset" type="xforms:XPathExpression"/>
- <xsd:attribute name="repeat-model" type="xsd:IDREF"/>
- <xsd:attribute name="repeat-bind" type="xsd:IDREF"/>
- <xsd:attribute name="repeat-startindex" type="xsd:positiveInteger"/>
- <xsd:attribute name="repeat-number" type="xsd:nonNegativeInteger"/>
-
- <xsd:element name="repeat">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:choice>
- <xsd:group ref="xforms:Core.Form.Controls"/>
- <xsd:group ref="xforms:Container.Form.Controls"/>
- <xsd:group ref="xforms:Action"/>
- <!-- containing document language to add additional allowed content here -->
- </xsd:choice>
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- <xsd:attribute name="startindex" type="xsd:positiveInteger"/>
- <xsd:attribute name="number" type="xsd:nonNegativeInteger"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="group">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label" minOccurs="0"/>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:choice>
- <xsd:group ref="xforms:Core.Form.Controls"/>
- <xsd:group ref="xforms:Container.Form.Controls"/>
- <xsd:group ref="xforms:UI.Common"/>
- <!-- containing document language to add additional allowed content here -->
- </xsd:choice>
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="switch">
- <xsd:complexType>
- <xsd:sequence maxOccurs="unbounded">
- <xsd:element name="case">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element ref="xforms:label" minOccurs="0"/>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:choice>
- <xsd:group ref="xforms:Core.Form.Controls"/>
- <xsd:group ref="xforms:Container.Form.Controls"/>
- <xsd:group ref="xforms:Action"/>
- <!-- containing document language to add additional allowed content here -->
- </xsd:choice>
- </xsd:sequence>
- </xsd:sequence>
- <xsd:attribute name="selected" type="xsd:boolean" use="optional" default="false"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attributeGroup ref="xforms:UI.Common.Attrs"/>
- </xsd:complexType>
- </xsd:element>
-
- <!--
-XForms Actions
--->
-
- <xsd:attributeGroup name="XML.Events">
- <xsd:attribute ref="ev:event"/>
- <xsd:attribute ref="ev:observer"/>
- <xsd:attribute ref="ev:target"/>
- <xsd:attribute ref="ev:handler"/>
- <xsd:attribute ref="ev:phase"/>
- <xsd:attribute ref="ev:propagate"/>
- <xsd:attribute ref="ev:defaultAction"/>
- </xsd:attributeGroup>
-
- <xsd:attributeGroup name="Common.Action.Attributes">
- <xsd:annotation>
- <xsd:documentation>Attributes for _every_ action in XForms</xsd:documentation>
- </xsd:annotation>
- <xsd:attribute name="if" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="while" type="xforms:XPathExpression" use="optional"/>
- </xsd:attributeGroup>
-
- <xsd:group name="Action">
- <xsd:sequence>
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element ref="xforms:action"/>
- <xsd:element ref="xforms:setvalue"/>
- <xsd:element ref="xforms:insert"/>
- <xsd:element ref="xforms:delete"/>
- <xsd:element ref="xforms:setindex"/>
- <xsd:element ref="xforms:toggle"/>
- <xsd:element ref="xforms:setfocus"/>
- <xsd:element ref="xforms:dispatch"/>
- <xsd:element ref="xforms:rebuild"/>
- <xsd:element ref="xforms:recalculate"/>
- <xsd:element ref="xforms:revalidate"/>
- <xsd:element ref="xforms:refresh"/>
- <xsd:element ref="xforms:reset"/>
- <xsd:element ref="xforms:load"/>
- <xsd:element ref="xforms:send"/>
- <xsd:element ref="xforms:message"/>
- </xsd:choice>
- </xsd:sequence>
- </xsd:group>
-
- <xsd:element name="action">
- <xsd:complexType>
- <xsd:sequence maxOccurs="unbounded">
- <xsd:group ref="xforms:Action"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="setvalue">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="insert">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
- <xsd:attribute name="at" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="context" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="origin" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="position" use="optional">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="before"/>
- <xsd:enumeration value="after"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="delete">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Nodeset.Binding.Attributes"/>
- <xsd:attribute name="at" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="context" type="xforms:XPathExpression" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="setindex">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="repeat" type="xsd:IDREF" use="required"/>
- <xsd:attribute name="index" type="xforms:XPathExpression" use="required"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="toggle">
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="1">
- <xsd:element name="case" type="xforms:ValueTemplate"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="case" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="setfocus">
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="1">
- <xsd:element name="control" type="xforms:ValueTemplate"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="control" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="dispatch">
- <xsd:complexType>
- <!-- Need to be able to say only zero or one of each child, but order independent.
- This gets as close as possible with schema. -->
- <xsd:sequence minOccurs="0" maxOccurs="3">
- <xsd:choice>
- <xsd:element name="name" type="xforms:ValueTemplate"/>
- <xsd:element name="targetid" type="xforms:ValueTemplate"/>
- <xsd:element name="target" type="xforms:ValueTemplate"/>
- <xsd:element name="delay" type="xforms:ValueTemplate"/>
- </xsd:choice>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="name" type="xsd:NMTOKEN" use="optional"/>
- <xsd:attribute name="targetid" type="xsd:IDREF" use="optional"/>
- <xsd:attribute name="target" type="xsd:IDREF" use="optional"/>
- <xsd:attribute name="delay" type="xsd:string" use="optional" default=""/>
- <xsd:attribute name="bubbles" type="xsd:boolean" use="optional" default="true"/>
- <xsd:attribute name="cancelable" type="xsd:boolean" use="optional" default="true"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="rebuild">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="recalculate">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="revalidate">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="refresh">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="reset">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- <xsd:attribute name="model" type="xsd:IDREF" use="optional"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="load">
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="1">
- <xsd:element name="resource" type="xforms:ValueTemplate"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="resource" type="xsd:anyURI" use="optional"/>
- <xsd:attribute name="show" use="optional" default="replace">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="new"/>
- <xsd:enumeration value="replace"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="send">
- <xsd:complexType>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attribute name="submission" type="xsd:IDREF" use="optional"/>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="message">
- <xsd:complexType mixed="true">
- <xsd:group ref="xforms:UI.Content"/>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
- <xsd:attributeGroup ref="xforms:Single.Node.Binding.Attributes"/>
- <xsd:attribute name="level" use="optional" default="modal">
- <xsd:simpleType>
- <xsd:union memberTypes="xforms:QNameButNotNCNAME">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="ephemeral"/>
- <xsd:enumeration value="modeless"/>
- <xsd:enumeration value="modal"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
- </xsd:attribute>
- <xsd:attributeGroup ref="xforms:XML.Events"/>
- <xsd:attributeGroup ref="xforms:Common.Action.Attributes"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:element name="submission">
- <xsd:annotation>
- <xsd:documentation>submit info container.</xsd:documentation>
- </xsd:annotation>
- <xsd:complexType>
- <xsd:sequence>
- <!-- There should only be zero or one resource, zero or one method, and zero or more header
- We can't say exactly this, but we get as close as possible -->
- <xsd:choice minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="resource" type="xforms:ValueTemplate"/>
- <xsd:element name="method" type="xforms:ValueTemplate"/>
- <xsd:element name="header">
- <xsd:complexType>
- <!-- Both name and value+ are required, but order independent -->
- <xsd:choice>
- <xsd:sequence>
- <xsd:element name="name" type="xforms:ValueTemplate" />
- <xsd:element name="value" type="xforms:ValueTemplate"
- minOccurs="1" maxOccurs="unbounded" />
- </xsd:sequence>
- <xsd:sequence>
- <xsd:element name="value" type="xforms:ValueTemplate"
- minOccurs="1" maxOccurs="unbounded" />
- <xsd:element name="name" type="xforms:ValueTemplate" />
- </xsd:sequence>
- </xsd:choice>
- <xsd:attribute name="combine" use="optional" default="append">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="append"/>
- <xsd:enumeration value="prepend"/>
- <xsd:enumeration value="replace"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
- </xsd:choice>
- <!-- As is the case everywhere else, action handlers are last -->
- <xsd:group ref="xforms:Action"/>
- </xsd:sequence>
- <xsd:attributeGroup ref="xforms:Common.Attributes"/>
-
- <xsd:attribute name="ref" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="bind" type="xsd:IDREF" use="optional"/>
-
- <!-- Either the resource attribute, action attribute, or resource child element is required -->
- <xsd:attribute name="resource" type="xsd:anyURI" use="optional"/>
- <xsd:attribute name="action" type="xsd:anyURI" use="optional"/>
-
- <xsd:attribute name="mode" use="optional" default="asynchronous">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="asynchronous"/>
- <xsd:enumeration value="synchronous"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
-
- <!-- Either the method attribute or the method child element is required -->
- <xsd:attribute name="method" use="optional">
- <xsd:simpleType>
- <xsd:union memberTypes="xforms:QNameButNotNCNAME xsd:NCName">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="post"/>
- <xsd:enumeration value="put"/>
- <xsd:enumeration value="get"/>
- <xsd:enumeration value="delete"/>
- <xsd:enumeration value="multipart-post"/>
- <xsd:enumeration value="form-data-post"/>
- <xsd:enumeration value="urlencoded-post"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
- </xsd:attribute>
-
- <!-- The defaults for these are false if serialization is 'none' and true otherwise -->
- <xsd:attribute name="validate" type="xsd:boolean" use="optional"/>
- <xsd:attribute name="relevant" type="xsd:boolean" use="optional"/>
-
- <!-- The default is based on the selected method, e.g. application/xml for the post method -->
- <xsd:attribute name="serialization" type="xsd:string" use="optional"/>
-
- <xsd:attribute name="version" type="xsd:NMTOKEN" use="optional" default="1.0"/>
- <xsd:attribute name="indent" type="xsd:boolean" use="optional" default="false"/>
- <xsd:attribute name="mediatype" type="xsd:string" use="optional" default="application/xml"/>
- <xsd:attribute name="encoding" type="xsd:string" use="optional" default="UTF-8"/>
-
- <xsd:attribute name="omit-xml-declaration" type="xsd:boolean" use="optional" default="false"/>
- <!-- This is optional with no default because omitting the attribute behaves differently
- than including it with any value -->
- <xsd:attribute name="standalone" type="xsd:boolean" use="optional"/>
-
- <xsd:attribute name="cdata-section-elements" type="xforms:QNameList" use="optional" default=""/>
-
- <xsd:attribute name="replace" use="optional" default="all">
- <xsd:simpleType>
- <xsd:union memberTypes="xforms:QNameButNotNCNAME">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="all"/>
- <xsd:enumeration value="instance"/>
- <xsd:enumeration value="text"/>
- <xsd:enumeration value="none"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
- </xsd:attribute>
-
- <!-- Default is not specified because the default is to replace the instance being submitted -->
- <xsd:attribute name="instance" type="xsd:IDREF" use="optional"/>
-
- <xsd:attribute name="separator" use="optional" default="&">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="&"/>
- <xsd:enumeration value=";"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:attribute>
-
- <!-- Default is not specified because the defalut is to replace the whole instance indicated
- by the instance attribute -->
- <xsd:attribute name="targetref" type="xforms:XPathExpression" use="optional"/>
- <xsd:attribute name="target" type="xforms:XPathExpression" use="optional"/>
-
- <!-- Default not specified because omitting the attribute behaves differently than
- including it with any value -->
- <xsd:attribute name="includenamespaceprefixes" use="optional">
- <xsd:simpleType>
- <xsd:list>
- <xsd:simpleType>
- <xsd:union memberTypes="xsd:NCName">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="#default"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
- </xsd:list>
- </xsd:simpleType>
- </xsd:attribute>
- </xsd:complexType>
- </xsd:element>
-
- <!--
-Internal helper types
--->
-
- <xsd:simpleType name="versionList">
- <xsd:list itemType="xforms:versionNumber"/>
- </xsd:simpleType>
- <xsd:simpleType name="versionNumber">
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="[1-9]\d*\.\d+"/>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:simpleType name="XPathExpression">
- <xsd:restriction base="xsd:string"/>
- </xsd:simpleType>
- <xsd:simpleType name="QNameList">
- <xsd:list itemType="xsd:QName"/>
- </xsd:simpleType>
- <xsd:simpleType name="anyURIList">
- <xsd:list itemType="xsd:anyURI"/>
- </xsd:simpleType>
- <xsd:simpleType name="QNameButNotNCNAME">
- <xsd:restriction base="xsd:QName">
- <xsd:pattern value="[^:]+:[^:]+"/>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:simpleType name="appearanceType">
- <xsd:union memberTypes="xforms:QNameButNotNCNAME">
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="full"/>
- <xsd:enumeration value="compact"/>
- <xsd:enumeration value="minimal"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:complexType name="ValueTemplate">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="value" type="xforms:XPathExpression" use="optional"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
-
- <!--
-New simpleTypes provided to form authors
--->
-
- <xsd:simpleType name="listItem">
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="\S+"/>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:simpleType name="listItems">
- <xsd:list itemType="xforms:listItem"/>
- </xsd:simpleType>
-
- <xsd:simpleType name="dateTime">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:dateTime"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="time">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:time"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="date">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:date"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="duration">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:duration"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="gYearMonth">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:gYearMonth"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="gYear">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:gYear"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="gMonthDay">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:gMonthDay"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="gDay">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:gDay"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="gMonth">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:gMonth"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="string">
- <xsd:restriction base="xsd:string"/>
- </xsd:simpleType>
-
- <xsd:simpleType name="boolean">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:boolean"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="base64Binary">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:base64Binary"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="hexBinary">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:hexBinary"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="float">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:float"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="decimal">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:decimal"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="double">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:double"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="anyURI">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:anyURI"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="QName">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:QName"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="normalizedString">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:normalizedString"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="token">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:token"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="language">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:language"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="Name">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:Name"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="NCName">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:NCName"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="ID">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:ID"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="IDREF">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:IDREF"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="IDREFS">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:IDREFS"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="NMTOKEN">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:NMTOKEN"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="NMTOKENS">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:NMTOKENS"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="integer">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:integer"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="negativeInteger">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:negativeInteger"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="long">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:long"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="int">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:int"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="short">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:short"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="byte">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:byte"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="nonNegativeInteger">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:nonNegativeInteger"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="unsignedLong">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:unsignedLong"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="unsignedInt">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:unsignedInt"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="unsignedShort">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:unsignedShort"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="unsignedByte">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:unsignedByte"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="positiveInteger">
- <xsd:union>
- <xsd:simpleType>
- <xsd:restriction base="xsd:positiveInteger"/>
- </xsd:simpleType>
- <xsd:simpleType>
- <xsd:restriction base="xsd:string">
- <xsd:length value="0"/>
- </xsd:restriction>
- </xsd:simpleType>
- </xsd:union>
- </xsd:simpleType>
-
- <xsd:simpleType name="dayTimeDuration">
- <xsd:restriction base="xsd:duration">
- <xsd:pattern value="([\-]?P([0-9]+D(T([0-9]+(H([0-9]+(M([0-9]+(\.[0-9]*)?S
- |\.[0-9]+S)?|(\.[0-9]*)?S)|(\.[0-9]*)?S)?|M([0-9]+
- (\.[0-9]*)?S|\.[0-9]+S)?|(\.[0-9]*)?S)|\.[0-9]+S))?
- |T([0-9]+(H([0-9]+(M([0-9]+(\.[0-9]*)?S|\.[0-9]+S)?
- |(\.[0-9]*)?S)|(\.[0-9]*)?S)?|M([0-9]+(\.[0-9]*)?S|\.[0-9]+S)?
- |(\.[0-9]*)?S)|\.[0-9]+S)))?"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:simpleType name="yearMonthDuration">
- <xsd:restriction base="xsd:duration">
- <xsd:pattern value="([\-]?P[0-9]+(Y([0-9]+M)?|M))?"/>
- </xsd:restriction>
- </xsd:simpleType>
- <xsd:simpleType name="email">
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="([A-Za-z0-9!#-'\*\+\-/=\?\^_`\{-~]+(\.[A-Za-z0-9!#-'\*\+\-/=\?\^_`\{-~]+)*@[A-Za-z0-9!#-'\*\+\-/=\?\^_`\{-~]+(\.[A-Za-z0-9!#-'\*\+\-/=\?\^_`\{-~]+)*)?"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:simpleType name="card-number">
- <xsd:annotation>
- <xsd:documentation>
- This type defines the basic lexical properties for a dataypte that can be used to represent
- various ID numbers such as for debit and credit cards.
- This type does not apply the Luhn checksum algorithm.
- </xsd:documentation>
- </xsd:annotation>
- <xsd:restriction base="xsd:string">
- <xsd:pattern value="[0-9]*"/>
- </xsd:restriction>
- </xsd:simpleType>
-
-
-</xsd:schema>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:docbook="http://docbook.org/ns/docbook">
- <xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd"/>
- <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
- <xs:attributeGroup name="db.common.attributes">
- <xs:attribute ref="xml:id"/>
- <xs:attribute name="version"/>
- <xs:attribute ref="xml:lang"/>
- <xs:attribute ref="xml:base"/>
- <xs:attribute name="remap"/>
- <xs:attribute name="xreflabel"/>
- <xs:attribute name="revisionflag">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="changed"/>
- <xs:enumeration value="added"/>
- <xs:enumeration value="deleted"/>
- <xs:enumeration value="off"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="dir">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ltr"/>
- <xs:enumeration value="rtl"/>
- <xs:enumeration value="lro"/>
- <xs:enumeration value="rlo"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="arch"/>
- <xs:attribute name="audience"/>
- <xs:attribute name="condition"/>
- <xs:attribute name="conformance"/>
- <xs:attribute name="os"/>
- <xs:attribute name="revision"/>
- <xs:attribute name="security"/>
- <xs:attribute name="userlevel"/>
- <xs:attribute name="vendor"/>
- <xs:attribute name="wordsize"/>
- <xs:attribute name="annotations"/>
- </xs:attributeGroup>
- <xs:attributeGroup name="db.common.linking.attributes">
- <xs:attribute name="linkend" type="xs:IDREF"/>
- <xs:attribute ref="xlink:href"/>
- <xs:attribute ref="xlink:type"/>
- <xs:attribute ref="xlink:role"/>
- <xs:attribute ref="xlink:arcrole"/>
- <xs:attribute ref="xlink:title"/>
- <xs:attribute ref="xlink:show"/>
- <xs:attribute ref="xlink:actuate"/>
- </xs:attributeGroup>
- <xs:element name="title">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="titleabbrev">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="subtitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="info">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:abstract"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:artpagenums"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:authorgroup"/>
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:bibliocoverage"/>
- <xs:element ref="docbook:biblioid"/>
- <xs:element ref="docbook:bibliosource"/>
- <xs:element ref="docbook:collab"/>
- <xs:element ref="docbook:confgroup"/>
- <xs:element ref="docbook:contractsponsor"/>
- <xs:element ref="docbook:contractnum"/>
- <xs:element ref="docbook:copyright"/>
- <xs:element ref="docbook:cover"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:edition"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:issuenum"/>
- <xs:element ref="docbook:keywordset"/>
- <xs:element ref="docbook:legalnotice"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:othercredit"/>
- <xs:element ref="docbook:pagenums"/>
- <xs:element ref="docbook:printhistory"/>
- <xs:element ref="docbook:pubdate"/>
- <xs:element ref="docbook:publisher"/>
- <xs:element ref="docbook:publishername"/>
- <xs:element ref="docbook:releaseinfo"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:seriesvolnums"/>
- <xs:element ref="docbook:subjectset"/>
- <xs:element ref="docbook:volumenum"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:extendedlink"/>
- <xs:element ref="docbook:bibliomisc"/>
- <xs:element ref="docbook:bibliomset"/>
- <xs:element ref="docbook:bibliorelation"/>
- <xs:element ref="docbook:biblioset"/>
- <xs:element ref="docbook:itermset"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:productnumber"/>
- </xs:choice>
- <xs:sequence>
- <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
- </xs:sequence>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="subjectset">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:subject"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="scheme" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="subject">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:subjectterm"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="weight"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="subjectterm">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keywordset">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:keyword"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keyword">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="procedure">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:step"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="step">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:sequence minOccurs="0">
- <xs:choice>
- <xs:element ref="docbook:substeps"/>
- <xs:element ref="docbook:stepalternatives"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- </xs:sequence>
- <xs:sequence>
- <xs:choice>
- <xs:element ref="docbook:substeps"/>
- <xs:element ref="docbook:stepalternatives"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="performance">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="optional"/>
- <xs:enumeration value="required"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="stepalternatives">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element maxOccurs="unbounded" ref="docbook:step"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="performance">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="optional"/>
- <xs:enumeration value="required"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="substeps">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:step"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="performance">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="optional"/>
- <xs:enumeration value="required"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="sidebar">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="abstract">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="personblurb">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="blockquote">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:attribution"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="attribution">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bridgehead">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="renderas">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="sect1"/>
- <xs:enumeration value="sect2"/>
- <xs:enumeration value="sect3"/>
- <xs:enumeration value="sect4"/>
- <xs:enumeration value="sect5"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherrenderas" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="remark">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="epigraph">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element minOccurs="0" ref="docbook:attribution"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:literallayout"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="footnote">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="formalpara">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- <xs:element ref="docbook:para"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="para">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="simpara">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="itemizedlist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:listitem"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="spacing">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="compact"/>
- <xs:enumeration value="normal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="mark" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="orderedlist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:listitem"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="spacing">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="compact"/>
- <xs:enumeration value="normal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startingnumber" type="xs:NMTOKEN"/>
- <xs:attribute name="inheritnum">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="ignore"/>
- <xs:enumeration value="inherit"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="numeration">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="arabic"/>
- <xs:enumeration value="upperalpha"/>
- <xs:enumeration value="loweralpha"/>
- <xs:enumeration value="upperroman"/>
- <xs:enumeration value="lowerroman"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="listitem">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="override" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="segmentedlist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:segtitle"/>
- <xs:element maxOccurs="unbounded" ref="docbook:seglistitem"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="segtitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seglistitem">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:seg"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seg">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="simplelist">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:member"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="type" default="vert">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="horiz"/>
- <xs:enumeration value="vert"/>
- <xs:enumeration value="inline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="columns" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="member">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="variablelist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:varlistentry"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="spacing">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="compact"/>
- <xs:enumeration value="normal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="termlength"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="varlistentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:term"/>
- <xs:element ref="docbook:listitem"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="term">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="example">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="floatstyle"/>
- <xs:attribute name="width" type="xs:NMTOKEN"/>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="informalexample">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="floatstyle"/>
- <xs:attribute name="width" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="literallayout">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="monospaced"/>
- <xs:enumeration value="normal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="screen">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- <xs:attribute name="width" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="screenshot">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:mediaobject"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="figure">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="floatstyle"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="informalfigure">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="floatstyle"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="mediaobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:videoobject"/>
- <xs:element ref="docbook:audioobject"/>
- <xs:element ref="docbook:imageobject"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:imageobjectco"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="inlinemediaobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:videoobject"/>
- <xs:element ref="docbook:audioobject"/>
- <xs:element ref="docbook:imageobject"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:imageobjectco"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="videoobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:videodata"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="audioobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:audiodata"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="imageobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:imagedata"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="textobject">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:textdata"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="videodata">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="format"/>
- <xs:attribute name="fileref"/>
- <xs:attribute name="entityref" type="xs:ENTITY"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="width"/>
- <xs:attribute name="contentwidth"/>
- <xs:attribute name="scalefit">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="scale" type="xs:NMTOKEN"/>
- <xs:attribute name="depth"/>
- <xs:attribute name="contentdepth"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="audiodata">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="format"/>
- <xs:attribute name="fileref"/>
- <xs:attribute name="entityref" type="xs:ENTITY"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="imagedata">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="format"/>
- <xs:attribute name="fileref"/>
- <xs:attribute name="entityref" type="xs:ENTITY"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="width"/>
- <xs:attribute name="contentwidth"/>
- <xs:attribute name="scalefit">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="scale" type="xs:NMTOKEN"/>
- <xs:attribute name="depth"/>
- <xs:attribute name="contentdepth"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="textdata">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="format"/>
- <xs:attribute name="fileref"/>
- <xs:attribute name="entityref" type="xs:ENTITY"/>
- <xs:attribute name="encoding"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="caption">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="address">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:pob"/>
- <xs:element ref="docbook:street"/>
- <xs:element ref="docbook:city"/>
- <xs:element ref="docbook:state"/>
- <xs:element ref="docbook:postcode"/>
- <xs:element ref="docbook:country"/>
- <xs:element ref="docbook:phone"/>
- <xs:element ref="docbook:fax"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:otheraddr"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="street">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="pob">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="postcode">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="city">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="state">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="country">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="phone">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="fax">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="otheraddr">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="affiliation">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:shortaffil"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:jobtitle"/>
- <xs:choice>
- <xs:element minOccurs="0" ref="docbook:org"/>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:orgname"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:orgdiv"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:address"/>
- </xs:sequence>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="shortaffil">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="jobtitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="orgname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="consortium"/>
- <xs:enumeration value="corporation"/>
- <xs:enumeration value="informal"/>
- <xs:enumeration value="nonprofit"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="orgdiv">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="artpagenums">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="personname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:honorific"/>
- <xs:element ref="docbook:firstname"/>
- <xs:element ref="docbook:surname"/>
- <xs:element ref="docbook:lineage"/>
- <xs:element ref="docbook:othername"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="author">
- <xs:complexType>
- <xs:choice>
- <xs:sequence>
- <xs:element ref="docbook:personname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element ref="docbook:orgname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:orgdiv"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="authorgroup">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:othercredit"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="collab">
- <xs:complexType>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:affiliation"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="authorinitials">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="person">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:personname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:personblurb"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="org">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:orgname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:orgdiv"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="confgroup">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:confdates"/>
- <xs:element ref="docbook:conftitle"/>
- <xs:element ref="docbook:confnum"/>
- <xs:element ref="docbook:confsponsor"/>
- <xs:element ref="docbook:address"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="confdates">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="conftitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="confnum">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="confsponsor">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="contractnum">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="contractsponsor">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="copyright">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:year"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:holder"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="year">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="holder">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="cover">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="date">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="edition">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="editor">
- <xs:complexType>
- <xs:choice>
- <xs:sequence>
- <xs:element ref="docbook:personname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element ref="docbook:orgname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:orgdiv"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="biblioid">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="doi"/>
- <xs:enumeration value="isbn"/>
- <xs:enumeration value="isrn"/>
- <xs:enumeration value="issn"/>
- <xs:enumeration value="libraryofcongress"/>
- <xs:enumeration value="pubsnumber"/>
- <xs:enumeration value="uri"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="citebiblioid">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="doi"/>
- <xs:enumeration value="isbn"/>
- <xs:enumeration value="isrn"/>
- <xs:enumeration value="issn"/>
- <xs:enumeration value="libraryofcongress"/>
- <xs:enumeration value="pubsnumber"/>
- <xs:enumeration value="uri"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliosource">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="doi"/>
- <xs:enumeration value="isbn"/>
- <xs:enumeration value="isrn"/>
- <xs:enumeration value="issn"/>
- <xs:enumeration value="libraryofcongress"/>
- <xs:enumeration value="pubsnumber"/>
- <xs:enumeration value="uri"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliorelation">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="doi"/>
- <xs:enumeration value="isbn"/>
- <xs:enumeration value="isrn"/>
- <xs:enumeration value="issn"/>
- <xs:enumeration value="libraryofcongress"/>
- <xs:enumeration value="pubsnumber"/>
- <xs:enumeration value="uri"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass" type="xs:NMTOKEN"/>
- <xs:attribute name="type">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="hasformat"/>
- <xs:enumeration value="haspart"/>
- <xs:enumeration value="hasversion"/>
- <xs:enumeration value="isformatof"/>
- <xs:enumeration value="ispartof"/>
- <xs:enumeration value="isreferencedby"/>
- <xs:enumeration value="isreplacedby"/>
- <xs:enumeration value="isrequiredby"/>
- <xs:enumeration value="isversionof"/>
- <xs:enumeration value="references"/>
- <xs:enumeration value="replaces"/>
- <xs:enumeration value="requires"/>
- <xs:enumeration value="othertype"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="othertype" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliocoverage">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="spatial">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="dcmipoint"/>
- <xs:enumeration value="iso3166"/>
- <xs:enumeration value="dcmibox"/>
- <xs:enumeration value="tgn"/>
- <xs:enumeration value="otherspatial"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherspatial" type="xs:NMTOKEN"/>
- <xs:attribute name="temporal">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="dcmiperiod"/>
- <xs:enumeration value="w3c-dtf"/>
- <xs:enumeration value="othertemporal"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="othertemporal" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="legalnotice">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="othercredit">
- <xs:complexType>
- <xs:choice>
- <xs:sequence>
- <xs:element ref="docbook:personname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element ref="docbook:orgname"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:orgdiv"/>
- <xs:element ref="docbook:affiliation"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:contrib"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="copyeditor"/>
- <xs:enumeration value="graphicdesigner"/>
- <xs:enumeration value="other"/>
- <xs:enumeration value="productioneditor"/>
- <xs:enumeration value="technicaleditor"/>
- <xs:enumeration value="translator"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="pagenums">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="contrib">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="honorific">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="firstname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="surname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="lineage">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="othername">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="printhistory">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="pubdate">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="publisher">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:publishername"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:address"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="publishername">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="releaseinfo">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="revhistory">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:revision"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="revision">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:revnumber"/>
- <xs:element ref="docbook:date"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:author"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:element ref="docbook:revremark"/>
- <xs:element ref="docbook:revdescription"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="revnumber">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="revremark">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="revdescription">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seriesvolnums">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="volumenum">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="issuenum">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="package">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="email">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="lineannotation">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="parameter">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="command"/>
- <xs:enumeration value="function"/>
- <xs:enumeration value="option"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="replaceable">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="command"/>
- <xs:enumeration value="function"/>
- <xs:enumeration value="option"/>
- <xs:enumeration value="parameter"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="uri">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="type"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="abbrev">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:trademark"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="acronym">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:trademark"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="citation">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="citerefentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:refentrytitle"/>
- <xs:element minOccurs="0" ref="docbook:manvolnum"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refentrytitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="manvolnum">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="citetitle">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="pubwork">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="article"/>
- <xs:enumeration value="bbs"/>
- <xs:enumeration value="book"/>
- <xs:enumeration value="cdrom"/>
- <xs:enumeration value="chapter"/>
- <xs:enumeration value="dvd"/>
- <xs:enumeration value="emailmessage"/>
- <xs:enumeration value="gopher"/>
- <xs:enumeration value="journal"/>
- <xs:enumeration value="manuscript"/>
- <xs:enumeration value="newsposting"/>
- <xs:enumeration value="part"/>
- <xs:enumeration value="refentry"/>
- <xs:enumeration value="section"/>
- <xs:enumeration value="series"/>
- <xs:enumeration value="set"/>
- <xs:enumeration value="webpage"/>
- <xs:enumeration value="wiki"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="emphasis">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="foreignphrase">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="phrase">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="quote">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="subscript">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="superscript">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="trademark">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="copyright"/>
- <xs:enumeration value="registered"/>
- <xs:enumeration value="service"/>
- <xs:enumeration value="trade"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="wordasword">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="footnoteref">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="xref">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="xrefstyle"/>
- <xs:attribute name="endterm" type="xs:IDREF"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="link">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="xrefstyle"/>
- <xs:attribute name="endterm" type="xs:IDREF"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="olink">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="targetdoc"/>
- <xs:attribute name="role"/>
- <xs:attribute name="xrefstyle"/>
- <xs:attribute name="localinfo"/>
- <xs:attribute name="targetptr"/>
- <xs:attribute name="type"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="anchor">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="alt">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:inlinemediaobject"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="set">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:toc"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:set"/>
- <xs:element ref="docbook:book"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:setindex"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="book">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- <xs:element ref="docbook:dedication"/>
- <xs:element ref="docbook:acknowledgements"/>
- <xs:element ref="docbook:preface"/>
- <xs:element ref="docbook:chapter"/>
- <xs:element ref="docbook:appendix"/>
- <xs:element ref="docbook:article"/>
- <xs:element ref="docbook:colophon"/>
- <xs:element ref="docbook:part"/>
- <xs:element ref="docbook:reference"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="dedication">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="acknowledgements">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="colophon">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="appendix">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="chapter">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="part">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:partintro"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- <xs:element ref="docbook:dedication"/>
- <xs:element ref="docbook:acknowledgements"/>
- <xs:element ref="docbook:preface"/>
- <xs:element ref="docbook:chapter"/>
- <xs:element ref="docbook:appendix"/>
- <xs:element ref="docbook:article"/>
- <xs:element ref="docbook:colophon"/>
- <xs:element ref="docbook:refentry"/>
- <xs:element ref="docbook:reference"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="preface">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="partintro">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="section">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="simplesect">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="article">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- <xs:element ref="docbook:appendix"/>
- <xs:element ref="docbook:acknowledgements"/>
- <xs:element ref="docbook:colophon"/>
- </xs:choice>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:section"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect1"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- <xs:element ref="docbook:appendix"/>
- <xs:element ref="docbook:acknowledgements"/>
- <xs:element ref="docbook:colophon"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="faq"/>
- <xs:enumeration value="journalarticle"/>
- <xs:enumeration value="productsheet"/>
- <xs:enumeration value="specification"/>
- <xs:enumeration value="techreport"/>
- <xs:enumeration value="whitepaper"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="annotation">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attribute name="annotates"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="extendedlink">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:locator"/>
- <xs:element ref="docbook:arc"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="locator">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute ref="xlink:label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="arc">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute ref="xlink:from"/>
- <xs:attribute ref="xlink:to"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="sect1">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect2"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect2"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="sect2">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect3"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect3"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="sect3">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect4"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect4"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="sect4">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect5"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:sect5"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="sect5">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:simplesect"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:glossary"/>
- <xs:element ref="docbook:bibliography"/>
- <xs:element ref="docbook:index"/>
- <xs:element ref="docbook:toc"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="reference">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:partintro"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refentry"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="status"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element minOccurs="0" ref="docbook:refmeta"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refnamediv"/>
- <xs:element minOccurs="0" ref="docbook:refsynopsisdiv"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:refsection"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refsect1"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="status"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refmeta">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- <xs:element ref="docbook:refentrytitle"/>
- <xs:element minOccurs="0" ref="docbook:manvolnum"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:refmiscinfo"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refmiscinfo">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="source"/>
- <xs:enumeration value="version"/>
- <xs:enumeration value="manual"/>
- <xs:enumeration value="sectdesc"/>
- <xs:enumeration value="software"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherclass"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refnamediv">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:refdescriptor"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refname"/>
- <xs:element ref="docbook:refpurpose"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:refclass"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refdescriptor">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refpurpose">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refclass">
- <xs:complexType mixed="true">
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:application"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refsynopsisdiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0">
- <xs:element maxOccurs="unbounded" ref="docbook:refsection"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refsect2"/>
- </xs:choice>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refsection"/>
- <xs:element maxOccurs="unbounded" ref="docbook:refsect2"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refsection">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:refsection"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refsection"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="status"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refsect1">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:refsect2"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refsect2"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refsect2">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:refsect3"/>
- </xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:refsect3"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="refsect3">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glosslist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence minOccurs="0">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:glossentry"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:glossterm"/>
- <xs:element minOccurs="0" ref="docbook:acronym"/>
- <xs:element minOccurs="0" ref="docbook:abbrev"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- <xs:choice>
- <xs:element ref="docbook:glosssee"/>
- <xs:element maxOccurs="unbounded" ref="docbook:glossdef"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="sortas"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossdef">
- <xs:complexType>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:glossseealso"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="subject"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glosssee">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="otherterm" type="xs:IDREF"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossseealso">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="otherterm" type="xs:IDREF"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="firstterm">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="baseform"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossterm">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="baseform"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossary">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:glossdiv"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:glossentry"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:bibliography"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="glossdiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:glossentry"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="termdef">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attribute name="sortas"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="baseform"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="biblioentry">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:abstract"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:artpagenums"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:authorgroup"/>
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:bibliocoverage"/>
- <xs:element ref="docbook:biblioid"/>
- <xs:element ref="docbook:bibliosource"/>
- <xs:element ref="docbook:collab"/>
- <xs:element ref="docbook:confgroup"/>
- <xs:element ref="docbook:contractsponsor"/>
- <xs:element ref="docbook:contractnum"/>
- <xs:element ref="docbook:copyright"/>
- <xs:element ref="docbook:cover"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:edition"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:issuenum"/>
- <xs:element ref="docbook:keywordset"/>
- <xs:element ref="docbook:legalnotice"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:othercredit"/>
- <xs:element ref="docbook:pagenums"/>
- <xs:element ref="docbook:printhistory"/>
- <xs:element ref="docbook:pubdate"/>
- <xs:element ref="docbook:publisher"/>
- <xs:element ref="docbook:publishername"/>
- <xs:element ref="docbook:releaseinfo"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:seriesvolnums"/>
- <xs:element ref="docbook:subjectset"/>
- <xs:element ref="docbook:volumenum"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:extendedlink"/>
- <xs:element ref="docbook:bibliomisc"/>
- <xs:element ref="docbook:bibliomset"/>
- <xs:element ref="docbook:bibliorelation"/>
- <xs:element ref="docbook:biblioset"/>
- <xs:element ref="docbook:itermset"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:subtitle"/>
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliomixed">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:abstract"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:artpagenums"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:authorgroup"/>
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:bibliocoverage"/>
- <xs:element ref="docbook:biblioid"/>
- <xs:element ref="docbook:bibliosource"/>
- <xs:element ref="docbook:collab"/>
- <xs:element ref="docbook:confgroup"/>
- <xs:element ref="docbook:contractsponsor"/>
- <xs:element ref="docbook:contractnum"/>
- <xs:element ref="docbook:copyright"/>
- <xs:element ref="docbook:cover"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:edition"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:issuenum"/>
- <xs:element ref="docbook:keywordset"/>
- <xs:element ref="docbook:legalnotice"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:othercredit"/>
- <xs:element ref="docbook:pagenums"/>
- <xs:element ref="docbook:printhistory"/>
- <xs:element ref="docbook:pubdate"/>
- <xs:element ref="docbook:publisher"/>
- <xs:element ref="docbook:publishername"/>
- <xs:element ref="docbook:releaseinfo"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:seriesvolnums"/>
- <xs:element ref="docbook:subjectset"/>
- <xs:element ref="docbook:volumenum"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:extendedlink"/>
- <xs:element ref="docbook:bibliomisc"/>
- <xs:element ref="docbook:bibliomset"/>
- <xs:element ref="docbook:bibliorelation"/>
- <xs:element ref="docbook:biblioset"/>
- <xs:element ref="docbook:itermset"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:subtitle"/>
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="biblioset">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:abstract"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:artpagenums"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:authorgroup"/>
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:bibliocoverage"/>
- <xs:element ref="docbook:biblioid"/>
- <xs:element ref="docbook:bibliosource"/>
- <xs:element ref="docbook:collab"/>
- <xs:element ref="docbook:confgroup"/>
- <xs:element ref="docbook:contractsponsor"/>
- <xs:element ref="docbook:contractnum"/>
- <xs:element ref="docbook:copyright"/>
- <xs:element ref="docbook:cover"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:edition"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:issuenum"/>
- <xs:element ref="docbook:keywordset"/>
- <xs:element ref="docbook:legalnotice"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:othercredit"/>
- <xs:element ref="docbook:pagenums"/>
- <xs:element ref="docbook:printhistory"/>
- <xs:element ref="docbook:pubdate"/>
- <xs:element ref="docbook:publisher"/>
- <xs:element ref="docbook:publishername"/>
- <xs:element ref="docbook:releaseinfo"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:seriesvolnums"/>
- <xs:element ref="docbook:subjectset"/>
- <xs:element ref="docbook:volumenum"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:extendedlink"/>
- <xs:element ref="docbook:bibliomisc"/>
- <xs:element ref="docbook:bibliomset"/>
- <xs:element ref="docbook:bibliorelation"/>
- <xs:element ref="docbook:biblioset"/>
- <xs:element ref="docbook:itermset"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:subtitle"/>
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="relation"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliomset">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:abstract"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:artpagenums"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:authorgroup"/>
- <xs:element ref="docbook:authorinitials"/>
- <xs:element ref="docbook:bibliocoverage"/>
- <xs:element ref="docbook:biblioid"/>
- <xs:element ref="docbook:bibliosource"/>
- <xs:element ref="docbook:collab"/>
- <xs:element ref="docbook:confgroup"/>
- <xs:element ref="docbook:contractsponsor"/>
- <xs:element ref="docbook:contractnum"/>
- <xs:element ref="docbook:copyright"/>
- <xs:element ref="docbook:cover"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:edition"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:issuenum"/>
- <xs:element ref="docbook:keywordset"/>
- <xs:element ref="docbook:legalnotice"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:othercredit"/>
- <xs:element ref="docbook:pagenums"/>
- <xs:element ref="docbook:printhistory"/>
- <xs:element ref="docbook:pubdate"/>
- <xs:element ref="docbook:publisher"/>
- <xs:element ref="docbook:publishername"/>
- <xs:element ref="docbook:releaseinfo"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:seriesvolnums"/>
- <xs:element ref="docbook:subjectset"/>
- <xs:element ref="docbook:volumenum"/>
- <xs:element ref="docbook:extendedlink"/>
- <xs:element ref="docbook:bibliomisc"/>
- <xs:element ref="docbook:bibliomset"/>
- <xs:element ref="docbook:bibliorelation"/>
- <xs:element ref="docbook:biblioset"/>
- <xs:element ref="docbook:itermset"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personblurb"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:subtitle"/>
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="relation"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliomisc">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliography">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:bibliodiv"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:biblioentry"/>
- <xs:element ref="docbook:bibliomixed"/>
- </xs:choice>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliodiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:biblioentry"/>
- <xs:element ref="docbook:bibliomixed"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="bibliolist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence minOccurs="0">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:biblioentry"/>
- <xs:element ref="docbook:bibliomixed"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="biblioref">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="xrefstyle"/>
- <xs:attribute name="endterm" type="xs:IDREF"/>
- <xs:attribute name="units" type="xs:NMTOKEN"/>
- <xs:attribute name="begin" type="xs:NMTOKEN"/>
- <xs:attribute name="end" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="itermset">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:indexterm"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="indexterm">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:primary"/>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element ref="docbook:secondary"/>
- <xs:choice minOccurs="0">
- <xs:sequence>
- <xs:element ref="docbook:tertiary"/>
- <xs:choice minOccurs="0">
- <xs:element ref="docbook:see"/>
- <xs:element maxOccurs="unbounded" ref="docbook:seealso"/>
- </xs:choice>
- </xs:sequence>
- <xs:element ref="docbook:see"/>
- <xs:element maxOccurs="unbounded" ref="docbook:seealso"/>
- </xs:choice>
- </xs:sequence>
- <xs:element ref="docbook:see"/>
- <xs:element maxOccurs="unbounded" ref="docbook:seealso"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="significance">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="normal"/>
- <xs:enumeration value="preferred"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startref" type="xs:IDREF"/>
- <xs:attribute name="zone" type="xs:IDREFS"/>
- <xs:attribute name="pagenum"/>
- <xs:attribute name="scope">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="all"/>
- <xs:enumeration value="global"/>
- <xs:enumeration value="local"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="type"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="singular"/>
- <xs:enumeration value="startofrange"/>
- <xs:enumeration value="endofrange"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="primary">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="sortas"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="secondary">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="sortas"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tertiary">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="sortas"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="see">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seealso">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="index">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexdiv"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexentry"/>
- <xs:element ref="docbook:segmentedlist"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- <xs:attribute name="type"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="setindex">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexdiv"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- <xs:attribute name="type"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="indexdiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:indexentry"/>
- <xs:element ref="docbook:segmentedlist"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="status"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="indexentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:primaryie"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:seeie"/>
- <xs:element ref="docbook:seealsoie"/>
- </xs:choice>
- <xs:sequence minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:secondaryie"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:seeie"/>
- <xs:element ref="docbook:seealsoie"/>
- <xs:element ref="docbook:tertiaryie"/>
- </xs:choice>
- </xs:sequence>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="primaryie">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="secondaryie">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tertiaryie">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seeie">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="seealsoie">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="toc">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:tocdiv"/>
- <xs:element ref="docbook:tocentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tocdiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:tocdiv"/>
- <xs:element ref="docbook:tocentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="pagenum"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tocentry">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="pagenum"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="task">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- <xs:element ref="docbook:subtitle"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:tasksummary"/>
- <xs:element minOccurs="0" ref="docbook:taskprerequisites"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:example"/>
- <xs:element minOccurs="0" ref="docbook:taskrelated"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tasksummary">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="taskprerequisites">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="taskrelated">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="calloutlist">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:callout"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="callout">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="arearefs" use="required" type="xs:IDREFS"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="programlistingco">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:areaspec"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:calloutlist"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="areaspec">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:area"/>
- <xs:element ref="docbook:areaset"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="units">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="calspair"/>
- <xs:enumeration value="linecolumn"/>
- <xs:enumeration value="linecolumnpair"/>
- <xs:enumeration value="linerange"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherunits" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="area">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="units">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="calspair"/>
- <xs:enumeration value="linecolumn"/>
- <xs:enumeration value="linecolumnpair"/>
- <xs:enumeration value="linerange"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherunits" type="xs:NMTOKEN"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- <xs:attribute name="label"/>
- <xs:attribute name="coords" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="areaset">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:area"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="units">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="calspair"/>
- <xs:enumeration value="linecolumn"/>
- <xs:enumeration value="linecolumnpair"/>
- <xs:enumeration value="linerange"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherunits" type="xs:NMTOKEN"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="screenco">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:areaspec"/>
- <xs:element ref="docbook:screen"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:calloutlist"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="imageobjectco">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element ref="docbook:areaspec"/>
- <xs:element maxOccurs="unbounded" ref="docbook:imageobject"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:calloutlist"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="co">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="linkends" type="xs:IDREFS"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="coref">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="productionset">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:production"/>
- <xs:element ref="docbook:productionrecap"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="production">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:lhs"/>
- <xs:element ref="docbook:rhs"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:constraint"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="lhs">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="rhs">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:sbr"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="nonterminal">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="def" use="required"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="constraint">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="productionrecap">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="constraintdef">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tgroup">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colspec"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:spanspec"/>
- <xs:element minOccurs="0" ref="docbook:thead"/>
- <xs:element minOccurs="0" ref="docbook:tfoot"/>
- <xs:element ref="docbook:tbody"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="tgroupstyle"/>
- <xs:attribute name="cols" use="required" type="xs:NMTOKEN"/>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="colspec">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="colnum" type="xs:NMTOKEN"/>
- <xs:attribute name="char"/>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="colwidth"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="colname"/>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="spanspec">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="spanname" use="required"/>
- <xs:attribute name="namest" use="required"/>
- <xs:attribute name="nameend" use="required"/>
- <xs:attribute name="char"/>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="charoff"/>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="thead">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colspec"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:row"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tr"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tfoot">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colspec"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:row"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tr"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tbody">
- <xs:complexType>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:row"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tr"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="row">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:entry"/>
- <xs:element ref="docbook:entrytbl"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="entry">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="top"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="charoff"/>
- <xs:attribute name="morerows" type="xs:NMTOKEN"/>
- <xs:attribute name="colname"/>
- <xs:attribute name="namest"/>
- <xs:attribute name="spanname"/>
- <xs:attribute name="nameend"/>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rotate">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="entrytbl">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colspec"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:spanspec"/>
- <xs:element minOccurs="0" ref="docbook:thead"/>
- <xs:element ref="docbook:tbody"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="colname"/>
- <xs:attribute name="namest"/>
- <xs:attribute name="spanname"/>
- <xs:attribute name="nameend"/>
- <xs:attribute name="tgroupstyle"/>
- <xs:attribute name="cols" type="xs:NMTOKEN"/>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="center"/>
- <xs:enumeration value="char"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="right"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="table">
- <xs:complexType>
- <xs:choice>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:sequence>
- <xs:element ref="docbook:title"/>
- <xs:element minOccurs="0" ref="docbook:titleabbrev"/>
- </xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:indexterm"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:textobject"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:mediaobject"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tgroup"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:element ref="docbook:caption"/>
- <xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:col"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colgroup"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:thead"/>
- <xs:element minOccurs="0" ref="docbook:tfoot"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:tbody"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tr"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attribute name="label"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="tabstyle"/>
- <xs:attribute name="floatstyle"/>
- <xs:attribute name="orient">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="land"/>
- <xs:enumeration value="port"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="frame">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="all"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="none"/>
- <xs:enumeration value="sides"/>
- <xs:enumeration value="top"/>
- <xs:enumeration value="topbot"/>
- <xs:enumeration value="void"/>
- <xs:enumeration value="above"/>
- <xs:enumeration value="below"/>
- <xs:enumeration value="hsides"/>
- <xs:enumeration value="lhs"/>
- <xs:enumeration value="rhs"/>
- <xs:enumeration value="vsides"/>
- <xs:enumeration value="box"/>
- <xs:enumeration value="border"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="shortentry">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="tocentry">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowheader">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="firstcol"/>
- <xs:enumeration value="norowheader"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="summary"/>
- <xs:attribute name="width"/>
- <xs:attribute name="border" type="xs:NMTOKEN"/>
- <xs:attribute name="rules">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="groups"/>
- <xs:enumeration value="rows"/>
- <xs:enumeration value="cols"/>
- <xs:enumeration value="all"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="cellspacing"/>
- <xs:attribute name="cellpadding"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="informaltable">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:textobject"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:mediaobject"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tgroup"/>
- </xs:choice>
- </xs:sequence>
- <xs:sequence>
- <xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:col"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:colgroup"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:thead"/>
- <xs:element minOccurs="0" ref="docbook:tfoot"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:tbody"/>
- <xs:element maxOccurs="unbounded" ref="docbook:tr"/>
- </xs:choice>
- </xs:sequence>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="tabstyle"/>
- <xs:attribute name="floatstyle"/>
- <xs:attribute name="orient">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="land"/>
- <xs:enumeration value="port"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="colsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowsep">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="frame">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="all"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="none"/>
- <xs:enumeration value="sides"/>
- <xs:enumeration value="top"/>
- <xs:enumeration value="topbot"/>
- <xs:enumeration value="void"/>
- <xs:enumeration value="above"/>
- <xs:enumeration value="below"/>
- <xs:enumeration value="hsides"/>
- <xs:enumeration value="lhs"/>
- <xs:enumeration value="rhs"/>
- <xs:enumeration value="vsides"/>
- <xs:enumeration value="box"/>
- <xs:enumeration value="border"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowheader">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="firstcol"/>
- <xs:enumeration value="norowheader"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="summary"/>
- <xs:attribute name="width"/>
- <xs:attribute name="border" type="xs:NMTOKEN"/>
- <xs:attribute name="rules">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="groups"/>
- <xs:enumeration value="rows"/>
- <xs:enumeration value="cols"/>
- <xs:enumeration value="all"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="cellspacing"/>
- <xs:attribute name="cellpadding"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="col">
- <xs:complexType>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="span" type="xs:NMTOKEN"/>
- <xs:attribute name="width"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="colgroup">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:col"/>
- </xs:sequence>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="span" type="xs:NMTOKEN"/>
- <xs:attribute name="width"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="tr">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:th"/>
- <xs:element ref="docbook:td"/>
- </xs:choice>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="th">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="abbr"/>
- <xs:attribute name="axis"/>
- <xs:attribute name="headers"/>
- <xs:attribute name="scope">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="row"/>
- <xs:enumeration value="col"/>
- <xs:enumeration value="rowgroup"/>
- <xs:enumeration value="colgroup"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowspan" type="xs:NMTOKEN"/>
- <xs:attribute name="colspan" type="xs:NMTOKEN"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="td">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- </xs:choice>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attribute name="class"/>
- <xs:attribute name="style"/>
- <xs:attribute name="title"/>
- <xs:attribute name="lang"/>
- <xs:attribute name="onclick"/>
- <xs:attribute name="ondblclick"/>
- <xs:attribute name="onmousedown"/>
- <xs:attribute name="onmouseup"/>
- <xs:attribute name="onmouseover"/>
- <xs:attribute name="onmousemove"/>
- <xs:attribute name="onmouseout"/>
- <xs:attribute name="onkeypress"/>
- <xs:attribute name="onkeydown"/>
- <xs:attribute name="onkeyup"/>
- <xs:attribute name="abbr"/>
- <xs:attribute name="axis"/>
- <xs:attribute name="headers"/>
- <xs:attribute name="scope">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="row"/>
- <xs:enumeration value="col"/>
- <xs:enumeration value="rowgroup"/>
- <xs:enumeration value="colgroup"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="rowspan" type="xs:NMTOKEN"/>
- <xs:attribute name="colspan" type="xs:NMTOKEN"/>
- <xs:attribute name="align">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="left"/>
- <xs:enumeration value="center"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="justify"/>
- <xs:enumeration value="char"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="char"/>
- <xs:attribute name="charoff"/>
- <xs:attribute name="valign">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="top"/>
- <xs:enumeration value="middle"/>
- <xs:enumeration value="bottom"/>
- <xs:enumeration value="baseline"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgset">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:msgentry"/>
- <xs:element maxOccurs="unbounded" ref="docbook:simplemsgentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:msg"/>
- <xs:element minOccurs="0" ref="docbook:msginfo"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:msgexplan"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="simplemsgentry">
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="docbook:msgtext"/>
- <xs:element maxOccurs="unbounded" ref="docbook:msgexplan"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="msgaud"/>
- <xs:attribute name="msgorig"/>
- <xs:attribute name="msglevel"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msg">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:msgmain"/>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:msgsub"/>
- <xs:element ref="docbook:msgrel"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgmain">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:msgtext"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgsub">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:msgtext"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgrel">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:msgtext"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgtext">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msginfo">
- <xs:complexType>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:msglevel"/>
- <xs:element ref="docbook:msgorig"/>
- <xs:element ref="docbook:msgaud"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msglevel">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgorig">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgaud">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="msgexplan">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="qandaset">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:qandadiv"/>
- <xs:element maxOccurs="unbounded" ref="docbook:qandaentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="defaultlabel">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="none"/>
- <xs:enumeration value="number"/>
- <xs:enumeration value="qanda"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="qandadiv">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:qandadiv"/>
- <xs:element maxOccurs="unbounded" ref="docbook:qandaentry"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="qandaentry">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element ref="docbook:question"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:answer"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="question">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:label"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="answer">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:label"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="label">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="equation">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:mediaobject"/>
- <xs:element maxOccurs="unbounded" ref="docbook:mathphrase"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="label"/>
- <xs:attribute name="pgwide">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="0"/>
- <xs:enumeration value="1"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="floatstyle"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="informalequation">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:mediaobject"/>
- <xs:element maxOccurs="unbounded" ref="docbook:mathphrase"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:caption"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="inlineequation">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:alt"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:inlinemediaobject"/>
- <xs:element maxOccurs="unbounded" ref="docbook:mathphrase"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="mathphrase">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:emphasis"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="markup">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tag">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="attribute"/>
- <xs:enumeration value="attvalue"/>
- <xs:enumeration value="element"/>
- <xs:enumeration value="emptytag"/>
- <xs:enumeration value="endtag"/>
- <xs:enumeration value="genentity"/>
- <xs:enumeration value="localname"/>
- <xs:enumeration value="namespace"/>
- <xs:enumeration value="numcharref"/>
- <xs:enumeration value="paramentity"/>
- <xs:enumeration value="pi"/>
- <xs:enumeration value="prefix"/>
- <xs:enumeration value="comment"/>
- <xs:enumeration value="starttag"/>
- <xs:enumeration value="xmlpi"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="namespace"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="symbol">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="limit"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="token">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="literal">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="code">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="constant">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="limit"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="productname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="copyright"/>
- <xs:enumeration value="registered"/>
- <xs:enumeration value="service"/>
- <xs:enumeration value="trade"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="productnumber">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="database">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="altkey"/>
- <xs:enumeration value="constraint"/>
- <xs:enumeration value="datatype"/>
- <xs:enumeration value="field"/>
- <xs:enumeration value="foreignkey"/>
- <xs:enumeration value="group"/>
- <xs:enumeration value="index"/>
- <xs:enumeration value="key1"/>
- <xs:enumeration value="key2"/>
- <xs:enumeration value="name"/>
- <xs:enumeration value="primarykey"/>
- <xs:enumeration value="procedure"/>
- <xs:enumeration value="record"/>
- <xs:enumeration value="rule"/>
- <xs:enumeration value="secondarykey"/>
- <xs:enumeration value="table"/>
- <xs:enumeration value="user"/>
- <xs:enumeration value="view"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="application">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="hardware"/>
- <xs:enumeration value="software"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="hardware">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guibutton">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guiicon">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guilabel">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guimenu">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guimenuitem">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="guisubmenu">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="menuchoice">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:shortcut"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guisubmenu"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="mousebutton">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keycap">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="function">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="alt"/>
- <xs:enumeration value="backspace"/>
- <xs:enumeration value="command"/>
- <xs:enumeration value="control"/>
- <xs:enumeration value="delete"/>
- <xs:enumeration value="down"/>
- <xs:enumeration value="end"/>
- <xs:enumeration value="enter"/>
- <xs:enumeration value="escape"/>
- <xs:enumeration value="home"/>
- <xs:enumeration value="insert"/>
- <xs:enumeration value="left"/>
- <xs:enumeration value="meta"/>
- <xs:enumeration value="option"/>
- <xs:enumeration value="pagedown"/>
- <xs:enumeration value="pageup"/>
- <xs:enumeration value="right"/>
- <xs:enumeration value="shift"/>
- <xs:enumeration value="space"/>
- <xs:enumeration value="tab"/>
- <xs:enumeration value="up"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otherfunction"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keycode">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keycombo">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:mousebutton"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="action">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="click"/>
- <xs:enumeration value="double-click"/>
- <xs:enumeration value="press"/>
- <xs:enumeration value="seq"/>
- <xs:enumeration value="simul"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otheraction"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="keysym">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="accel">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="shortcut">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:mousebutton"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="action">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="click"/>
- <xs:enumeration value="double-click"/>
- <xs:enumeration value="press"/>
- <xs:enumeration value="seq"/>
- <xs:enumeration value="simul"/>
- <xs:enumeration value="other"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="otheraction"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="prompt">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="envar">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="filename">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="path"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="devicefile"/>
- <xs:enumeration value="directory"/>
- <xs:enumeration value="extension"/>
- <xs:enumeration value="headerfile"/>
- <xs:enumeration value="libraryfile"/>
- <xs:enumeration value="partition"/>
- <xs:enumeration value="symlink"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="command">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="computeroutput">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:co"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="userinput">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:co"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="cmdsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:arg"/>
- <xs:element ref="docbook:group"/>
- <xs:element ref="docbook:sbr"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:synopfragment"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="sepchar"/>
- <xs:attribute name="cmdlength"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="arg">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:arg"/>
- <xs:element ref="docbook:group"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:synopfragmentref"/>
- <xs:element ref="docbook:sbr"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="rep" default="norepeat">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="norepeat"/>
- <xs:enumeration value="repeat"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="choice" default="opt">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="opt"/>
- <xs:enumeration value="plain"/>
- <xs:enumeration value="req"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="group">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:arg"/>
- <xs:element ref="docbook:group"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:synopfragmentref"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:sbr"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="rep" default="norepeat">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="norepeat"/>
- <xs:enumeration value="repeat"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="choice" default="opt">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="opt"/>
- <xs:enumeration value="plain"/>
- <xs:enumeration value="req"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="sbr">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="synopfragment">
- <xs:complexType>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:arg"/>
- <xs:element ref="docbook:group"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="synopfragmentref">
- <xs:complexType mixed="true">
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="synopsis">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- <xs:attribute name="label"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" ref="docbook:info"/>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:funcsynopsisinfo"/>
- <xs:element ref="docbook:funcprototype"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcsynopsisinfo">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcprototype">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- <xs:element ref="docbook:funcdef"/>
- <xs:choice>
- <xs:element ref="docbook:void"/>
- <xs:element ref="docbook:varargs"/>
- <xs:sequence>
- <xs:element maxOccurs="unbounded" ref="docbook:paramdef"/>
- <xs:element minOccurs="0" ref="docbook:varargs"/>
- </xs:sequence>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcdef">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:function"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="function">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="void">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="varargs">
- <xs:complexType>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="paramdef">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:funcparams"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="choice" default="opt">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="opt"/>
- <xs:enumeration value="req"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="funcparams">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="classsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- </xs:choice>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:classsynopsisinfo"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="class"/>
- <xs:enumeration value="interface"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="classsynopsisinfo">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="ooclass">
- <xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:modifier"/>
- </xs:choice>
- <xs:element ref="docbook:classname"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="oointerface">
- <xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:modifier"/>
- </xs:choice>
- <xs:element ref="docbook:interfacename"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="ooexception">
- <xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:modifier"/>
- </xs:choice>
- <xs:element ref="docbook:exceptionname"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="modifier">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute ref="xml:space"/>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="interfacename">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="exceptionname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="fieldsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- <xs:element minOccurs="0" ref="docbook:type"/>
- <xs:element ref="docbook:varname"/>
- <xs:element minOccurs="0" ref="docbook:initializer"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="initializer">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="constructorsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- <xs:element minOccurs="0" ref="docbook:methodname"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:methodparam"/>
- <xs:element minOccurs="0" ref="docbook:void"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:exceptionname"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="destructorsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- <xs:element minOccurs="0" ref="docbook:methodname"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:methodparam"/>
- <xs:element minOccurs="0" ref="docbook:void"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:exceptionname"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="methodsynopsis">
- <xs:complexType>
- <xs:sequence>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- <xs:choice minOccurs="0">
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:void"/>
- </xs:choice>
- <xs:element ref="docbook:methodname"/>
- <xs:choice>
- <xs:element maxOccurs="unbounded" ref="docbook:methodparam"/>
- <xs:element ref="docbook:void"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:exceptionname"/>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="language"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="methodname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="methodparam">
- <xs:complexType>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:type"/>
- </xs:choice>
- <xs:choice>
- <xs:sequence>
- <xs:element ref="docbook:parameter"/>
- <xs:element minOccurs="0" ref="docbook:initializer"/>
- </xs:sequence>
- <xs:element ref="docbook:funcparams"/>
- </xs:choice>
- <xs:element minOccurs="0" maxOccurs="unbounded" ref="docbook:modifier"/>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="rep" default="norepeat">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="norepeat"/>
- <xs:enumeration value="repeat"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="choice" default="req">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="opt"/>
- <xs:enumeration value="plain"/>
- <xs:enumeration value="req"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="varname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="returnvalue">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="type">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="classname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="programlisting">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:info"/>
- <xs:element ref="docbook:textobject"/>
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:abbrev"/>
- <xs:element ref="docbook:acronym"/>
- <xs:element ref="docbook:date"/>
- <xs:element ref="docbook:emphasis"/>
- <xs:element ref="docbook:footnote"/>
- <xs:element ref="docbook:footnoteref"/>
- <xs:element ref="docbook:foreignphrase"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:quote"/>
- <xs:element ref="docbook:wordasword"/>
- <xs:element ref="docbook:firstterm"/>
- <xs:element ref="docbook:glossterm"/>
- <xs:element ref="docbook:coref"/>
- <xs:element ref="docbook:trademark"/>
- <xs:element ref="docbook:productnumber"/>
- <xs:element ref="docbook:productname"/>
- <xs:element ref="docbook:database"/>
- <xs:element ref="docbook:application"/>
- <xs:element ref="docbook:hardware"/>
- <xs:element ref="docbook:citation"/>
- <xs:element ref="docbook:citerefentry"/>
- <xs:element ref="docbook:citetitle"/>
- <xs:element ref="docbook:citebiblioid"/>
- <xs:element ref="docbook:author"/>
- <xs:element ref="docbook:person"/>
- <xs:element ref="docbook:personname"/>
- <xs:element ref="docbook:org"/>
- <xs:element ref="docbook:orgname"/>
- <xs:element ref="docbook:editor"/>
- <xs:element ref="docbook:jobtitle"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:package"/>
- <xs:element ref="docbook:parameter"/>
- <xs:element ref="docbook:termdef"/>
- <xs:element ref="docbook:nonterminal"/>
- <xs:element ref="docbook:systemitem"/>
- <xs:element ref="docbook:option"/>
- <xs:element ref="docbook:optional"/>
- <xs:element ref="docbook:property"/>
- <xs:element ref="docbook:inlineequation"/>
- <xs:element ref="docbook:tag"/>
- <xs:element ref="docbook:markup"/>
- <xs:element ref="docbook:token"/>
- <xs:element ref="docbook:symbol"/>
- <xs:element ref="docbook:literal"/>
- <xs:element ref="docbook:code"/>
- <xs:element ref="docbook:constant"/>
- <xs:element ref="docbook:email"/>
- <xs:element ref="docbook:uri"/>
- <xs:element ref="docbook:guiicon"/>
- <xs:element ref="docbook:guibutton"/>
- <xs:element ref="docbook:guimenuitem"/>
- <xs:element ref="docbook:guimenu"/>
- <xs:element ref="docbook:guisubmenu"/>
- <xs:element ref="docbook:guilabel"/>
- <xs:element ref="docbook:menuchoice"/>
- <xs:element ref="docbook:mousebutton"/>
- <xs:element ref="docbook:keycombo"/>
- <xs:element ref="docbook:keycap"/>
- <xs:element ref="docbook:keycode"/>
- <xs:element ref="docbook:keysym"/>
- <xs:element ref="docbook:shortcut"/>
- <xs:element ref="docbook:accel"/>
- <xs:element ref="docbook:prompt"/>
- <xs:element ref="docbook:envar"/>
- <xs:element ref="docbook:filename"/>
- <xs:element ref="docbook:command"/>
- <xs:element ref="docbook:computeroutput"/>
- <xs:element ref="docbook:userinput"/>
- <xs:element ref="docbook:function"/>
- <xs:element ref="docbook:varname"/>
- <xs:element ref="docbook:returnvalue"/>
- <xs:element ref="docbook:type"/>
- <xs:element ref="docbook:classname"/>
- <xs:element ref="docbook:exceptionname"/>
- <xs:element ref="docbook:interfacename"/>
- <xs:element ref="docbook:methodname"/>
- <xs:element ref="docbook:modifier"/>
- <xs:element ref="docbook:initializer"/>
- <xs:element ref="docbook:ooclass"/>
- <xs:element ref="docbook:ooexception"/>
- <xs:element ref="docbook:oointerface"/>
- <xs:element ref="docbook:errorcode"/>
- <xs:element ref="docbook:errortext"/>
- <xs:element ref="docbook:errorname"/>
- <xs:element ref="docbook:errortype"/>
- <xs:element ref="docbook:lineannotation"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="continuation">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="continues"/>
- <xs:enumeration value="restarts"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="linenumbering">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="numbered"/>
- <xs:enumeration value="unnumbered"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="startinglinenumber" type="xs:NMTOKEN"/>
- <xs:attribute name="language"/>
- <xs:attribute ref="xml:space"/>
- <xs:attribute name="width" type="xs:NMTOKEN"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="caution">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="important">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="note">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="tip">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="warning">
- <xs:complexType>
- <xs:sequence>
- <xs:sequence>
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:title"/>
- <xs:element ref="docbook:titleabbrev"/>
- </xs:choice>
- <xs:element minOccurs="0" ref="docbook:info"/>
- </xs:sequence>
- <xs:choice maxOccurs="unbounded">
- <xs:element ref="docbook:itemizedlist"/>
- <xs:element ref="docbook:orderedlist"/>
- <xs:element ref="docbook:procedure"/>
- <xs:element ref="docbook:simplelist"/>
- <xs:element ref="docbook:variablelist"/>
- <xs:element ref="docbook:segmentedlist"/>
- <xs:element ref="docbook:glosslist"/>
- <xs:element ref="docbook:bibliolist"/>
- <xs:element ref="docbook:calloutlist"/>
- <xs:element ref="docbook:qandaset"/>
- <xs:element ref="docbook:example"/>
- <xs:element ref="docbook:figure"/>
- <xs:element ref="docbook:table"/>
- <xs:element ref="docbook:equation"/>
- <xs:element ref="docbook:informalexample"/>
- <xs:element ref="docbook:informalfigure"/>
- <xs:element ref="docbook:informaltable"/>
- <xs:element ref="docbook:informalequation"/>
- <xs:element ref="docbook:sidebar"/>
- <xs:element ref="docbook:blockquote"/>
- <xs:element ref="docbook:address"/>
- <xs:element ref="docbook:epigraph"/>
- <xs:element ref="docbook:mediaobject"/>
- <xs:element ref="docbook:screenshot"/>
- <xs:element ref="docbook:task"/>
- <xs:element ref="docbook:productionset"/>
- <xs:element ref="docbook:constraintdef"/>
- <xs:element ref="docbook:msgset"/>
- <xs:element ref="docbook:screen"/>
- <xs:element ref="docbook:literallayout"/>
- <xs:element ref="docbook:programlistingco"/>
- <xs:element ref="docbook:screenco"/>
- <xs:element ref="docbook:programlisting"/>
- <xs:element ref="docbook:synopsis"/>
- <xs:element ref="docbook:bridgehead"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:revhistory"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:funcsynopsis"/>
- <xs:element ref="docbook:classsynopsis"/>
- <xs:element ref="docbook:methodsynopsis"/>
- <xs:element ref="docbook:constructorsynopsis"/>
- <xs:element ref="docbook:destructorsynopsis"/>
- <xs:element ref="docbook:fieldsynopsis"/>
- <xs:element ref="docbook:cmdsynopsis"/>
- <xs:element ref="docbook:caution"/>
- <xs:element ref="docbook:important"/>
- <xs:element ref="docbook:note"/>
- <xs:element ref="docbook:tip"/>
- <xs:element ref="docbook:warning"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:para"/>
- <xs:element ref="docbook:formalpara"/>
- <xs:element ref="docbook:simpara"/>
- <xs:element ref="docbook:annotation"/>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="errorcode">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="errorname">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="errortext">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="errortype">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="systemitem">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- <xs:element ref="docbook:co"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- <xs:attribute name="class">
- <xs:simpleType>
- <xs:restriction base="xs:token">
- <xs:enumeration value="daemon"/>
- <xs:enumeration value="domainname"/>
- <xs:enumeration value="etheraddress"/>
- <xs:enumeration value="event"/>
- <xs:enumeration value="eventhandler"/>
- <xs:enumeration value="filesystem"/>
- <xs:enumeration value="fqdomainname"/>
- <xs:enumeration value="groupname"/>
- <xs:enumeration value="ipaddress"/>
- <xs:enumeration value="library"/>
- <xs:enumeration value="macro"/>
- <xs:enumeration value="netmask"/>
- <xs:enumeration value="newsgroup"/>
- <xs:enumeration value="osname"/>
- <xs:enumeration value="process"/>
- <xs:enumeration value="protocol"/>
- <xs:enumeration value="resource"/>
- <xs:enumeration value="server"/>
- <xs:enumeration value="service"/>
- <xs:enumeration value="systemname"/>
- <xs:enumeration value="username"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- </xs:complexType>
- </xs:element>
- <xs:element name="option">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="optional">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="property">
- <xs:complexType mixed="true">
- <xs:choice minOccurs="0" maxOccurs="unbounded">
- <xs:element ref="docbook:inlinemediaobject"/>
- <xs:element ref="docbook:remark"/>
- <xs:element ref="docbook:superscript"/>
- <xs:element ref="docbook:subscript"/>
- <xs:element ref="docbook:xref"/>
- <xs:element ref="docbook:link"/>
- <xs:element ref="docbook:olink"/>
- <xs:element ref="docbook:anchor"/>
- <xs:element ref="docbook:biblioref"/>
- <xs:element ref="docbook:alt"/>
- <xs:element ref="docbook:annotation"/>
- <xs:element ref="docbook:indexterm"/>
- <xs:element ref="docbook:phrase"/>
- <xs:element ref="docbook:replaceable"/>
- </xs:choice>
- <xs:attribute name="role"/>
- <xs:attributeGroup ref="docbook:db.common.attributes"/>
- <xs:attributeGroup ref="docbook:db.common.linking.attributes"/>
- </xs:complexType>
- </xs:element>
-</xs:schema>
-<?xml version='1.0' encoding='UTF-8'?>\r
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink">\r
- \r
- <xs:annotation>\r
- <xs:documentation>This schema is not normative, or even definitive. The\r
-prose copy in the XLink 1.1 recommendation (http://www.w3.org/TR/xlink11/) is\r
-definitive, although it should not differ from this file, except for the\r
-absence of these two initial comments.</xs:documentation>\r
- </xs:annotation>\r
- \r
- <xs:annotation>\r
- <xs:documentation>In keeping with the W3C's standard versioning\r
- policy, this schema document will persist at\r
- http://www.w3.org/XML/2008/06/xlink.xsd.\r
- At the date of issue it can also be found at\r
- http://www.w3.org/1999/xlink.xsd.\r
- The schema document at that URI may however change in the future,\r
- in order to remain compatible with the latest version of XML Schema\r
- itself, or with the XLink namespace itself. In other words, if the XML\r
- Schema or XLink namespaces change, the version of this document at\r
- http://www.w3.org/1999/xlink.xsd will change\r
- accordingly; the version at\r
- http://www.w3.org/2008/06/xlink.xsd will not change.\r
-</xs:documentation>\r
- </xs:annotation>\r
- \r
- <xs:annotation>\r
- <xs:documentation>This schema document provides attribute declarations and\r
-attribute group, complex type and simple type definitions which can be used in\r
-the construction of user schemas to define the structure of particular linking\r
-constructs, e.g.\r
-<![CDATA[\r
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"\r
- xmlns:xl="http://www.w3.org/1999/xlink">\r
-\r
- <xs:import namespace="http://www.w3.org/1999/xlink"\r
- location="http://www.w3.org/1999/xlink.xsd">\r
-\r
- <xs:element name="mySimple">\r
- <xs:complexType>\r
- ...\r
- <xs:attributeGroup ref="xl:simpleAttrs"/>\r
- ...\r
- </xs:complexType>\r
- </xs:element>\r
- ...\r
-</xs:schema>]]></xs:documentation>\r
- </xs:annotation>\r
-\r
- <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>\r
-\r
- <xs:attribute name="type" type="xlink:typeType"/>\r
-\r
- <xs:simpleType name="typeType">\r
- <xs:restriction base="xs:token">\r
- <xs:enumeration value="simple"/>\r
- <xs:enumeration value="extended"/>\r
- <xs:enumeration value="title"/>\r
- <xs:enumeration value="resource"/>\r
- <xs:enumeration value="locator"/>\r
- <xs:enumeration value="arc"/>\r
- </xs:restriction>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="href" type="xlink:hrefType"/>\r
-\r
- <xs:simpleType name="hrefType">\r
- <xs:restriction base="xs:anyURI"/>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="role" type="xlink:roleType"/>\r
-\r
- <xs:simpleType name="roleType">\r
- <xs:restriction base="xs:anyURI">\r
- <xs:minLength value="1"/>\r
- </xs:restriction>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="arcrole" type="xlink:arcroleType"/>\r
-\r
- <xs:simpleType name="arcroleType">\r
- <xs:restriction base="xs:anyURI">\r
- <xs:minLength value="1"/>\r
- </xs:restriction>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="title" type="xlink:titleAttrType"/>\r
-\r
- <xs:simpleType name="titleAttrType">\r
- <xs:restriction base="xs:string"/>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="show" type="xlink:showType"/>\r
-\r
- <xs:simpleType name="showType">\r
- <xs:restriction base="xs:token">\r
- <xs:enumeration value="new"/>\r
- <xs:enumeration value="replace"/>\r
- <xs:enumeration value="embed"/>\r
- <xs:enumeration value="other"/>\r
- <xs:enumeration value="none"/>\r
- </xs:restriction>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="actuate" type="xlink:actuateType"/>\r
-\r
- <xs:simpleType name="actuateType">\r
- <xs:restriction base="xs:token">\r
- <xs:enumeration value="onLoad"/>\r
- <xs:enumeration value="onRequest"/>\r
- <xs:enumeration value="other"/>\r
- <xs:enumeration value="none"/>\r
- </xs:restriction>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="label" type="xlink:labelType"/>\r
-\r
- <xs:simpleType name="labelType">\r
- <xs:restriction base="xs:NCName"/>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="from" type="xlink:fromType"/>\r
-\r
- <xs:simpleType name="fromType">\r
- <xs:restriction base="xs:NCName"/>\r
- </xs:simpleType>\r
-\r
- <xs:attribute name="to" type="xlink:toType"/>\r
-\r
- <xs:simpleType name="toType">\r
- <xs:restriction base="xs:NCName"/>\r
- </xs:simpleType>\r
-\r
- <xs:attributeGroup name="simpleAttrs">\r
- <xs:attribute ref="xlink:type" fixed="simple"/>\r
- <xs:attribute ref="xlink:href"/>\r
- <xs:attribute ref="xlink:role"/>\r
- <xs:attribute ref="xlink:arcrole"/>\r
- <xs:attribute ref="xlink:title"/>\r
- <xs:attribute ref="xlink:show"/>\r
- <xs:attribute ref="xlink:actuate"/>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="simpleModel">\r
- <xs:sequence>\r
- <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
- </xs:sequence>\r
- </xs:group>\r
-\r
- <xs:complexType mixed="true" name="simple">\r
- <xs:annotation>\r
- <xs:documentation>\r
- Intended for use as the type of user-declared elements to make them\r
- simple links.\r
- </xs:documentation>\r
- </xs:annotation>\r
- <xs:group ref="xlink:simpleModel"/>\r
- <xs:attributeGroup ref="xlink:simpleAttrs"/>\r
- </xs:complexType>\r
-\r
- <xs:attributeGroup name="extendedAttrs">\r
- <xs:attribute ref="xlink:type" fixed="extended" use="required"/>\r
- <xs:attribute ref="xlink:role"/>\r
- <xs:attribute ref="xlink:title"/>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="extendedModel">\r
- <xs:choice>\r
- <xs:element ref="xlink:title"/>\r
- <xs:element ref="xlink:resource"/>\r
- <xs:element ref="xlink:locator"/>\r
- <xs:element ref="xlink:arc"/>\r
- </xs:choice>\r
- </xs:group>\r
-\r
- <xs:complexType name="extended">\r
- <xs:annotation>\r
- <xs:documentation>\r
- Intended for use as the type of user-declared elements to make them\r
- extended links.\r
- Note that the elements referenced in the content model are all abstract.\r
- The intention is that by simply declaring elements with these as their\r
- substitutionGroup, all the right things will happen.\r
- </xs:documentation>\r
- </xs:annotation>\r
- <xs:group ref="xlink:extendedModel" minOccurs="0" maxOccurs="unbounded"/>\r
- <xs:attributeGroup ref="xlink:extendedAttrs"/>\r
- </xs:complexType>\r
-\r
- <xs:element name="title" type="xlink:titleEltType" abstract="true"/>\r
-\r
- <xs:attributeGroup name="titleAttrs">\r
- <xs:attribute ref="xlink:type" fixed="title" use="required"/>\r
- <xs:attribute ref="xml:lang">\r
- <xs:annotation>\r
- <xs:documentation>\r
- xml:lang is not required, but provides much of the\r
- motivation for title elements in addition to attributes, and so\r
- is provided here for convenience.\r
- </xs:documentation>\r
- </xs:annotation>\r
- </xs:attribute>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="titleModel">\r
- <xs:sequence>\r
- <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
- </xs:sequence>\r
- </xs:group>\r
-\r
- <xs:complexType mixed="true" name="titleEltType">\r
- <xs:group ref="xlink:titleModel"/>\r
- <xs:attributeGroup ref="xlink:titleAttrs"/>\r
- </xs:complexType>\r
-\r
- <xs:element name="resource" type="xlink:resourceType" abstract="true"/>\r
-\r
- <xs:attributeGroup name="resourceAttrs">\r
- <xs:attribute ref="xlink:type" fixed="resource" use="required"/>\r
- <xs:attribute ref="xlink:role"/>\r
- <xs:attribute ref="xlink:title"/>\r
- <xs:attribute ref="xlink:label"/>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="resourceModel">\r
- <xs:sequence>\r
- <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
- </xs:sequence>\r
- </xs:group>\r
-\r
- <xs:complexType mixed="true" name="resourceType">\r
- <xs:group ref="xlink:resourceModel"/>\r
- <xs:attributeGroup ref="xlink:resourceAttrs"/>\r
- </xs:complexType>\r
-\r
- <xs:element name="locator" type="xlink:locatorType" abstract="true"/>\r
-\r
- <xs:attributeGroup name="locatorAttrs">\r
- <xs:attribute ref="xlink:type" fixed="locator" use="required"/>\r
- <xs:attribute ref="xlink:href" use="required"/>\r
- <xs:attribute ref="xlink:role"/>\r
- <xs:attribute ref="xlink:title"/>\r
- <xs:attribute ref="xlink:label">\r
- <xs:annotation>\r
- <xs:documentation>\r
- label is not required, but locators have no particular\r
- XLink function if they are not labeled.\r
- </xs:documentation>\r
- </xs:annotation>\r
- </xs:attribute>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="locatorModel">\r
- <xs:sequence>\r
- <xs:element ref="xlink:title" minOccurs="0" maxOccurs="unbounded"/>\r
- </xs:sequence>\r
- </xs:group>\r
-\r
- <xs:complexType name="locatorType">\r
- <xs:group ref="xlink:locatorModel"/>\r
- <xs:attributeGroup ref="xlink:locatorAttrs"/>\r
- </xs:complexType>\r
-\r
- <xs:element name="arc" type="xlink:arcType" abstract="true"/>\r
-\r
- <xs:attributeGroup name="arcAttrs">\r
- <xs:attribute ref="xlink:type" fixed="arc" use="required"/>\r
- <xs:attribute ref="xlink:arcrole"/>\r
- <xs:attribute ref="xlink:title"/>\r
- <xs:attribute ref="xlink:show"/>\r
- <xs:attribute ref="xlink:actuate"/>\r
- <xs:attribute ref="xlink:from"/>\r
- <xs:attribute ref="xlink:to">\r
- <xs:annotation>\r
- <xs:documentation>\r
- from and to have default behavior when values are missing\r
- </xs:documentation>\r
- </xs:annotation>\r
- </xs:attribute>\r
- </xs:attributeGroup>\r
-\r
- <xs:group name="arcModel">\r
- <xs:sequence>\r
- <xs:element ref="xlink:title" minOccurs="0" maxOccurs="unbounded"/>\r
- </xs:sequence>\r
- </xs:group>\r
-\r
- <xs:complexType name="arcType">\r
- <xs:group ref="xlink:arcModel"/>\r
- <xs:attributeGroup ref="xlink:arcAttrs"/>\r
- </xs:complexType>\r
-\r
-</xs:schema>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/1999/xlink" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+ <xs:annotation>
+ <xs:documentation>This schema document provides attribute declarations and
+attribute group, complex type and simple type definitions which can be used in
+the construction of user schemas to define the structure of particular linking
+constructs, e.g.
+<![CDATA[
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xl="http://www.w3.org/1999/xlink">
+
+ <xs:import namespace="http://www.w3.org/1999/xlink"
+ location="http://www.w3.org/1999/xlink.xsd">
+
+ <xs:element name="mySimple">
+ <xs:complexType>
+ ...
+ <xs:attributeGroup ref="xl:simpleAttrs"/>
+ ...
+ </xs:complexType>
+ </xs:element>
+ ...
+</xs:schema>]]></xs:documentation>
+ </xs:annotation>
+
+ <xs:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+
+ <xs:attribute name="type" type="xlink:typeType"/>
+
+ <xs:simpleType name="typeType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="simple"/>
+ <xs:enumeration value="extended"/>
+ <xs:enumeration value="title"/>
+ <xs:enumeration value="resource"/>
+ <xs:enumeration value="locator"/>
+ <xs:enumeration value="arc"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:attribute name="href" type="xlink:hrefType"/>
+
+ <xs:simpleType name="hrefType">
+ <xs:restriction base="xs:anyURI"/>
+ </xs:simpleType>
+
+ <xs:attribute name="role" type="xlink:roleType"/>
+
+ <xs:simpleType name="roleType">
+ <xs:restriction base="xs:anyURI">
+ <xs:minLength value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:attribute name="arcrole" type="xlink:arcroleType"/>
+
+ <xs:simpleType name="arcroleType">
+ <xs:restriction base="xs:anyURI">
+ <xs:minLength value="1"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:attribute name="title" type="xlink:titleAttrType"/>
+
+ <xs:simpleType name="titleAttrType">
+ <xs:restriction base="xs:string"/>
+ </xs:simpleType>
+
+ <xs:attribute name="show" type="xlink:showType"/>
+
+ <xs:simpleType name="showType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="new"/>
+ <xs:enumeration value="replace"/>
+ <xs:enumeration value="embed"/>
+ <xs:enumeration value="other"/>
+ <xs:enumeration value="none"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:attribute name="actuate" type="xlink:actuateType"/>
+
+ <xs:simpleType name="actuateType">
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="onLoad"/>
+ <xs:enumeration value="onRequest"/>
+ <xs:enumeration value="other"/>
+ <xs:enumeration value="none"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:attribute name="label" type="xlink:labelType"/>
+
+ <xs:simpleType name="labelType">
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+
+ <xs:attribute name="from" type="xlink:fromType"/>
+
+ <xs:simpleType name="fromType">
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+
+ <xs:attribute name="to" type="xlink:toType"/>
+
+ <xs:simpleType name="toType">
+ <xs:restriction base="xs:NCName"/>
+ </xs:simpleType>
+
+ <xs:attributeGroup name="simpleAttrs">
+ <xs:attribute ref="xlink:type" fixed="simple"/>
+ <xs:attribute ref="xlink:href"/>
+ <xs:attribute ref="xlink:role"/>
+ <xs:attribute ref="xlink:arcrole"/>
+ <xs:attribute ref="xlink:title"/>
+ <xs:attribute ref="xlink:show"/>
+ <xs:attribute ref="xlink:actuate"/>
+ </xs:attributeGroup>
+
+ <xs:group name="simpleModel">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:complexType mixed="true" name="simple">
+ <xs:annotation>
+ <xs:documentation>
+ Intended for use as the type of user-declared elements to make them
+ simple links.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:group ref="xlink:simpleModel"/>
+ <xs:attributeGroup ref="xlink:simpleAttrs"/>
+ </xs:complexType>
+
+ <xs:attributeGroup name="extendedAttrs">
+ <xs:attribute ref="xlink:type" fixed="extended" use="required"/>
+ <xs:attribute ref="xlink:role"/>
+ <xs:attribute ref="xlink:title"/>
+ </xs:attributeGroup>
+
+ <xs:group name="extendedModel">
+ <xs:choice>
+ <xs:element ref="xlink:title"/>
+ <xs:element ref="xlink:resource"/>
+ <xs:element ref="xlink:locator"/>
+ <xs:element ref="xlink:arc"/>
+ </xs:choice>
+ </xs:group>
+
+ <xs:complexType name="extended">
+ <xs:annotation>
+ <xs:documentation>
+ Intended for use as the type of user-declared elements to make them
+ extended links.
+ Note that the elements referenced in the content model are all abstract.
+ The intention is that by simply declaring elements with these as their
+ substitutionGroup, all the right things will happen.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:group ref="xlink:extendedModel" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:attributeGroup ref="xlink:extendedAttrs"/>
+ </xs:complexType>
+
+ <xs:element name="title" type="xlink:titleEltType" abstract="true"/>
+
+ <xs:attributeGroup name="titleAttrs">
+ <xs:attribute ref="xlink:type" fixed="title" use="required"/>
+ <xs:attribute ref="xml:lang">
+ <xs:annotation>
+ <xs:documentation>
+ xml:lang is not required, but provides much of the
+ motivation for title elements in addition to attributes, and so
+ is provided here for convenience.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+
+ <xs:group name="titleModel">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:complexType mixed="true" name="titleEltType">
+ <xs:group ref="xlink:titleModel"/>
+ <xs:attributeGroup ref="xlink:titleAttrs"/>
+ </xs:complexType>
+
+ <xs:element name="resource" type="xlink:resourceType" abstract="true"/>
+
+ <xs:attributeGroup name="resourceAttrs">
+ <xs:attribute ref="xlink:type" fixed="resource" use="required"/>
+ <xs:attribute ref="xlink:role"/>
+ <xs:attribute ref="xlink:title"/>
+ <xs:attribute ref="xlink:label"/>
+ </xs:attributeGroup>
+
+ <xs:group name="resourceModel">
+ <xs:sequence>
+ <xs:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:complexType mixed="true" name="resourceType">
+ <xs:group ref="xlink:resourceModel"/>
+ <xs:attributeGroup ref="xlink:resourceAttrs"/>
+ </xs:complexType>
+
+ <xs:element name="locator" type="xlink:locatorType" abstract="true"/>
+
+ <xs:attributeGroup name="locatorAttrs">
+ <xs:attribute ref="xlink:type" fixed="locator" use="required"/>
+ <xs:attribute ref="xlink:href" use="required"/>
+ <xs:attribute ref="xlink:role"/>
+ <xs:attribute ref="xlink:title"/>
+ <xs:attribute ref="xlink:label">
+ <xs:annotation>
+ <xs:documentation>
+ label is not required, but locators have no particular
+ XLink function if they are not labeled.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+
+ <xs:group name="locatorModel">
+ <xs:sequence>
+ <xs:element ref="xlink:title" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:complexType name="locatorType">
+ <xs:group ref="xlink:locatorModel"/>
+ <xs:attributeGroup ref="xlink:locatorAttrs"/>
+ </xs:complexType>
+
+ <xs:element name="arc" type="xlink:arcType" abstract="true"/>
+
+ <xs:attributeGroup name="arcAttrs">
+ <xs:attribute ref="xlink:type" fixed="arc" use="required"/>
+ <xs:attribute ref="xlink:arcrole"/>
+ <xs:attribute ref="xlink:title"/>
+ <xs:attribute ref="xlink:show"/>
+ <xs:attribute ref="xlink:actuate"/>
+ <xs:attribute ref="xlink:from"/>
+ <xs:attribute ref="xlink:to">
+ <xs:annotation>
+ <xs:documentation>
+ from and to have default behavior when values are missing
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:attributeGroup>
+
+ <xs:group name="arcModel">
+ <xs:sequence>
+ <xs:element ref="xlink:title" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:group>
+
+ <xs:complexType name="arcType">
+ <xs:group ref="xlink:arcModel"/>
+ <xs:attributeGroup ref="xlink:arcAttrs"/>
+ </xs:complexType>
+
+ <!-- Hack required for GML support -->
+ <xs:attributeGroup name="simpleLink">
+ <xs:attribute name="type" type="xs:string" use="optional" fixed="simple" form="qualified"/>
+ <xs:attribute ref="xlink:href" use="optional"/>
+ <xs:attribute ref="xlink:role" use="optional"/>
+ <xs:attribute ref="xlink:arcrole" use="optional"/>
+ <xs:attribute ref="xlink:title" use="optional"/>
+ <xs:attribute ref="xlink:show" use="optional"/>
+ <xs:attribute ref="xlink:actuate" use="optional"/>
+ </xs:attributeGroup>
+</xs:schema>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema
- targetNamespace="http://www.w3.org/2001/xml-events"
- xmlns:ev="http://www.w3.org/2001/xml-events"
- xmlns:xs="http://www.w3.org/2001/XMLSchema"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.w3.org/2001/XMLSchema
- http://www.w3.org/2001/XMLSchema.xsd"
- elementFormDefault="unqualified"
- blockDefault="#all"
- finalDefault="#all"
- attributeFormDefault="unqualified">
-
- <xs:annotation>
- <xs:documentation>
- This is the XML Schema for XML Events global attributes
-
- URI: http://www.w3.org/MarkUp/SCHEMA/xml-events-attribs-1.xsd
- $Id: xml-events-attribs-1.xsd,v 1.7 2004/11/22 17:09:15 ahby Exp $
- </xs:documentation>
- <xs:documentation source="xml-events-copyright-1.xsd"/>
- </xs:annotation>
-
- <xs:annotation>
- <xs:documentation>
- XML Event Attributes
-
- These "global" event attributes are defined in "Attaching
- Attributes Directly to the Observer Element" of the XML
- Events specification.
- </xs:documentation>
- </xs:annotation>
-
- <xs:attribute name="event" type="xs:NMTOKEN"/>
- <xs:attribute name="observer" type="xs:IDREF"/>
- <xs:attribute name="target" type="xs:IDREF"/>
- <xs:attribute name="handler" type="xs:anyURI"/>
- <xs:attribute name="phase" default="default">
- <xs:simpleType>
- <xs:restriction base="xs:NMTOKEN">
- <xs:enumeration value="capture"/>
- <xs:enumeration value="default"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="propagate" default="continue">
- <xs:simpleType>
- <xs:restriction base="xs:NMTOKEN">
- <xs:enumeration value="stop"/>
- <xs:enumeration value="continue"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
- <xs:attribute name="defaultAction" default="perform">
- <xs:simpleType>
- <xs:restriction base="xs:NMTOKEN">
- <xs:enumeration value="cancel"/>
- <xs:enumeration value="perform"/>
- </xs:restriction>
- </xs:simpleType>
- </xs:attribute>
-
- <xs:attributeGroup name="XmlEvents.attlist">
- <xs:attribute ref="ev:event"/>
- <xs:attribute ref="ev:observer"/>
- <xs:attribute ref="ev:target"/>
- <xs:attribute ref="ev:handler"/>
- <xs:attribute ref="ev:phase"/>
- <xs:attribute ref="ev:propagate"/>
- <xs:attribute ref="ev:defaultAction"/>
- </xs:attributeGroup>
-
-</xs:schema>
import java.util.Iterator;
import java.util.NoSuchElementException;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.Content;
import org.argeo.api.acr.CrName;
import org.argeo.api.acr.spi.ProvidedSession;
if (nextElement == null)
throw new NoSuchElementException();
Content result;
- String isMount = nextElement.getAttributeNS(CrName.CR_NAMESPACE_URI, CrName.mount.qName().getLocalPart());
+ String isMount = nextElement.getAttributeNS(ArgeoNamespace.CR_NAMESPACE_URI, CrName.mount.qName().getLocalPart());
if (isMount.equals("true")) {
result = session.get(parent.getPath() + '/' + nextElement.getTagName());
}
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
// private final static Logger logger = System.getLogger(XmlNormalizer.class.getName());
private DocumentBuilder documentBuilder;
- private Transformer transformer;
+ private TransformerFactory transformerFactory;
+
+ private DOMSource stripSpaceXsl;
public XmlNormalizer() {
this(2);
public XmlNormalizer(int indent) {
try {
documentBuilder = DocumentBuilderFactory.newNSInstance().newDocumentBuilder();
- TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", indent);
try (InputStream in = XmlNormalizer.class.getResourceAsStream("stripSpaces.xsl")) {
- transformer = transformerFactory.newTransformer(new StreamSource(in));
+ DOMResult result = new DOMResult();
+ transformerFactory.newTransformer().transform(new StreamSource(in), result);
+ stripSpaceXsl = new DOMSource(result.getNode());
}
- } catch (TransformerConfigurationException | ParserConfigurationException | TransformerFactoryConfigurationError
+ } catch (ParserConfigurationException | TransformerFactoryConfigurationError | TransformerException
| IOException e) {
throw new IllegalStateException("Cannot initialise document builder and transformer", e);
}
}
}
- public void normalizeAndIndent(InputStream in, OutputStream out) throws IOException {
- normalizeAndIndent(in, out, 2);
+ public void normalizeAndIndent(Source source, Result result) {
+ try {
+ Transformer transformer = transformerFactory.newTransformer(stripSpaceXsl);
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+ // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+
+ transformer.transform(source, result);
+ } catch (TransformerException e) {
+ throw new RuntimeException("Cannot strip space from " + source, e);
+ }
}
- public void normalizeAndIndent(InputStream in, OutputStream out, int indent) throws IOException {
+ public void normalizeAndIndent(InputStream in, OutputStream out) throws IOException {
try {
Document document = documentBuilder.parse(in);
// node.getParentNode().removeChild(node);
// }
- transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
- // transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-
- transformer.transform(new DOMSource(document), new StreamResult(out));
- } catch (DOMException | IllegalArgumentException | SAXException | TransformerFactoryConfigurationError
- | TransformerException e) {
+ normalizeAndIndent(new DOMSource(document), new StreamResult(out));
+ } catch (DOMException | IllegalArgumentException | SAXException | TransformerFactoryConfigurationError e) {
throw new RuntimeException("Cannot normalise and indent XML", e);
}
}
+ public static void print(Source source, int indent) {
+ XmlNormalizer xmlNormalizer = new XmlNormalizer(indent);
+ xmlNormalizer.normalizeAndIndent(source, new StreamResult(System.out));
+ }
+
+ public static void print(Source source) {
+ print(source, 2);
+ }
+
public static void main(String[] args) throws IOException {
Path dir = Paths.get(args[0]);
XmlNormalizer xmlNormalizer = new XmlNormalizer();
import org.argeo.cms.internal.auth.ImpliedByPrincipal;
import org.argeo.cms.internal.auth.RemoteCmsSessionImpl;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.osgi.useradmin.AuthenticatingUser;
+import org.argeo.cms.osgi.useradmin.AuthenticatingUser;
import org.osgi.service.useradmin.Authorization;
/** Centralises security related registrations. */
import javax.xml.namespace.QName;
+import org.argeo.api.acr.ArgeoNamespace;
import org.argeo.api.acr.ContentName;
-import org.argeo.api.acr.CrName;
+import org.argeo.cms.SystemRole;
/** Standard CMS system roles. */
public enum CmsRole implements SystemRole {
userAdmin, //
- groupAdmin;
+ groupAdmin, //
+ //
+ ;
private final static String QUALIFIER = "cms.";
private final ContentName name;
CmsRole() {
- name = new ContentName(CrName.ROLE_NAMESPACE_URI, QUALIFIER + name());
+ name = new ContentName(ArgeoNamespace.ROLE_NAMESPACE_URI, QUALIFIER + name());
}
@Override
- public QName getName() {
+ public QName qName() {
return name;
}
+++ /dev/null
-package org.argeo.cms.auth;
-
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Locale;
-import java.util.Set;
-import java.util.UUID;
-
-import javax.security.auth.Subject;
-import javax.security.auth.x500.X500Principal;
-
-import org.argeo.api.acr.NamespaceUtils;
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.api.cms.CmsSession;
-import org.argeo.api.cms.CmsSessionId;
-import org.argeo.cms.internal.auth.CmsSessionImpl;
-import org.argeo.cms.internal.auth.ImpliedByPrincipal;
-import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.util.CurrentSubject;
-import org.osgi.service.useradmin.Authorization;
-
-/**
- * Programmatic access to the currently authenticated user, within a CMS
- * context.
- */
-public final class CurrentUser {
- /*
- * CURRENT USER API
- */
-
- /**
- * Technical username of the currently authenticated user.
- *
- * @return the authenticated username or null if not authenticated / anonymous
- */
- public static String getUsername() {
- return getUsername(currentSubject());
- }
-
- /**
- * Human readable name of the currently authenticated user (typically first name
- * and last name).
- */
- public static String getDisplayName() {
- return getDisplayName(currentSubject());
- }
-
- /** Whether a user is currently authenticated. */
- public static boolean isAnonymous() {
- return isAnonymous(currentSubject());
- }
-
- /** Locale of the current user */
- public final static Locale locale() {
- return locale(currentSubject());
- }
-
- /** Roles of the currently logged-in user */
- public final static Set<String> roles() {
- return roles(currentSubject());
- }
-
- /** Returns true if the current user is in the specified role */
- public static boolean isInRole(String role) {
- Set<String> roles = roles();
- return roles.contains(role);
- }
-
- /** Implies this {@link SystemRole} in this context. */
- public final static boolean implies(SystemRole role, String context) {
- return role.implied(currentSubject(), context);
- }
-
- /** Implies this {@link SystemRole} in this context. */
- public final static boolean implies(String role, String context) {
- return SystemRole.implied(NamespaceUtils.parsePrefixedName(role), currentSubject(), context);
- }
-
- /** Executes as the current user */
- public final static <T> T doAs(PrivilegedAction<T> action) {
- return Subject.doAs(currentSubject(), action);
- }
-
- /** Executes as the current user */
- public final static <T> T tryAs(PrivilegedExceptionAction<T> action) throws PrivilegedActionException {
- return Subject.doAs(currentSubject(), action);
- }
-
- /*
- * WRAPPERS
- */
-
- public final static String getUsername(Subject subject) {
- if (subject == null)
- throw new IllegalArgumentException("Subject cannot be null");
- if (subject.getPrincipals(X500Principal.class).size() != 1)
- return CmsConstants.ROLE_ANONYMOUS;
- Principal principal = subject.getPrincipals(X500Principal.class).iterator().next();
- return principal.getName();
- }
-
- public final static String getDisplayName(Subject subject) {
- return getAuthorization(subject).toString();
- }
-
- public final static Set<String> roles(Subject subject) {
- Set<String> roles = new HashSet<String>();
- roles.add(getUsername(subject));
- for (Principal group : subject.getPrincipals(ImpliedByPrincipal.class)) {
- roles.add(group.getName());
- }
- return roles;
- }
-
- public final static Locale locale(Subject subject) {
- Set<Locale> locales = subject.getPublicCredentials(Locale.class);
- if (locales.isEmpty()) {
- Locale defaultLocale = CmsContextImpl.getCmsContext().getDefaultLocale();
- return defaultLocale;
- } else
- return locales.iterator().next();
- }
-
- /** Whether this user is currently authenticated. */
- public static boolean isAnonymous(Subject subject) {
- if (subject == null)
- return true;
- String username = getUsername(subject);
- return username == null || username.equalsIgnoreCase(CmsConstants.ROLE_ANONYMOUS);
- }
-
- public static CmsSession getCmsSession() {
- Subject subject = currentSubject();
- Iterator<CmsSessionId> it = subject.getPrivateCredentials(CmsSessionId.class).iterator();
- if (!it.hasNext())
- throw new IllegalStateException("No CMS session id available for " + subject);
- CmsSessionId cmsSessionId = it.next();
- if (it.hasNext())
- throw new IllegalStateException("More than one CMS session id available for " + subject);
- return CmsContextImpl.getCmsContext().getCmsSessionByUuid(cmsSessionId.getUuid());
- }
-
- public static boolean isAvailable() {
- return CurrentSubject.current() != null;
- }
-
- /*
- * HELPERS
- */
- private static Subject currentSubject() {
- Subject subject = CurrentSubject.current();
- if (subject == null)
- throw new IllegalStateException("Cannot find related subject");
- return subject;
- }
-
- private static Authorization getAuthorization(Subject subject) {
- return subject.getPrivateCredentials(Authorization.class).iterator().next();
- }
-
- public static boolean logoutCmsSession(Subject subject) {
- UUID nodeSessionId;
- if (subject.getPrivateCredentials(CmsSessionId.class).size() == 1)
- nodeSessionId = subject.getPrivateCredentials(CmsSessionId.class).iterator().next().getUuid();
- else
- return false;
- CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByUuid(nodeSessionId);
-
- // FIXME logout all views
- // TODO check why it is sometimes null
- if (cmsSession != null)
- cmsSession.close();
- // if (log.isDebugEnabled())
- // log.debug("Logged out CMS session " + cmsSession.getUuid());
- return true;
- }
-
- /** singleton */
- private CurrentUser() {
- }
-}
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
-import org.argeo.cms.security.PBEKeySpecCallback;
-import org.argeo.util.CurrentSubject;
-import org.argeo.util.PasswordEncryption;
+import org.argeo.api.cms.keyring.PBEKeySpecCallback;
+import org.argeo.cms.util.CurrentSubject;
+import org.argeo.cms.util.PasswordEncryption;
/** Adds a secret key to the private credentials */
public class KeyringLoginModule implements LoginModule {
/** Transitional interface to decouple from the Servlet API. */
public interface RemoteAuthResponse {
- void setHeader(String keys, String value);
+ /** Set this header to a single value, possibly removing previous values. */
+ void setHeader(String headerName, String value);
+ /** Add a value to this header. */
+ void addHeader(String headerName, String value);
}
import org.argeo.api.cms.CmsAuth;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsSession;
+import org.argeo.cms.http.HttpHeader;
+import org.argeo.cms.http.HttpStatus;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.util.CurrentSubject;
-import org.argeo.util.http.HttpHeader;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.util.CurrentSubject;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
// response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic
// realm=\"" + httpAuthRealm + "\"");
- if (hasAcceptorCredentials() && !forceBasic && !negotiateFailed)// SPNEGO
- remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getHeaderName(), HttpHeader.NEGOTIATE);
- else
+ if (hasAcceptorCredentials() && !forceBasic && !negotiateFailed) {// SPNEGO
+ remoteAuthResponse.addHeader(HttpHeader.WWW_AUTHENTICATE.getHeaderName(), HttpHeader.NEGOTIATE);
+ // TODO make it configurable ?
+ remoteAuthResponse.addHeader(HttpHeader.WWW_AUTHENTICATE.getHeaderName(),
+ HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + realm + "\"");
+ } else {
remoteAuthResponse.setHeader(HttpHeader.WWW_AUTHENTICATE.getHeaderName(),
HttpHeader.BASIC + " " + HttpHeader.REALM + "=\"" + realm + "\"");
+ }
// response.setDateHeader("Date", System.currentTimeMillis());
// response.setDateHeader("Expires", System.currentTimeMillis() + (24 *
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.CmsDeployProperty;
+import org.argeo.cms.http.HttpHeader;
import org.argeo.cms.internal.auth.CmsSessionImpl;
import org.argeo.cms.internal.runtime.CmsContextImpl;
import org.argeo.cms.internal.runtime.CmsStateImpl;
-import org.argeo.util.http.HttpHeader;
import org.osgi.service.useradmin.Authorization;
-/** Use the HTTP session as the basis for authentication. */
+/** Use a remote session as the basis for authentication. */
public class RemoteSessionLoginModule implements LoginModule {
private final static CmsLog log = CmsLog.getLog(RemoteSessionLoginModule.class);
return false;
// TODO factorize with below
String httpSessionId = httpSession.getId();
-// if (log.isTraceEnabled())
-// log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
if (cmsSession != null && !cmsSession.isAnonymous()) {
authorization = cmsSession.getAuthorization();
authorization = (Authorization) request.getAttribute(RemoteAuthRequest.AUTHORIZATION);
if (authorization == null) {// search by session ID
RemoteAuthSession httpSession = request.getSession();
-// if (httpSession == null) {
-// // TODO make sure this is always safe
-// if (log.isTraceEnabled())
-// log.trace("Create http session");
-// httpSession = request.createSession();
-// }
if (httpSession != null) {
String httpSessionId = httpSession.getId();
-// if (log.isTraceEnabled())
-// log.trace("HTTP login: " + request.getPathInfo() + " #" + httpSessionId);
CmsSessionImpl cmsSession = CmsContextImpl.getCmsContext().getCmsSessionByLocalId(httpSessionId);
if (cmsSession != null && !cmsSession.isAnonymous()) {
authorization = cmsSession.getAuthorization();
}
}
}
-
- // auth token
- // String mail = request.getParameter(LdapAttrs.mail.name());
- // String authPassword = request.getParameter(LdapAttrs.authPassword.name());
- // if (authPassword != null) {
- // sharedState.put(CmsAuthUtils.SHARED_STATE_PWD, authPassword);
- // if (mail != null)
- // sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, mail);
- // }
}
private void extractClientCertificate(RemoteAuthRequest req) {
+++ /dev/null
-package org.argeo.cms.auth;
-
-public class RoleNameUtils {
-
- /*
- * UTILITIES
- */
- public final static String getLastRdnValue(String dn) {
- // we don't use LdapName for portability with Android
- // TODO make it more robust
- String[] parts = dn.split(",");
- String[] rdn = parts[0].split("=");
- return rdn[1];
- }
-
- public final static String getParent(String dn) {
- int index = dn.indexOf(',');
- return dn.substring(index + 1);
- }
-
- /** Up two levels. */
- public final static String getContext(String dn) {
- return getParent(getParent(dn));
- }
-}
import javax.security.auth.spi.LoginModule;
import javax.security.auth.x500.X500Principal;
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.cms.directory.ldap.IpaUtils;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.osgi.useradmin.OsUserUtils;
-import org.argeo.util.directory.ldap.IpaUtils;
-import org.argeo.util.naming.LdapAttrs;
+import org.argeo.cms.osgi.useradmin.OsUserUtils;
import org.osgi.service.useradmin.Authorization;
/** Login module for when the system is owned by a single user. */
throw new LoginException("No username available");
String hostname = CmsContextImpl.getCmsContext().getCmsState().getHostname();
String baseDn = ("." + hostname).replaceAll("\\.", ",dc=");
- X500Principal principal = new X500Principal(LdapAttrs.uid + "=" + username + baseDn);
+ X500Principal principal = new X500Principal(LdapAttr.uid + "=" + username + baseDn);
authorizationName = principal.getName();
}
@Override
public boolean login() throws LoginException {
byte[] spnegoToken = (byte[]) sharedState.get(CmsAuthUtils.SHARED_STATE_SPNEGO_TOKEN);
- if (spnegoToken == null)
+ if (spnegoToken == null) {
+ if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) {
+ // workaround: set shared state name to empty
+ // in order to avoid Krb5LoginModule printing to System.out
+ // TODO ask upstream to only log in debug mode
+ sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, "");
+ }
return false;
+ }
gssContext = checkToken(spnegoToken);
if (gssContext == null)
return false;
+++ /dev/null
-package org.argeo.cms.auth;
-
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.xml.namespace.QName;
-
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.cms.internal.auth.ImpliedByPrincipal;
-
-public interface SystemRole {
- QName getName();
-
- default boolean implied(Subject subject, String context) {
- return implied(getName(), subject, context);
- }
-
- static boolean implied(QName name, Subject subject, String context) {
- Set<ImpliedByPrincipal> roles = subject.getPrincipals(ImpliedByPrincipal.class);
- for (ImpliedByPrincipal role : roles) {
- if (role.isSystemRole()) {
- if (role.getRoleName().equals(name)) {
- // !! if context is not specified, it is considered irrelevant
- if (context == null)
- return true;
- if (role.getContext().equalsIgnoreCase(context)
- || role.getContext().equals(CmsConstants.NODE_BASEDN))
- return true;
- }
- }
- }
- return false;
-
- }
-}
package org.argeo.cms.auth;
-import static org.argeo.util.naming.LdapAttrs.cn;
+import static org.argeo.api.acr.ldap.LdapAttr.cn;
import java.io.IOException;
+import java.security.Principal;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.HashSet;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
+import org.argeo.api.acr.ldap.LdapAttr;
import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.directory.ldap.IpaUtils;
import org.argeo.cms.internal.runtime.CmsContextImpl;
-import org.argeo.osgi.useradmin.AuthenticatingUser;
-import org.argeo.osgi.useradmin.TokenUtils;
-import org.argeo.util.directory.ldap.IpaUtils;
-import org.argeo.util.naming.LdapAttrs;
+import org.argeo.cms.osgi.useradmin.AuthenticatingUser;
+import org.argeo.cms.osgi.useradmin.TokenUtils;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.Group;
import org.osgi.service.useradmin.User;
private CallbackHandler callbackHandler;
private Map<String, Object> sharedState = null;
- private List<String> indexedUserProperties = Arrays.asList(new String[] { LdapAttrs.mail.name(),
- LdapAttrs.uid.name(), LdapAttrs.employeeNumber.name(), LdapAttrs.authPassword.name() });
+ private List<String> indexedUserProperties = Arrays.asList(new String[] { LdapAttr.mail.name(), LdapAttr.uid.name(),
+ LdapAttr.employeeNumber.name(), LdapAttr.authPassword.name() });
// private state
// private BundleContext bc;
return true;// expect Kerberos
if (password != null) {
+ // TODO disabling bind for the time being,
+ // as it requires authorisations to be set at LDAP level
+ boolean tryBind = false;
// try bind first
- try {
- AuthenticatingUser authenticatingUser = new AuthenticatingUser(user.getName(), password);
- bindAuthorization = userAdmin.getAuthorization(authenticatingUser);
- // TODO check tokens as well
- if (bindAuthorization != null) {
- authenticatedUser = user;
- return true;
+ if (tryBind)
+ try {
+ AuthenticatingUser authenticatingUser = new AuthenticatingUser(user.getName(), password);
+ bindAuthorization = userAdmin.getAuthorization(authenticatingUser);
+ // TODO check tokens as well
+ if (bindAuthorization != null) {
+ authenticatedUser = user;
+ return true;
+ }
+ } catch (Exception e) {
+ // silent
+ if (log.isTraceEnabled())
+ log.trace("Bind failed", e);
}
- } catch (Exception e) {
- // silent
- if (log.isTraceEnabled())
- log.trace("Bind failed", e);
- }
// works only if a connection password is provided
if (!user.hasCredential(null, password)) {
// Register CmsSession with initial subject
CmsAuthUtils.registerSessionAuthorization(request, subject, authorization, locale);
- if (log.isDebugEnabled())
- log.debug("Logged in to CMS: " + subject);
+ if (log.isDebugEnabled()) {
+ StringBuilder msg = new StringBuilder();
+ msg.append("Logged in to CMS: " + authorization.getName() + "(" + authorization + ")\n");
+ for (Principal principal : subject.getPrincipals()) {
+ msg.append(" Principal: " + principal.getName()).append(" (")
+ .append(principal.getClass().getSimpleName()).append(")\n");
+ }
+ for (Object credential : subject.getPublicCredentials()) {
+ msg.append(" Public Credential: " + credential).append(" (")
+ .append(credential.getClass().getSimpleName()).append(")\n");
+ }
+ log.debug(msg);
+ }
+// if (log.isTraceEnabled())
+// log.trace(" Subject: " + subject);
return true;
}
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import org.argeo.api.acr.ldap.LdapAttr;
import org.argeo.api.cms.CmsConstants;
-import org.argeo.util.naming.LdapAttrs;
+import org.argeo.cms.CurrentUser;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
// CURRENTUSER HELPERS
/** Checks if current user is the same as the passed one */
public static boolean isCurrentUser(User user) {
- String userUsername = getProperty(user, LdapAttrs.DN);
+ String userUsername = getProperty(user, LdapAttr.DN);
LdapName userLdapName = getLdapName(userUsername);
LdapName selfUserName = getCurrentUserLdapName();
return userLdapName.equals(selfUserName);
/** Retrieves the current logged-in user common name */
public final static String getCommonName(User user) {
- return getProperty(user, LdapAttrs.cn.name());
+ return getProperty(user, LdapAttr.cn.name());
}
// OTHER USERS HELPERS
public static String getUserLocalId(String dn) {
LdapName ldapName = getLdapName(dn);
Rdn last = ldapName.getRdn(ldapName.size() - 1);
- if (last.getType().toLowerCase().equals(LdapAttrs.uid.name())
- || last.getType().toLowerCase().equals(LdapAttrs.cn.name()))
+ if (last.getType().toLowerCase().equals(LdapAttr.uid.name())
+ || last.getType().toLowerCase().equals(LdapAttr.cn.name()))
return (String) last.getValue();
else
throw new IllegalArgumentException("Cannot retrieve user local id, non valid dn: " + dn);
}
public static String getUserDisplayName(Role user) {
- String dName = getProperty(user, LdapAttrs.displayName.name());
+ String dName = getProperty(user, LdapAttr.displayName.name());
if (isEmpty(dName))
- dName = getProperty(user, LdapAttrs.cn.name());
+ dName = getProperty(user, LdapAttr.cn.name());
if (isEmpty(dName))
- dName = getProperty(user, LdapAttrs.uid.name());
+ dName = getProperty(user, LdapAttr.uid.name());
if (isEmpty(dName))
dName = getUserLocalId(user.getName());
return dName;
if (user == null)
return null;
else
- return getProperty(user, LdapAttrs.mail.name());
+ return getProperty(user, LdapAttr.mail.name());
}
// LDAP NAMES HELPERS
}
/**
- * Simply retrieves a LDAP name from a {@link LdapAttrs.DN} with no exception
+ * Simply retrieves a LDAP name from a {@link LdapAttr.DN} with no exception
*/
private static LdapName getLdapName(String dn) {
try {
int i = 0;
loop: while (i < rdns.size()) {
Rdn currrRdn = rdns.get(i);
- if (LdapAttrs.uid.name().equals(currrRdn.getType()) || LdapAttrs.cn.name().equals(currrRdn.getType())
- || LdapAttrs.ou.name().equals(currrRdn.getType()))
+ if (LdapAttr.uid.name().equals(currrRdn.getType()) || LdapAttr.cn.name().equals(currrRdn.getType())
+ || LdapAttr.ou.name().equals(currrRdn.getType()))
break loop;
else {
String currVal = (String) currrRdn.getValue();
--- /dev/null
+package org.argeo.cms.client;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandler;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.net.http.WebSocket;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.argeo.cms.auth.ConsoleCallbackHandler;
+import org.argeo.cms.auth.RemoteAuthUtils;
+import org.argeo.cms.http.HttpHeader;
+
+/** Utility to connect to a remote CMS node. */
+public class CmsClient {
+ public final static String CLIENT_LOGIN_CONTEXT = "CLIENT";
+
+ private URI uri;
+
+ private HttpClient httpClient;
+ private String gssToken;
+
+ public CmsClient(URI uri) {
+ this.uri = uri;
+ }
+
+ public void login() {
+ String server = uri.getHost();
+
+ URL jaasUrl = CmsClient.class.getResource("jaas-client-ipa.cfg");
+ System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
+ try {
+ LoginContext lc = new LoginContext(CLIENT_LOGIN_CONTEXT, new ConsoleCallbackHandler());
+ lc.login();
+ gssToken = RemoteAuthUtils.createGssToken(lc.getSubject(), "HTTP", server);
+ } catch (LoginException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+
+ }
+ }
+
+ public String getAsString() {
+ return getAsString(uri);
+ }
+
+ public String getAsString(URI uri) {
+ uri = normalizeUri(uri);
+ try {
+ HttpClient httpClient = getHttpClient();
+
+ HttpRequest request = HttpRequest.newBuilder().uri(uri) //
+ .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + getGssToken()) //
+ .build();
+ BodyHandler<String> bodyHandler = BodyHandlers.ofString();
+ HttpResponse<String> response = httpClient.send(request, bodyHandler);
+ return response.body();
+// int responseCode = response.statusCode();
+// System.exit(responseCode);
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException("Cannot read " + uri + " as a string", e);
+ }
+ }
+
+ protected URI normalizeUri(URI uri) {
+ if (uri.getHost() != null)
+ return uri;
+ try {
+ String path = uri.getPath();
+ if (path.startsWith("/")) {// absolute
+ return new URI(this.uri.getScheme(), this.uri.getUserInfo(), this.uri.getHost(), this.uri.getPort(),
+ path, uri.getQuery(), uri.getFragment());
+ } else {
+ String thisUriStr = this.uri.toString();
+ if (!thisUriStr.endsWith("/"))
+ thisUriStr = thisUriStr + "/";
+ return URI.create(thisUriStr + path);
+ }
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Cannot interpret " + uri, e);
+ }
+ }
+
+ public URI getUri() {
+ return uri;
+ }
+
+ String getGssToken() {
+ return gssToken;
+ }
+
+ public HttpClient getHttpClient() {
+ if (httpClient == null) {
+ login();
+ HttpClient client = HttpClient.newBuilder() //
+ .sslContext(ipaSslContext()) //
+ .version(HttpClient.Version.HTTP_1_1) //
+ .build();
+ httpClient = client;
+ }
+ return httpClient;
+ }
+
+ public CompletableFuture<WebSocket> newWebSocket(WebSocket.Listener listener) {
+ return newWebSocket(uri, listener);
+ }
+
+ public CompletableFuture<WebSocket> newWebSocket(URI uri, WebSocket.Listener listener) {
+ CompletableFuture<WebSocket> ws = getHttpClient().newWebSocketBuilder()
+ .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + getGssToken())
+ .buildAsync(uri, listener);
+ return ws;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected SSLContext ipaSslContext() {
+ try {
+ final Collection<X509Certificate> certificates;
+ Path caCertificatePath = Paths.get("/etc/ipa/ca.crt");
+ if (Files.exists(caCertificatePath)) {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
+ try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(caCertificatePath))) {
+ certificates = (Collection<X509Certificate>) certificateFactory.generateCertificates(in);
+ }
+ } else {
+ certificates = null;
+ }
+ TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() {
+ public void checkClientTrusted(X509Certificate[] xcs, String string) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] xcs, String string) {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ if (certificates == null)
+ return null;
+ return certificates.toArray(new X509Certificate[certificates.size()]);
+ }
+ } };
+
+ SSLContext sc = SSLContext.getInstance("ssl");
+ sc.init(null, noopTrustManager, null);
+ return sc;
+ } catch (KeyManagementException | NoSuchAlgorithmException | CertificateException | IOException e) {
+ throw new IllegalStateException("Cannot create SSL context ", e);
+ }
+ }
+
+}
+++ /dev/null
-package org.argeo.cms.client;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
-import java.net.http.HttpResponse;
-import java.net.http.HttpResponse.BodyHandler;
-import java.net.http.HttpResponse.BodyHandlers;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.Collection;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-
-import org.argeo.cms.auth.ConsoleCallbackHandler;
-import org.argeo.cms.auth.RemoteAuthUtils;
-import org.argeo.util.http.HttpHeader;
-
-public class SpnegoHttpClient {
- public final static String CLIENT_LOGIN_CONTEXT = "CLIENT";
-
- public static void main(String[] args) throws MalformedURLException {
-// String principal = System.getProperty("javax.security.auth.login.name");
- if (args.length == 0) {
- System.err.println("usage: java -Djavax.security.auth.login.name=<principal@REALM> "
- + SpnegoHttpClient.class.getName() + " <url>");
- System.exit(1);
- return;
- }
- String url = args[0];
- URL u = new URL(url);
- String server = u.getHost();
-
- URL jaasUrl = SpnegoHttpClient.class.getResource("jaas-client-ipa.cfg");
- System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
- try {
- LoginContext lc = new LoginContext(CLIENT_LOGIN_CONTEXT, new ConsoleCallbackHandler());
- lc.login();
-
- HttpClient httpClient = openHttpClient(lc.getSubject());
- String token = RemoteAuthUtils.createGssToken(lc.getSubject(), "HTTP", server);
-
- HttpRequest request = HttpRequest.newBuilder().uri(u.toURI()) //
- .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + token) //
- .build();
- BodyHandler<String> bodyHandler = BodyHandlers.ofString();
- HttpResponse<String> response = httpClient.send(request, bodyHandler);
- System.out.println(response.body());
- int responseCode = response.statusCode();
- System.exit(responseCode);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- static HttpClient openHttpClient(Subject subject) {
- HttpClient client = HttpClient.newBuilder() //
- .sslContext(ipaSslContext()) //
- .version(HttpClient.Version.HTTP_1_1) //
- .build();
-
- return client;
- }
-
- @SuppressWarnings("unchecked")
- static SSLContext ipaSslContext() {
- try {
- final Collection<X509Certificate> certificates;
- Path caCertificatePath = Paths.get("/etc/ipa/ca.crt");
- if (Files.exists(caCertificatePath)) {
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
- try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(caCertificatePath))) {
- certificates = (Collection<X509Certificate>) certificateFactory.generateCertificates(in);
- }
- } else {
- certificates = null;
- }
- TrustManager[] noopTrustManager = new TrustManager[] { new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] xcs, String string) {
- }
-
- public void checkServerTrusted(X509Certificate[] xcs, String string) {
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- if (certificates == null)
- return null;
- return certificates.toArray(new X509Certificate[certificates.size()]);
- }
- } };
-
- SSLContext sc = SSLContext.getInstance("ssl");
- sc.init(null, noopTrustManager, null);
- return sc;
- } catch (KeyManagementException | NoSuchAlgorithmException | CertificateException | IOException e) {
- throw new IllegalStateException("Cannot create SSL context ", e);
- }
- }
-
-}
package org.argeo.cms.client;
import java.net.URI;
-import java.net.URL;
-import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.nio.ByteBuffer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
-
-import javax.security.auth.login.LoginContext;
-
-import org.argeo.cms.auth.RemoteAuthUtils;
-import org.argeo.util.http.HttpHeader;
+import java.util.concurrent.ExecutionException;
/** Tests connectivity to the web socket server. */
-public class WebSocketEventClient {
+public class WebSocketEventClient implements Runnable {
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- System.err.println("usage: java " + WebSocketEventClient.class.getName() + " <url>");
- System.exit(1);
- return;
- }
- URI uri = URI.create(args[0]);
- WebSocket.Listener listener = new WebSocket.Listener() {
+ private final URI uri;
- public CompletionStage<?> onText(WebSocket webSocket, CharSequence message, boolean last) {
- System.out.println(message);
- CompletionStage<String> res = CompletableFuture.completedStage(message.toString());
- return res;
- }
+ private WebSocket webSocket;
- @Override
- public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
- // System.out.println("Pong received.");
- return null;
- }
-
- };
+ private CmsClient cmsClient;
- // SPNEGO
- URL jaasUrl = SpnegoHttpClient.class.getResource("jaas-client-ipa.cfg");
- System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm());
- LoginContext lc = new LoginContext(SpnegoHttpClient.CLIENT_LOGIN_CONTEXT);
- lc.login();
- String token = RemoteAuthUtils.createGssToken(lc.getSubject(), "HTTP", uri.getHost());
+ public WebSocketEventClient(URI uri) {
+ this.uri = uri;
+ cmsClient = new CmsClient(uri);
+ }
- HttpClient client = SpnegoHttpClient.openHttpClient(lc.getSubject());
- CompletableFuture<WebSocket> ws = client.newWebSocketBuilder()
- .header(HttpHeader.AUTHORIZATION.getHeaderName(), HttpHeader.NEGOTIATE + " " + token)
- .buildAsync(uri, listener);
+ @Override
+ public void run() {
+ try {
+ CompletableFuture<WebSocket> ws = cmsClient.newWebSocket(new WsEventListener());
- WebSocket webSocket = ws.get();
- webSocket.request(Long.MAX_VALUE);
+ WebSocket webSocket = ws.get();
+ webSocket.request(Long.MAX_VALUE);
- Runtime.getRuntime().addShutdownHook(new Thread(() -> webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "")));
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "")));
- while (!webSocket.isInputClosed()) {
- webSocket.sendPing(ByteBuffer.allocate(0));
- Thread.sleep(10000);
+ while (!webSocket.isInputClosed()) {
+ webSocket.sendPing(ByteBuffer.allocate(0));
+ Thread.sleep(10000);
+ }
+ } catch (InterruptedException e) {
+ if (webSocket != null)
+ webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "");
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Cannot listent to " + uri, e.getCause());
}
}
+ private class WsEventListener implements WebSocket.Listener {
+ public CompletionStage<?> onText(WebSocket webSocket, CharSequence message, boolean last) {
+ System.out.println(message);
+ CompletionStage<String> res = CompletableFuture.completedStage(message.toString());
+ return res;
+ }
+
+ @Override
+ public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
+ // System.out.println("Pong received.");
+ return null;
+ }
+
+ }
}
--- /dev/null
+package org.argeo.cms.client;
+
+import java.math.RoundingMode;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.WebSocket;
+import java.nio.ByteBuffer;
+import java.text.DecimalFormat;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.ExecutionException;
+
+/** Tests connectivity to the web socket server. */
+public class WebSocketPing implements Runnable {
+ private final static int PING_FRAME_SIZE = 125;
+ private final static DecimalFormat decimalFormat = new DecimalFormat("0.0");
+ static {
+ decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
+ }
+
+ private final URI uri;
+ private final UUID uuid;
+
+ private WebSocket webSocket;
+
+ public WebSocketPing(URI uri) {
+ this.uri = uri;
+ this.uuid = UUID.randomUUID();
+ }
+
+ @Override
+ public void run() {
+ try {
+ WebSocket.Listener listener = new WebSocket.Listener() {
+
+ @Override
+ public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
+ long msb = message.getLong();
+ long lsb = message.getLong();
+ long end = System.nanoTime();
+ if (msb != uuid.getMostSignificantBits() || lsb != uuid.getLeastSignificantBits())
+ return null; // ignore
+ long begin = message.getLong();
+ double durationNs = end - begin;
+ double durationMs = durationNs / 1000000;
+ int size = message.remaining() + (3 * Long.BYTES);
+ System.out.println(
+ size + " bytes from " + uri + ": time=" + decimalFormat.format(durationMs) + " ms");
+ return null;
+ }
+
+ };
+
+ HttpClient client = HttpClient.newHttpClient();
+ CompletableFuture<WebSocket> ws = client.newWebSocketBuilder().buildAsync(uri, listener);
+ webSocket = ws.get();
+ webSocket.request(Long.MAX_VALUE);
+
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "")));
+
+ while (!webSocket.isInputClosed()) {
+ long begin = System.nanoTime();
+ ByteBuffer buffer = ByteBuffer.allocate(PING_FRAME_SIZE);
+ buffer.putLong(uuid.getMostSignificantBits());
+ buffer.putLong(uuid.getLeastSignificantBits());
+ buffer.putLong(begin);
+ buffer.flip();
+ webSocket.sendPing(buffer);
+ Thread.sleep(1000);
+ }
+ } catch (InterruptedException e) {
+ if (webSocket != null)
+ webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "");
+ } catch (ExecutionException e) {
+ throw new RuntimeException("Cannot ping " + uri, e.getCause());
+ }
+ }
+
+// public static void main(String[] args) throws Exception {
+// if (args.length == 0) {
+// System.err.println("usage: java " + WsPing.class.getName() + " <url>");
+// System.exit(1);
+// return;
+// }
+// URI uri = URI.create(args[0]);
+// new WsPing(uri).run();
+// }
+
+}
+++ /dev/null
-package org.argeo.cms.client;
-
-import java.math.RoundingMode;
-import java.net.URI;
-import java.net.http.HttpClient;
-import java.net.http.WebSocket;
-import java.nio.ByteBuffer;
-import java.text.DecimalFormat;
-import java.util.UUID;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.ExecutionException;
-
-/** Tests connectivity to the web socket server. */
-public class WsPing implements Runnable {
- private final static int PING_FRAME_SIZE = 125;
-
- private final URI uri;
- private final UUID uuid;
-
- private final DecimalFormat decimalFormat;
-
- public WsPing(URI uri) {
- this.uri = uri;
- this.uuid = UUID.randomUUID();
- decimalFormat = new DecimalFormat("0.0");
- decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
- }
-
- @Override
- public void run() {
- try {
- WebSocket.Listener listener = new WebSocket.Listener() {
-
- @Override
- public CompletionStage<?> onPong(WebSocket webSocket, ByteBuffer message) {
- long msb = message.getLong();
- long lsb = message.getLong();
- long end = System.nanoTime();
- if (msb != uuid.getMostSignificantBits() || lsb != uuid.getLeastSignificantBits())
- return null; // ignore
- long begin = message.getLong();
- double durationNs = end - begin;
- double durationMs = durationNs / 1000000;
- int size = message.remaining() + (3 * Long.BYTES);
- System.out.println(
- size + " bytes from " + uri + ": time=" + decimalFormat.format(durationMs) + " ms");
- return null;
- }
-
- };
-
- HttpClient client = HttpClient.newHttpClient();
- CompletableFuture<WebSocket> ws = client.newWebSocketBuilder().buildAsync(uri, listener);
- WebSocket webSocket = ws.get();
- webSocket.request(Long.MAX_VALUE);
-
- Runtime.getRuntime().addShutdownHook(new Thread(() -> webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "")));
-
- while (!webSocket.isInputClosed()) {
- long begin = System.nanoTime();
- ByteBuffer buffer = ByteBuffer.allocate(PING_FRAME_SIZE);
- buffer.putLong(uuid.getMostSignificantBits());
- buffer.putLong(uuid.getLeastSignificantBits());
- buffer.putLong(begin);
- buffer.flip();
- webSocket.sendPing(buffer);
- Thread.sleep(1000);
- }
- } catch (InterruptedException | ExecutionException e) {
- e.printStackTrace();
- }
- }
-
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- System.err.println("usage: java " + WsPing.class.getName() + " <url>");
- System.exit(1);
- return;
- }
- URI uri = URI.create(args[0]);
- new WsPing(uri).run();
- }
-
-}
CLIENT {
com.sun.security.auth.module.Krb5LoginModule required
- useTicketCache=true;
+ useTicketCache=true;
};
import javax.xml.namespace.QName;
-import org.argeo.util.http.HttpHeader;
-import org.argeo.util.http.HttpMethod;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpHeader;
+import org.argeo.cms.http.HttpMethod;
+import org.argeo.cms.http.HttpStatus;
public class DavClient {
package org.argeo.cms.dav;
-import org.argeo.util.http.HttpHeader;
+import org.argeo.cms.http.HttpHeader;
import com.sun.net.httpserver.HttpExchange;
import javax.xml.namespace.NamespaceContext;
import org.argeo.api.acr.ContentNotFoundException;
-import org.argeo.util.http.HttpHeader;
-import org.argeo.util.http.HttpMethod;
-import org.argeo.util.http.HttpStatus;
-import org.argeo.util.http.HttpServerUtils;
+import org.argeo.cms.http.HttpHeader;
+import org.argeo.cms.http.HttpMethod;
+import org.argeo.cms.http.HttpStatus;
+import org.argeo.cms.http.server.HttpServerUtils;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import javax.xml.namespace.QName;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpStatus;
/** The WebDav response for a given resource. */
public class DavResponse {
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpStatus;
/**
* Asynchronously iterate over the response statuses of the response to a
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.http.HttpStatus;
class MultiStatusWriter implements Consumer<DavResponse> {
private BlockingQueue<DavResponse> queue = new ArrayBlockingQueue<>(64);
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import static org.argeo.cms.directory.ldap.LdapNameUtils.toLdapName;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.StringJoiner;
+
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.transaction.xa.XAResource;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.acr.ldap.LdapObj;
+import org.argeo.api.cms.directory.CmsDirectory;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.transaction.WorkControl;
+import org.argeo.api.cms.transaction.WorkingCopyXaResource;
+import org.argeo.api.cms.transaction.XAResourceProvider;
+import org.argeo.cms.osgi.useradmin.OsUserDirectory;
+import org.argeo.cms.runtime.DirectoryConf;
+
+/** A {@link CmsDirectory} based either on LDAP or LDIF. */
+public abstract class AbstractLdapDirectory implements CmsDirectory, XAResourceProvider {
+ protected static final String SHARED_STATE_USERNAME = "javax.security.auth.login.name";
+ protected static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password";
+
+ private final LdapName baseDn;
+ private final Hashtable<String, Object> configProperties;
+ private final Rdn userBaseRdn, groupBaseRdn, systemRoleBaseRdn;
+ private final String userObjectClass, groupObjectClass;
+ private String memberAttributeId = "member";
+
+ private final boolean readOnly;
+ private final boolean disabled;
+ private final String uri;
+
+ private String forcedPassword;
+
+ private final boolean scoped;
+
+ private List<String> credentialAttributeIds = Arrays
+ .asList(new String[] { LdapAttr.userPassword.name(), LdapAttr.authPassword.name() });
+
+ private WorkControl transactionControl;
+ private WorkingCopyXaResource<LdapEntryWorkingCopy> xaResource;
+
+ private LdapDirectoryDao directoryDao;
+
+ /** Whether the the directory has is authenticated via a service user. */
+ private boolean authenticated = false;
+
+ public AbstractLdapDirectory(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
+ this.configProperties = new Hashtable<String, Object>();
+ for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ configProperties.put(key, props.get(key));
+ }
+
+ String baseDnStr = DirectoryConf.baseDn.getValue(configProperties);
+ if (baseDnStr == null)
+ throw new IllegalArgumentException("Base DN must be specified: " + configProperties);
+ baseDn = toLdapName(baseDnStr);
+ this.scoped = scoped;
+
+ if (uriArg != null) {
+ uri = uriArg.toString();
+ // uri from properties is ignored
+ } else {
+ String uriStr = DirectoryConf.uri.getValue(configProperties);
+ if (uriStr == null)
+ uri = null;
+ else
+ uri = uriStr;
+ }
+
+ forcedPassword = DirectoryConf.forcedPassword.getValue(configProperties);
+
+ userObjectClass = DirectoryConf.userObjectClass.getValue(configProperties);
+ groupObjectClass = DirectoryConf.groupObjectClass.getValue(configProperties);
+
+ String userBase = DirectoryConf.userBase.getValue(configProperties);
+ String groupBase = DirectoryConf.groupBase.getValue(configProperties);
+ String systemRoleBase = DirectoryConf.systemRoleBase.getValue(configProperties);
+ try {
+// baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties));
+ userBaseRdn = new Rdn(userBase);
+// userBaseDn = new LdapName(userBase + "," + baseDn);
+ groupBaseRdn = new Rdn(groupBase);
+// groupBaseDn = new LdapName(groupBase + "," + baseDn);
+ systemRoleBaseRdn = new Rdn(systemRoleBase);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException(
+ "Badly formated base DN " + DirectoryConf.baseDn.getValue(configProperties), e);
+ }
+
+ // read only
+ String readOnlyStr = DirectoryConf.readOnly.getValue(configProperties);
+ if (readOnlyStr == null) {
+ readOnly = readOnlyDefault(uri);
+ configProperties.put(DirectoryConf.readOnly.name(), Boolean.toString(readOnly));
+ } else
+ readOnly = Boolean.parseBoolean(readOnlyStr);
+
+ // disabled
+ String disabledStr = DirectoryConf.disabled.getValue(configProperties);
+ if (disabledStr != null)
+ disabled = Boolean.parseBoolean(disabledStr);
+ else
+ disabled = false;
+ if (!getRealm().isEmpty()) {
+ // IPA multiple LDAP causes URI parsing to fail
+ // TODO manage generic redundant LDAP case
+ directoryDao = new LdapDao(this);
+ } else {
+ if (uri != null) {
+ URI u = URI.create(uri);
+ if (DirectoryConf.SCHEME_LDAP.equals(u.getScheme())
+ || DirectoryConf.SCHEME_LDAPS.equals(u.getScheme())) {
+ directoryDao = new LdapDao(this);
+ authenticated = configProperties.get(Context.SECURITY_PRINCIPAL) != null;
+ } else if (DirectoryConf.SCHEME_FILE.equals(u.getScheme())) {
+ directoryDao = new LdifDao(this);
+ authenticated = true;
+ } else if (DirectoryConf.SCHEME_OS.equals(u.getScheme())) {
+ directoryDao = new OsUserDirectory(this);
+ authenticated = true;
+ // singleUser = true;
+ } else {
+ throw new IllegalArgumentException("Unsupported scheme " + u.getScheme());
+ }
+ } else {
+ // in memory
+ directoryDao = new LdifDao(this);
+ }
+ }
+ if (directoryDao != null)
+ xaResource = new WorkingCopyXaResource<>(directoryDao);
+ }
+
+ /*
+ * INITIALISATION
+ */
+
+ public void init() {
+ getDirectoryDao().init();
+ }
+
+ public void destroy() {
+ getDirectoryDao().destroy();
+ }
+
+ /*
+ * CREATION
+ */
+ protected abstract LdapEntry newUser(LdapName name);
+
+ protected abstract LdapEntry newGroup(LdapName name);
+
+ /*
+ * EDITION
+ */
+
+ public boolean isEditing() {
+ return xaResource.wc() != null;
+ }
+
+ public LdapEntryWorkingCopy getWorkingCopy() {
+ LdapEntryWorkingCopy wc = xaResource.wc();
+ if (wc == null)
+ return null;
+ return wc;
+ }
+
+ public void checkEdit() {
+ if (xaResource.wc() == null) {
+ try {
+ transactionControl.getWorkContext().registerXAResource(xaResource, null);
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot enlist " + xaResource, e);
+ }
+ } else {
+ }
+ }
+
+ public void setTransactionControl(WorkControl transactionControl) {
+ this.transactionControl = transactionControl;
+ }
+
+ public XAResource getXaResource() {
+ return xaResource;
+ }
+
+ public boolean removeEntry(LdapName dn) {
+ checkEdit();
+ LdapEntryWorkingCopy wc = getWorkingCopy();
+ boolean actuallyDeleted;
+ if (getDirectoryDao().entryExists(dn) || wc.getNewData().containsKey(dn)) {
+ LdapEntry user = doGetRole(dn);
+ wc.getDeletedData().put(dn, user);
+ actuallyDeleted = true;
+ } else {// just removing from groups (e.g. system roles)
+ actuallyDeleted = false;
+ }
+ for (LdapName groupDn : getDirectoryDao().getDirectGroups(dn)) {
+ LdapEntry group = doGetRole(groupDn);
+ group.getAttributes().get(getMemberAttributeId()).remove(dn.toString());
+ }
+ return actuallyDeleted;
+ }
+
+ /*
+ * RETRIEVAL
+ */
+
+ protected LdapEntry doGetRole(LdapName dn) {
+ LdapEntryWorkingCopy wc = getWorkingCopy();
+ LdapEntry user;
+ try {
+ user = getDirectoryDao().doGetEntry(dn);
+ } catch (NameNotFoundException e) {
+ user = null;
+ }
+ if (wc != null) {
+ if (user == null && wc.getNewData().containsKey(dn))
+ user = wc.getNewData().get(dn);
+ else if (wc.getDeletedData().containsKey(dn))
+ user = null;
+ }
+ return user;
+ }
+
+ protected void collectGroups(LdapEntry user, List<LdapEntry> allRoles) {
+ Attributes attrs = user.getAttributes();
+ // TODO centralize attribute name
+ Attribute memberOf = attrs.get(LdapAttr.memberOf.name());
+ // if user belongs to this directory, we only check memberOf
+ if (memberOf != null && user.getDn().startsWith(getBaseDn())) {
+ try {
+ NamingEnumeration<?> values = memberOf.getAll();
+ while (values.hasMore()) {
+ Object value = values.next();
+ LdapName groupDn = new LdapName(value.toString());
+ LdapEntry group = doGetRole(groupDn);
+ if (group != null) {
+ allRoles.add(group);
+ } else {
+ // user doesn't have the right to retrieve role, but we know it exists
+ // otherwise memberOf would not work
+ group = newGroup(groupDn);
+ allRoles.add(group);
+ }
+ }
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get memberOf groups for " + user, e);
+ }
+ } else {
+ directGroups: for (LdapName groupDn : getDirectoryDao().getDirectGroups(user.getDn())) {
+ LdapEntry group = doGetRole(groupDn);
+ if (group != null) {
+ if (allRoles.contains(group)) {
+ // important in order to avoi loops
+ continue directGroups;
+ }
+ allRoles.add(group);
+ collectGroups(group, allRoles);
+ }
+ }
+ }
+ }
+
+ /*
+ * HIERARCHY
+ */
+ @Override
+ public HierarchyUnit getHierarchyUnit(String path) {
+ LdapName dn = pathToName(path);
+ return directoryDao.doGetHierarchyUnit(dn);
+ }
+
+ @Override
+ public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
+ return directoryDao.doGetDirectHierarchyUnits(baseDn, functionalOnly);
+ }
+
+ @Override
+ public HierarchyUnit getDirectChild(Type type) {
+ // TODO factorise with hierarchy unit?
+ return switch (type) {
+ case ROLES -> getDirectoryDao().doGetHierarchyUnit((LdapName) getBaseDn().add(getSystemRoleBaseRdn()));
+ case PEOPLE -> getDirectoryDao().doGetHierarchyUnit((LdapName) getBaseDn().add(getUserBaseRdn()));
+ case GROUPS -> getDirectoryDao().doGetHierarchyUnit((LdapName) getBaseDn().add(getGroupBaseRdn()));
+ case FUNCTIONAL -> throw new IllegalArgumentException("Type must be a technical type");
+ };
+ }
+
+ @Override
+ public String getHierarchyUnitName() {
+ return getName();
+ }
+
+ @Override
+ public String getHierarchyUnitLabel(Locale locale) {
+ String key = LdapNameUtils.getLastRdn(getBaseDn()).getType();
+ Object value = LdapEntry.getLocalized(asLdapEntry().getProperties(), key, locale);
+ if (value == null)
+ value = getHierarchyUnitName();
+ assert value != null;
+ return value.toString();
+ }
+
+ @Override
+ public HierarchyUnit getParent() {
+ return null;
+ }
+
+ @Override
+ public boolean isType(Type type) {
+ return Type.FUNCTIONAL.equals(type);
+ }
+
+ @Override
+ public CmsDirectory getDirectory() {
+ return this;
+ }
+
+ @Override
+ public HierarchyUnit createHierarchyUnit(String path) {
+ checkEdit();
+ LdapEntryWorkingCopy wc = getWorkingCopy();
+ LdapName dn = pathToName(path);
+ if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
+ || wc.getNewData().containsKey(dn))
+ throw new IllegalArgumentException("Already a hierarchy unit " + path);
+ BasicAttributes attrs = new BasicAttributes(true);
+ attrs.put(LdapAttr.objectClass.name(), LdapObj.organizationalUnit.name());
+ Rdn nameRdn = dn.getRdn(dn.size() - 1);
+ // TODO deal with multiple attr RDN
+ attrs.put(nameRdn.getType(), nameRdn.getValue());
+ wc.getModifiedData().put(dn, attrs);
+ LdapHierarchyUnit newHierarchyUnit = new LdapHierarchyUnit(this, dn);
+ wc.getNewData().put(dn, newHierarchyUnit);
+ return newHierarchyUnit;
+ }
+
+ /*
+ * PATHS
+ */
+
+ @Override
+ public String getBase() {
+ return getBaseDn().toString();
+ }
+
+ @Override
+ public String getName() {
+ return nameToSimple(getBaseDn(), ".");
+ }
+
+ protected String nameToRelativePath(LdapName dn) {
+ LdapName name = LdapNameUtils.relativeName(getBaseDn(), dn);
+ return nameToSimple(name, "/");
+ }
+
+ protected String nameToSimple(LdapName name, String separator) {
+ StringJoiner path = new StringJoiner(separator);
+ for (int i = 0; i < name.size(); i++) {
+ path.add(name.getRdn(i).getValue().toString());
+ }
+ return path.toString();
+
+ }
+
+ protected LdapName pathToName(String path) {
+ try {
+ LdapName name = (LdapName) getBaseDn().clone();
+ String[] segments = path.split("/");
+ Rdn parentRdn = null;
+ // segments[0] is the directory itself
+ for (int i = 0; i < segments.length; i++) {
+ String segment = segments[i];
+ // TODO make attr names configurable ?
+ String attr = getDirectory().getRealm().isPresent()/* IPA */ ? LdapAttr.cn.name() : LdapAttr.ou.name();
+ if (parentRdn != null) {
+ if (getUserBaseRdn().equals(parentRdn))
+ attr = LdapAttr.uid.name();
+ else if (getGroupBaseRdn().equals(parentRdn))
+ attr = LdapAttr.cn.name();
+ else if (getSystemRoleBaseRdn().equals(parentRdn))
+ attr = LdapAttr.cn.name();
+ }
+ Rdn rdn = new Rdn(attr, segment);
+ name.add(rdn);
+ parentRdn = rdn;
+ }
+ return name;
+ } catch (InvalidNameException e) {
+ throw new IllegalStateException("Cannot convert " + path + " to LDAP name", e);
+ }
+
+ }
+
+ /*
+ * UTILITIES
+ */
+ protected boolean isExternal(LdapName name) {
+ return !name.startsWith(baseDn);
+ }
+
+ protected static boolean hasObjectClass(Attributes attrs, LdapObj objectClass) {
+ return hasObjectClass(attrs, objectClass.name());
+ }
+
+ protected static boolean hasObjectClass(Attributes attrs, String objectClass) {
+ try {
+ Attribute attr = attrs.get(LdapAttr.objectClass.name());
+ NamingEnumeration<?> en = attr.getAll();
+ while (en.hasMore()) {
+ String v = en.next().toString();
+ if (v.equalsIgnoreCase(objectClass))
+ return true;
+
+ }
+ return false;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot search for objectClass " + objectClass, e);
+ }
+ }
+
+ private static boolean readOnlyDefault(String uriStr) {
+ if (uriStr == null)
+ return true;
+ /// TODO make it more generic
+ URI uri;
+ try {
+ uri = new URI(uriStr.split(" ")[0]);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ if (uri.getScheme() == null)
+ return false;// assume relative file to be writable
+ if (uri.getScheme().equals(DirectoryConf.SCHEME_FILE)) {
+ File file = new File(uri);
+ if (file.exists())
+ return !file.canWrite();
+ else
+ return !file.getParentFile().canWrite();
+ } else if (uri.getScheme().equals(DirectoryConf.SCHEME_LDAP)) {
+ if (uri.getAuthority() != null)// assume writable if authenticated
+ return false;
+ } else if (uri.getScheme().equals(DirectoryConf.SCHEME_OS)) {
+ return true;
+ }
+ return true;// read only by default
+ }
+
+ /*
+ * AS AN ENTRY
+ */
+ public LdapEntry asLdapEntry() {
+ try {
+ return directoryDao.doGetEntry(baseDn);
+ } catch (NameNotFoundException e) {
+ throw new IllegalStateException("Cannot get " + baseDn + " entry", e);
+ }
+ }
+
+ public Dictionary<String, Object> getProperties() {
+ return asLdapEntry().getProperties();
+ }
+
+ /*
+ * ACCESSORS
+ */
+ @Override
+ public Optional<String> getRealm() {
+ Object realm = configProperties.get(DirectoryConf.realm.name());
+ if (realm == null)
+ return Optional.empty();
+ return Optional.of(realm.toString());
+ }
+
+ public LdapName getBaseDn() {
+ return (LdapName) baseDn.clone();
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ public boolean isDisabled() {
+ return disabled;
+ }
+
+ public boolean isAuthenticated() {
+ return authenticated;
+ }
+
+ public Rdn getUserBaseRdn() {
+ return userBaseRdn;
+ }
+
+ public Rdn getGroupBaseRdn() {
+ return groupBaseRdn;
+ }
+
+ public Rdn getSystemRoleBaseRdn() {
+ return systemRoleBaseRdn;
+ }
+
+// public Dictionary<String, Object> getConfigProperties() {
+// return configProperties;
+// }
+
+ public Dictionary<String, Object> cloneConfigProperties() {
+ return new Hashtable<>(configProperties);
+ }
+
+ public String getForcedPassword() {
+ return forcedPassword;
+ }
+
+ public boolean isScoped() {
+ return scoped;
+ }
+
+ public List<String> getCredentialAttributeIds() {
+ return credentialAttributeIds;
+ }
+
+ public String getUri() {
+ return uri;
+ }
+
+ public LdapDirectoryDao getDirectoryDao() {
+ return directoryDao;
+ }
+
+ /** dn can be null, in that case a default should be returned. */
+ public String getUserObjectClass() {
+ return userObjectClass;
+ }
+
+ public String getGroupObjectClass() {
+ return groupObjectClass;
+ }
+
+ public String getMemberAttributeId() {
+ return memberAttributeId;
+ }
+
+ /*
+ * OBJECT METHODS
+ */
+
+ @Override
+ public int hashCode() {
+ return baseDn.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Directory " + baseDn.toString();
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import javax.naming.ldap.LdapName;
+
+/** Base class for LDAP/LDIF directory DAOs. */
+public abstract class AbstractLdapDirectoryDao implements LdapDirectoryDao {
+
+ private AbstractLdapDirectory directory;
+
+ public AbstractLdapDirectoryDao(AbstractLdapDirectory directory) {
+ this.directory = directory;
+ }
+
+ public AbstractLdapDirectory getDirectory() {
+ return directory;
+ }
+
+ @Override
+ public LdapEntryWorkingCopy newWorkingCopy() {
+ return new LdapEntryWorkingCopy();
+ }
+
+ @Override
+ public LdapEntry newUser(LdapName name) {
+ return getDirectory().newUser(name);
+ }
+
+ @Override
+ public LdapEntry newGroup(LdapName name) {
+ return getDirectory().newGroup(name);
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+
+public class AttributesDictionary extends Dictionary<String, Object> {
+ private final Attributes attributes;
+
+ /** The provided attributes is wrapped, not copied. */
+ public AttributesDictionary(Attributes attributes) {
+ if (attributes == null)
+ throw new IllegalArgumentException("Attributes cannot be null");
+ this.attributes = attributes;
+ }
+
+ @Override
+ public int size() {
+ return attributes.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return attributes.size() == 0;
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ NamingEnumeration<String> namingEnumeration = attributes.getIDs();
+ return new Enumeration<String>() {
+
+ @Override
+ public boolean hasMoreElements() {
+ return namingEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public String nextElement() {
+ return namingEnumeration.nextElement();
+ }
+
+ };
+ }
+
+ @Override
+ public Enumeration<Object> elements() {
+ NamingEnumeration<String> namingEnumeration = attributes.getIDs();
+ return new Enumeration<Object>() {
+
+ @Override
+ public boolean hasMoreElements() {
+ return namingEnumeration.hasMoreElements();
+ }
+
+ @Override
+ public Object nextElement() {
+ String key = namingEnumeration.nextElement();
+ return get(key);
+ }
+
+ };
+ }
+
+ @Override
+ /** @returns a <code>String</code> or <code>String[]</code> */
+ public Object get(Object key) {
+ try {
+ if (key == null)
+ throw new IllegalArgumentException("Key cannot be null");
+ Attribute attr = attributes.get(key.toString());
+ if (attr == null)
+ return null;
+ if (attr.size() == 0)
+ throw new IllegalStateException("There must be at least one value");
+ else if (attr.size() == 1) {
+ return attr.get().toString();
+ } else {// multiple
+ String[] res = new String[attr.size()];
+ for (int i = 0; i < attr.size(); i++) {
+ Object value = attr.get();
+ if (value == null)
+ throw new RuntimeException("Values cannot be null");
+ res[i] = attr.get(i).toString();
+ }
+ return res;
+ }
+ } catch (NamingException e) {
+ throw new RuntimeException("Cannot get value for " + key, e);
+ }
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ if (key == null)
+ throw new IllegalArgumentException("Key cannot be null");
+ if (value == null)
+ throw new IllegalArgumentException("Value cannot be null");
+
+ Object oldValue = get(key);
+ Attribute attr = attributes.get(key);
+ if (attr == null) {
+ attr = new BasicAttribute(key);
+ attributes.put(attr);
+ }
+
+ if (value instanceof String[]) {
+ String[] values = (String[]) value;
+ // clean additional values
+ for (int i = values.length; i < attr.size(); i++)
+ attr.remove(i);
+ // set values
+ for (int i = 0; i < values.length; i++) {
+ attr.set(i, values[i]);
+ }
+ } else {
+ if (attr.size() > 1)
+ throw new IllegalArgumentException("Attribute " + key + " is multi-valued");
+ if (attr.size() == 1) {
+ try {
+ if (!attr.get(0).equals(value))
+ attr.set(0, value.toString());
+ } catch (NamingException e) {
+ throw new RuntimeException("Cannot check existing value", e);
+ }
+ } else {
+ attr.add(value.toString());
+ }
+ }
+ return oldValue;
+ }
+
+ @Override
+ public Object remove(Object key) {
+ if (key == null)
+ throw new IllegalArgumentException("Key cannot be null");
+ Object oldValue = get(key);
+ if (oldValue == null)
+ return null;
+ return attributes.remove(key.toString());
+ }
+
+ /**
+ * Copy the <b>content</b> of an {@link Attributes} to the provided
+ * {@link Dictionary}.
+ */
+ public static void copy(Attributes attributes, Dictionary<String, Object> dictionary) {
+ AttributesDictionary ad = new AttributesDictionary(attributes);
+ Enumeration<String> keys = ad.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ dictionary.put(key, ad.get(key));
+ }
+ }
+
+ /**
+ * Copy a {@link Dictionary} into an {@link Attributes}.
+ */
+ public static void copy(Dictionary<String, Object> dictionary, Attributes attributes) {
+ AttributesDictionary ad = new AttributesDictionary(attributes);
+ Enumeration<String> keys = dictionary.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ ad.put(key, dictionary.get(key));
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.StringTokenizer;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+
+/** LDAP authPassword field according to RFC 3112 */
+public class AuthPassword implements CallbackHandler {
+ private final String authScheme;
+ private final String authInfo;
+ private final String authValue;
+
+ public AuthPassword(String value) {
+ StringTokenizer st = new StringTokenizer(value, "$");
+ // TODO make it more robust, deal with bad formatting
+ this.authScheme = st.nextToken().trim();
+ this.authInfo = st.nextToken().trim();
+ this.authValue = st.nextToken().trim();
+
+ String expectedAuthScheme = getExpectedAuthScheme();
+ if (expectedAuthScheme != null && !authScheme.equals(expectedAuthScheme))
+ throw new IllegalArgumentException(
+ "Auth scheme " + authScheme + " is not compatible with " + expectedAuthScheme);
+ }
+
+ protected AuthPassword(String authInfo, String authValue) {
+ this.authScheme = getExpectedAuthScheme();
+ if (authScheme == null)
+ throw new IllegalArgumentException("Expected auth scheme cannot be null");
+ this.authInfo = authInfo;
+ this.authValue = authValue;
+ }
+
+ protected AuthPassword(AuthPassword authPassword) {
+ this.authScheme = authPassword.getAuthScheme();
+ this.authInfo = authPassword.getAuthInfo();
+ this.authValue = authPassword.getAuthValue();
+ }
+
+ protected String getExpectedAuthScheme() {
+ return null;
+ }
+
+ protected boolean matchAuthValue(Object object) {
+ return authValue.equals(object.toString());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AuthPassword))
+ return false;
+ AuthPassword authPassword = (AuthPassword) obj;
+ return authScheme.equals(authPassword.authScheme) && authInfo.equals(authPassword.authInfo)
+ && authValue.equals(authValue);
+ }
+
+ public boolean keyEquals(AuthPassword authPassword) {
+ return authScheme.equals(authPassword.authScheme) && authInfo.equals(authPassword.authInfo);
+ }
+
+ @Override
+ public int hashCode() {
+ return authValue.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return toAuthPassword();
+ }
+
+ public final String toAuthPassword() {
+ return getAuthScheme() + '$' + authInfo + '$' + authValue;
+ }
+
+ public String getAuthScheme() {
+ return authScheme;
+ }
+
+ public String getAuthInfo() {
+ return authInfo;
+ }
+
+ public String getAuthValue() {
+ return authValue;
+ }
+
+ public static AuthPassword matchAuthValue(Attributes attributes, char[] value) {
+ try {
+ Attribute authPassword = attributes.get(LdapAttr.authPassword.name());
+ if (authPassword != null) {
+ NamingEnumeration<?> values = authPassword.getAll();
+ while (values.hasMore()) {
+ Object val = values.next();
+ AuthPassword token = new AuthPassword(val.toString());
+ String auth;
+ if (Arrays.binarySearch(value, '$') >= 0) {
+ auth = token.authInfo + '$' + token.authValue;
+ } else {
+ auth = token.authValue;
+ }
+ if (Arrays.equals(auth.toCharArray(), value))
+ return token;
+ // if (token.matchAuthValue(value))
+ // return token;
+ }
+ }
+ return null;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot check attribute", e);
+ }
+ }
+
+ public static boolean remove(Attributes attributes, AuthPassword value) {
+ Attribute authPassword = attributes.get(LdapAttr.authPassword.name());
+ return authPassword.remove(value.toAuthPassword());
+ }
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback)
+ ((NameCallback) callback).setName(toAuthPassword());
+ else if (callback instanceof PasswordCallback)
+ ((PasswordCallback) callback).setPassword(getAuthValue().toCharArray());
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import static java.nio.charset.StandardCharsets.US_ASCII;
+
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.acr.ldap.LdapObj;
+import org.argeo.api.cms.directory.DirectoryDigestUtils;
+
+/** An entry in an LDAP (or LDIF) directory. */
+public class DefaultLdapEntry implements LdapEntry {
+ private final AbstractLdapDirectory directory;
+
+ private final LdapName dn;
+
+ private AttributeDictionary properties;
+ private AttributeDictionary credentials;
+
+// private String primaryObjectClass;
+// private List<String> objectClasses = new ArrayList<>();
+
+ protected DefaultLdapEntry(AbstractLdapDirectory directory, LdapName dn) {
+ Objects.requireNonNull(directory);
+ Objects.requireNonNull(dn);
+ this.directory = directory;
+ this.dn = dn;
+
+ // Object classes
+// Objects.requireNonNull(initialAttributes);
+// try {
+// NamingEnumeration<?> en = initialAttributes.get(LdapAttrs.objectClass.name()).getAll();
+// String first = null;
+// attrs: while (en.hasMore()) {
+// String v = en.next().toString();
+// if (v.equalsIgnoreCase(LdapObjs.top.name()))
+// continue attrs;
+// if (first == null)
+// first = v;
+// if (v.equalsIgnoreCase(getDirectory().getUserObjectClass()))
+// primaryObjectClass = getDirectory().getUserObjectClass();
+// else if (v.equalsIgnoreCase(getDirectory().getGroupObjectClass()))
+// primaryObjectClass = getDirectory().getGroupObjectClass();
+// objectClasses.add(v);
+// }
+// if (primaryObjectClass == null) {
+// if (first == null)
+// throw new IllegalStateException("Could not find primary object class");
+// primaryObjectClass = first;
+// }
+// } catch (NamingException e) {
+// throw new IllegalStateException("Cannot find object classes", e);
+// }
+
+ }
+
+ @Override
+ public LdapName getDn() {
+ // always return a copy since LdapName is mutable
+ return (LdapName) dn.clone();
+ }
+
+ public synchronized Attributes getAttributes() {
+ return isEditing() ? getModifiedAttributes() : getDirectory().getDirectoryDao().doGetAttributes(dn);
+ }
+
+ @Override
+ public List<LdapName> getReferences(String attributeId) {
+ Attribute memberAttribute = getAttributes().get(attributeId);
+ if (memberAttribute == null)
+ return new ArrayList<LdapName>();
+ try {
+ List<LdapName> roles = new ArrayList<LdapName>();
+ NamingEnumeration<?> values = memberAttribute.getAll();
+ while (values.hasMore()) {
+ LdapName dn = new LdapName(values.next().toString());
+ roles.add(dn);
+ }
+ return roles;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get members", e);
+ }
+
+ }
+
+ /** Should only be called from working copy thread. */
+ protected synchronized Attributes getModifiedAttributes() {
+ assert getWc() != null;
+ return getWc().getModifiedData().get(getDn());
+ }
+
+ protected synchronized boolean isEditing() {
+ return getWc() != null && getModifiedAttributes() != null;
+ }
+
+ private synchronized LdapEntryWorkingCopy getWc() {
+ return directory.getWorkingCopy();
+ }
+
+ protected synchronized void startEditing() {
+// if (frozen)
+// throw new IllegalStateException("Cannot edit frozen view");
+ if (directory.isReadOnly())
+ throw new IllegalStateException("User directory is read-only");
+ assert getModifiedAttributes() == null;
+ getWc().startEditing(this);
+ // modifiedAttributes = (Attributes) publishedAttributes.clone();
+ }
+
+ public synchronized void publishAttributes(Attributes modifiedAttributes) {
+// publishedAttributes = modifiedAttributes;
+ }
+
+ /*
+ * PROPERTIES
+ */
+ @Override
+ public Dictionary<String, Object> getProperties() {
+ if (properties == null)
+ properties = new AttributeDictionary(false);
+ return properties;
+ }
+
+ public Dictionary<String, Object> getCredentials() {
+ if (credentials == null)
+ credentials = new AttributeDictionary(true);
+ return credentials;
+ }
+
+ /*
+ * CREDENTIALS
+ */
+ @Override
+ public boolean hasCredential(String key, Object value) {
+ if (key == null) {
+ // TODO check other sources (like PKCS12)
+ // String pwd = new String((char[]) value);
+ // authPassword (RFC 312 https://tools.ietf.org/html/rfc3112)
+ char[] password = DirectoryDigestUtils.bytesToChars(value);
+
+ if (getDirectory().getForcedPassword() != null
+ && getDirectory().getForcedPassword().equals(new String(password)))
+ return true;
+
+ AuthPassword authPassword = AuthPassword.matchAuthValue(getAttributes(), password);
+ if (authPassword != null) {
+ if (authPassword.getAuthScheme().equals(SharedSecret.X_SHARED_SECRET)) {
+ SharedSecret onceToken = new SharedSecret(authPassword);
+ if (onceToken.isExpired()) {
+ // AuthPassword.remove(getAttributes(), onceToken);
+ return false;
+ } else {
+ // boolean wasRemoved = AuthPassword.remove(getAttributes(), onceToken);
+ return true;
+ }
+ // TODO delete expired tokens?
+ } else {
+ // TODO implement SHA
+ throw new UnsupportedOperationException(
+ "Unsupported authPassword scheme " + authPassword.getAuthScheme());
+ }
+ }
+
+ // Regular password
+// byte[] hashedPassword = hash(password, DigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256);
+ if (hasCredential(LdapAttr.userPassword.name(), DirectoryDigestUtils.charsToBytes(password)))
+ return true;
+ return false;
+ }
+
+ Object storedValue = getCredentials().get(key);
+ if (storedValue == null || value == null)
+ return false;
+ if (!(value instanceof String || value instanceof byte[]))
+ return false;
+ if (storedValue instanceof String && value instanceof String)
+ return storedValue.equals(value);
+ if (storedValue instanceof byte[] && value instanceof byte[]) {
+ String storedBase64 = new String((byte[]) storedValue, US_ASCII);
+ String passwordScheme = null;
+ if (storedBase64.charAt(0) == '{') {
+ int index = storedBase64.indexOf('}');
+ if (index > 0) {
+ passwordScheme = storedBase64.substring(1, index);
+ String storedValueBase64 = storedBase64.substring(index + 1);
+ byte[] storedValueBytes = Base64.getDecoder().decode(storedValueBase64);
+ char[] passwordValue = DirectoryDigestUtils.bytesToChars((byte[]) value);
+ byte[] valueBytes;
+ if (DirectoryDigestUtils.PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
+ valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, null, null,
+ null);
+ } else if (DirectoryDigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
+ // see https://www.thesubtlety.com/post/a-389-ds-pbkdf2-password-checker/
+ byte[] iterationsArr = Arrays.copyOfRange(storedValueBytes, 0, 4);
+ BigInteger iterations = new BigInteger(iterationsArr);
+ byte[] salt = Arrays.copyOfRange(storedValueBytes, iterationsArr.length,
+ iterationsArr.length + 64);
+ byte[] keyArr = Arrays.copyOfRange(storedValueBytes, iterationsArr.length + salt.length,
+ storedValueBytes.length);
+ int keyLengthBits = keyArr.length * 8;
+ valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, salt,
+ iterations.intValue(), keyLengthBits);
+ } else {
+ throw new UnsupportedOperationException("Unknown password scheme " + passwordScheme);
+ }
+ return Arrays.equals(storedValueBytes, valueBytes);
+ }
+ }
+ }
+// if (storedValue instanceof byte[] && value instanceof byte[]) {
+// return Arrays.equals((byte[]) storedValue, (byte[]) value);
+// }
+ return false;
+ }
+
+ /** Hash the password */
+ private static byte[] sha1hash(char[] password) {
+ byte[] hashedPassword = ("{SHA}" + Base64.getEncoder()
+ .encodeToString(DirectoryDigestUtils.sha1(DirectoryDigestUtils.charsToBytes(password))))
+ .getBytes(StandardCharsets.UTF_8);
+ return hashedPassword;
+ }
+
+ public AbstractLdapDirectory getDirectory() {
+ return directory;
+ }
+
+ public LdapDirectoryDao getDirectoryDao() {
+ return directory.getDirectoryDao();
+ }
+
+ @Override
+ public int hashCode() {
+ return dn.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj instanceof LdapEntry) {
+ LdapEntry that = (LdapEntry) obj;
+ return this.dn.equals(that.getDn());
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return dn.toString();
+ }
+
+ private static boolean isAsciiPrintable(String str) {
+ if (str == null) {
+ return false;
+ }
+ int sz = str.length();
+ for (int i = 0; i < sz; i++) {
+ if (isAsciiPrintable(str.charAt(i)) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static boolean isAsciiPrintable(char ch) {
+ return ch >= 32 && ch < 127;
+ }
+
+ protected class AttributeDictionary extends Dictionary<String, Object> {
+ private final List<String> effectiveKeys = new ArrayList<String>();
+ private final List<String> attrFilter;
+ private final Boolean includeFilter;
+
+ public AttributeDictionary(Boolean credentials) {
+ this.attrFilter = getDirectory().getCredentialAttributeIds();
+ this.includeFilter = credentials;
+ try {
+ NamingEnumeration<String> ids = getAttributes().getIDs();
+ while (ids.hasMore()) {
+ String id = ids.next();
+ if (credentials && attrFilter.contains(id))
+ effectiveKeys.add(id);
+ else if (!credentials && !attrFilter.contains(id))
+ effectiveKeys.add(id);
+ }
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot initialise attribute dictionary", e);
+ }
+ if (!credentials)
+ effectiveKeys.add(LdapAttr.objectClasses.name());
+ }
+
+ @Override
+ public int size() {
+ return effectiveKeys.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return effectiveKeys.size() == 0;
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ return Collections.enumeration(effectiveKeys);
+ }
+
+ @Override
+ public Enumeration<Object> elements() {
+ final Iterator<String> it = effectiveKeys.iterator();
+ return new Enumeration<Object>() {
+
+ @Override
+ public boolean hasMoreElements() {
+ return it.hasNext();
+ }
+
+ @Override
+ public Object nextElement() {
+ String key = it.next();
+ return get(key);
+ }
+
+ };
+ }
+
+ @Override
+ public Object get(Object key) {
+ try {
+ Attribute attr = !key.equals(LdapAttr.objectClasses.name()) ? getAttributes().get(key.toString())
+ : getAttributes().get(LdapAttr.objectClass.name());
+ if (attr == null)
+ return null;
+ Object value = attr.get();
+ if (value instanceof byte[]) {
+ if (key.equals(LdapAttr.userPassword.name()))
+ // TODO other cases (certificates, images)
+ return value;
+ value = new String((byte[]) value, StandardCharsets.UTF_8);
+ }
+ if (attr.size() == 1)
+ return value;
+ // special case for object class
+ if (key.equals(LdapAttr.objectClass.name())) {
+ // TODO support multiple object classes
+ NamingEnumeration<?> en = attr.getAll();
+ String first = null;
+ attrs: while (en.hasMore()) {
+ String v = en.next().toString();
+ if (v.equalsIgnoreCase(LdapObj.top.name()))
+ continue attrs;
+ if (first == null)
+ first = v;
+ if (v.equalsIgnoreCase(getDirectory().getUserObjectClass()))
+ return getDirectory().getUserObjectClass();
+ else if (v.equalsIgnoreCase(getDirectory().getGroupObjectClass()))
+ return getDirectory().getGroupObjectClass();
+ }
+ if (first != null)
+ return first;
+ throw new IllegalStateException("Cannot find objectClass in " + value);
+ } else {
+ NamingEnumeration<?> en = attr.getAll();
+ StringJoiner values = new StringJoiner("\n");
+ while (en.hasMore()) {
+ String v = en.next().toString();
+ values.add(v);
+ }
+ return values.toString();
+ }
+// else
+// return value;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get value for attribute " + key, e);
+ }
+ }
+
+ @Override
+ public Object put(String key, Object value) {
+ Objects.requireNonNull(value, "Value for key " + key + " is null");
+ try {
+ if (key == null) {
+ // FIXME remove this "feature", a key should be specified
+ // TODO persist to other sources (like PKCS12)
+ char[] password = DirectoryDigestUtils.bytesToChars(value);
+ byte[] hashedPassword = sha1hash(password);
+ return put(LdapAttr.userPassword.name(), hashedPassword);
+ }
+ if (key.startsWith("X-")) {
+ return put(LdapAttr.authPassword.name(), value);
+ }
+
+ // start editing
+ getDirectory().checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ // object classes special case.
+ if (key.equals(LdapAttr.objectClasses.name())) {
+ Attribute attribute = new BasicAttribute(LdapAttr.objectClass.name());
+ String[] objectClasses = value.toString().split("\n");
+ for (String objectClass : objectClasses) {
+ if (objectClass.trim().equals(""))
+ continue;
+ attribute.add(objectClass);
+ }
+ Attribute previousAttribute = getModifiedAttributes().put(attribute);
+ if (previousAttribute != null)
+ return previousAttribute.get();
+ else
+ return null;
+ }
+
+ if (!(value instanceof String || value instanceof byte[]))
+ throw new IllegalArgumentException("Value must be String or byte[]");
+
+ if (includeFilter && !attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " not included");
+ else if (!includeFilter && attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " excluded");
+
+ Attribute attribute = getModifiedAttributes().get(key.toString());
+ // if (attribute == null) // block unit tests
+ attribute = new BasicAttribute(key.toString());
+ if (value instanceof String && !isAsciiPrintable(((String) value)))
+ attribute.add(((String) value).getBytes(StandardCharsets.UTF_8));
+ else
+ attribute.add(value);
+ Attribute previousAttribute = getModifiedAttributes().put(attribute);
+ if (previousAttribute != null)
+ return previousAttribute.get();
+ else
+ return null;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get value for attribute " + key, e);
+ }
+ }
+
+ @Override
+ public Object remove(Object key) {
+ getDirectory().checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ if (includeFilter && !attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " not included");
+ else if (!includeFilter && attrFilter.contains(key))
+ throw new IllegalArgumentException("Key " + key + " excluded");
+
+ try {
+ Attribute attr = getModifiedAttributes().remove(key.toString());
+ if (attr != null)
+ return attr.get();
+ else
+ return null;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot remove attribute " + key, e);
+ }
+ }
+
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.StringJoiner;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.cms.dns.DnsBrowser;
+import org.argeo.cms.runtime.DirectoryConf;
+
+/** Free IPA specific conventions. */
+public class IpaUtils {
+ public final static String IPA_USER_BASE = "cn=users";
+ public final static String IPA_GROUP_BASE = "cn=groups";
+ public final static String IPA_ROLE_BASE = "cn=roles";
+ public final static String IPA_SERVICE_BASE = "cn=services";
+
+ public final static String IPA_ACCOUNTS_BASE = "cn=accounts";
+
+ private final static String KRB_PRINCIPAL_NAME = LdapAttr.krbPrincipalName.name().toLowerCase();
+
+ public final static String IPA_USER_DIRECTORY_CONFIG = DirectoryConf.userBase + "=" + IPA_USER_BASE + "&"
+ + DirectoryConf.groupBase + "=" + IPA_GROUP_BASE + "&" + DirectoryConf.systemRoleBase + "=" + IPA_ROLE_BASE
+ + "&" + DirectoryConf.readOnly + "=true";
+
+ @Deprecated
+ static String domainToUserDirectoryConfigPath(String realm) {
+ return domainToBaseDn(realm) + "?" + IPA_USER_DIRECTORY_CONFIG + "&" + DirectoryConf.realm.name() + "=" + realm;
+ }
+
+ public static void addIpaConfig(String realm, Dictionary<String, Object> properties) {
+ properties.put(DirectoryConf.baseDn.name(), domainToBaseDn(realm));
+ properties.put(DirectoryConf.realm.name(), realm);
+ properties.put(DirectoryConf.userBase.name(), IPA_USER_BASE);
+ properties.put(DirectoryConf.groupBase.name(), IPA_GROUP_BASE);
+ properties.put(DirectoryConf.systemRoleBase.name(), IPA_ROLE_BASE);
+ properties.put(DirectoryConf.readOnly.name(), Boolean.TRUE.toString());
+ }
+
+ public static String domainToBaseDn(String domain) {
+ String[] dcs = domain.split("\\.");
+ StringJoiner sj = new StringJoiner(",");
+ for (int i = 0; i < dcs.length; i++) {
+ String dc = dcs[i];
+ sj.add(LdapAttr.dc.name() + '=' + dc.toLowerCase());
+ }
+ return IPA_ACCOUNTS_BASE + ',' + sj.toString();
+ }
+
+ public static LdapName kerberosToDn(String kerberosName) {
+ String[] kname = kerberosName.split("@");
+ String username = kname[0];
+ String baseDn = domainToBaseDn(kname[1]);
+ String dn;
+ if (!username.contains("/"))
+ dn = LdapAttr.uid + "=" + username + "," + IPA_USER_BASE + "," + baseDn;
+ else
+ dn = KRB_PRINCIPAL_NAME + "=" + kerberosName + "," + IPA_SERVICE_BASE + "," + baseDn;
+ try {
+ return new LdapName(dn);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Badly formatted name for " + kerberosName + ": " + dn);
+ }
+ }
+
+ private IpaUtils() {
+
+ }
+
+ public static String kerberosDomainFromDns() {
+ String kerberosDomain;
+ try (DnsBrowser dnsBrowser = new DnsBrowser()) {
+ // TODO retrieve hostname from CMS config
+ InetAddress localhost = InetAddress.getLocalHost();
+ String hostname = localhost.getHostName();
+ int dotIndex = hostname.indexOf('.');
+ if (dotIndex <= 0) {
+ hostname = localhost.getCanonicalHostName();
+ dotIndex = hostname.indexOf('.');
+ if (dotIndex <= 0)
+ throw new IllegalArgumentException(
+ "Cannot extract DNS zone from hostname " + hostname + " (" + localhost + ")");
+ }
+ String dnsZone = hostname.substring(dotIndex + 1);
+ kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT");
+ return kerberosDomain;
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot determine Kerberos domain from DNS", e);
+ }
+
+ }
+
+ public static Dictionary<String, Object> convertIpaUri(URI uri) {
+ String path = uri.getPath();
+ String kerberosRealm;
+ if (path == null || path.length() <= 1) {
+ kerberosRealm = kerberosDomainFromDns();
+ } else {
+ kerberosRealm = path.substring(1);
+ }
+
+ if (kerberosRealm == null)
+ throw new IllegalStateException("No Kerberos domain available for " + uri);
+ // TODO intergrate CA certificate in truststore
+ // String schemeToUse = SCHEME_LDAPS;
+ String schemeToUse = DirectoryConf.SCHEME_LDAP;
+ List<String> ldapHosts;
+ String ldapHostsStr = uri.getHost();
+ if (ldapHostsStr == null || ldapHostsStr.trim().equals("")) {
+ try (DnsBrowser dnsBrowser = new DnsBrowser()) {
+ ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase(),
+ schemeToUse.equals(DirectoryConf.SCHEME_LDAP) ? true : false);
+ if (ldapHosts == null || ldapHosts.size() == 0) {
+ throw new IllegalStateException("Cannot configure LDAP for IPA " + uri);
+ } else {
+ ldapHostsStr = ldapHosts.get(0);
+ }
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
+ }
+ } else {
+ ldapHosts = new ArrayList<>();
+ ldapHosts.add(ldapHostsStr);
+ }
+
+ StringBuilder uriStr = new StringBuilder();
+ try {
+ for (String host : ldapHosts) {
+ URI convertedUri = new URI(schemeToUse + "://" + host + "/");
+ uriStr.append(convertedUri).append(' ');
+ }
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
+ }
+
+ Hashtable<String, Object> res = new Hashtable<>();
+ res.put(DirectoryConf.uri.name(), uriStr.toString());
+ addIpaConfig(kerberosRealm, res);
+ return res;
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.cms.transaction.WorkingCopy;
+
+/** A synchronized wrapper for a single {@link InitialLdapContext}. */
+// TODO implement multiple contexts and connection pooling.
+public class LdapConnection {
+ private InitialLdapContext initialLdapContext = null;
+
+ public LdapConnection(String url, Dictionary<String, ?> properties) {
+ try {
+ Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
+ connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ connEnv.put(Context.PROVIDER_URL, url);
+ connEnv.put("java.naming.ldap.attributes.binary", LdapAttr.userPassword.name());
+ // use pooling in order to avoid connection timeout
+// connEnv.put("com.sun.jndi.ldap.connect.pool", "true");
+// connEnv.put("com.sun.jndi.ldap.connect.pool.timeout", 300000);
+
+ initialLdapContext = new InitialLdapContext(connEnv, null);
+ // StartTlsResponse tls = (StartTlsResponse) ctx
+ // .extendedOperation(new StartTlsRequest());
+ // tls.negotiate();
+ Object securityAuthentication = properties.get(Context.SECURITY_AUTHENTICATION);
+ if (securityAuthentication != null)
+ initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, securityAuthentication);
+ else
+ initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
+ Object principal = properties.get(Context.SECURITY_PRINCIPAL);
+ if (principal != null) {
+ initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString());
+ Object creds = properties.get(Context.SECURITY_CREDENTIALS);
+ if (creds != null) {
+ initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
+ }
+ }
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot connect to LDAP", e);
+ }
+
+ }
+
+ public void init() {
+
+ }
+
+ public void destroy() {
+ try {
+ // tls.close();
+ initialLdapContext.close();
+ initialLdapContext = null;
+ } catch (NamingException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected InitialLdapContext getLdapContext() {
+ return initialLdapContext;
+ }
+
+ protected void reconnect() throws NamingException {
+ initialLdapContext.reconnect(initialLdapContext.getConnectControls());
+ }
+
+ public synchronized NamingEnumeration<SearchResult> search(LdapName searchBase, String searchFilter,
+ SearchControls searchControls) throws NamingException {
+ NamingEnumeration<SearchResult> results;
+ try {
+ results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ } catch (CommunicationException e) {
+ reconnect();
+ results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ }
+ return results;
+ }
+
+ public synchronized Attributes getAttributes(LdapName name) throws NamingException {
+ try {
+ return getLdapContext().getAttributes(name);
+ } catch (CommunicationException e) {
+ reconnect();
+ return getLdapContext().getAttributes(name);
+ }
+ }
+
+ public synchronized boolean entryExists(LdapName name) throws NamingException {
+ String[] noAttrOID = new String[] { "1.1" };
+ try {
+ getLdapContext().getAttributes(name, noAttrOID);
+ return true;
+ } catch (CommunicationException e) {
+ reconnect();
+ getLdapContext().getAttributes(name, noAttrOID);
+ return true;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public synchronized void prepareChanges(WorkingCopy<?, ?, LdapName> wc) throws NamingException {
+ // make sure connection will work
+ reconnect();
+
+ // delete
+ for (LdapName dn : wc.getDeletedData().keySet()) {
+ if (!entryExists(dn))
+ throw new IllegalStateException("User to delete no found " + dn);
+ }
+ // add
+ for (LdapName dn : wc.getNewData().keySet()) {
+ if (entryExists(dn))
+ throw new IllegalStateException("User to create found " + dn);
+ }
+ // modify
+ for (LdapName dn : wc.getModifiedData().keySet()) {
+ if (!wc.getNewData().containsKey(dn) && !entryExists(dn))
+ throw new IllegalStateException("User to modify not found " + dn);
+ }
+
+ }
+
+// protected boolean entryExists(LdapName dn) throws NamingException {
+// try {
+// return getAttributes(dn).size() != 0;
+// } catch (NameNotFoundException e) {
+// return false;
+// }
+// }
+
+ public synchronized void commitChanges(LdapEntryWorkingCopy wc) throws NamingException {
+ // delete
+ for (LdapName dn : wc.getDeletedData().keySet()) {
+ getLdapContext().destroySubcontext(dn);
+ }
+ // add
+ for (LdapName dn : wc.getNewData().keySet()) {
+ LdapEntry user = wc.getNewData().get(dn);
+ getLdapContext().createSubcontext(dn, user.getAttributes());
+ }
+ // modify
+ for (LdapName dn : wc.getModifiedData().keySet()) {
+ Attributes modifiedAttrs = wc.getModifiedData().get(dn);
+ getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import static org.argeo.api.acr.ldap.LdapAttr.objectClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.AuthenticationNotSupportedException;
+import javax.naming.Binding;
+import javax.naming.InvalidNameException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.acr.ldap.LdapObj;
+import org.argeo.api.cms.directory.HierarchyUnit;
+
+/** A user admin based on a LDAP server. */
+public class LdapDao extends AbstractLdapDirectoryDao {
+ private LdapConnection ldapConnection;
+
+ public LdapDao(AbstractLdapDirectory directory) {
+ super(directory);
+ }
+
+ @Override
+ public void init() {
+ ldapConnection = new LdapConnection(getDirectory().getUri().toString(), getDirectory().cloneConfigProperties());
+ }
+
+ public void destroy() {
+ ldapConnection.destroy();
+ }
+
+ @Override
+ public boolean checkConnection() {
+ try {
+ return ldapConnection.entryExists(getDirectory().getBaseDn());
+ } catch (NamingException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean entryExists(LdapName dn) {
+ try {
+ return ldapConnection.entryExists(dn);
+ } catch (NameNotFoundException e) {
+ return false;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot check " + dn, e);
+ }
+ }
+
+ @Override
+ public LdapEntry doGetEntry(LdapName name) throws NameNotFoundException {
+// if (!entryExists(name))
+// throw new NameNotFoundException(name + " was not found in " + getDirectory().getBaseDn());
+ try {
+ Attributes attrs = ldapConnection.getAttributes(name);
+
+ LdapEntry res;
+ Rdn technicalRdn = LdapNameUtils.getParentRdn(name);
+ if (getDirectory().getGroupBaseRdn().equals(technicalRdn)) {
+ if (attrs.size() == 0) {// exists but not accessible
+ attrs = new BasicAttributes();
+ attrs.put(LdapAttr.objectClass.name(), LdapObj.top.name());
+ attrs.put(LdapAttr.objectClass.name(), getDirectory().getGroupObjectClass());
+ }
+ res = newGroup(name);
+ } else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn)) {
+ if (attrs.size() == 0) {// exists but not accessible
+ attrs = new BasicAttributes();
+ attrs.put(LdapAttr.objectClass.name(), LdapObj.top.name());
+ attrs.put(LdapAttr.objectClass.name(), getDirectory().getGroupObjectClass());
+ }
+ res = newGroup(name);
+ } else if (getDirectory().getUserBaseRdn().equals(technicalRdn)) {
+ if (attrs.size() == 0) {// exists but not accessible
+ attrs = new BasicAttributes();
+ attrs.put(LdapAttr.objectClass.name(), LdapObj.top.name());
+ attrs.put(LdapAttr.objectClass.name(), getDirectory().getUserObjectClass());
+ }
+ res = newUser(name);
+ } else {
+ res = new DefaultLdapEntry(getDirectory(), name);
+ }
+ return res;
+ } catch (NameNotFoundException e) {
+ throw e;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot retrieve entry " + name, e);
+ }
+ }
+
+ @Override
+ public Attributes doGetAttributes(LdapName name) {
+ try {
+ Attributes attrs = ldapConnection.getAttributes(name);
+ return attrs;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get attributes for " + name);
+ }
+ }
+
+ @Override
+ public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
+ ArrayList<LdapEntry> res = new ArrayList<>();
+ try {
+ String searchFilter = f != null ? f.toString()
+ : "(|(" + objectClass.name() + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass.name()
+ + "=" + getDirectory().getGroupObjectClass() + "))";
+ SearchControls searchControls = new SearchControls();
+ // only attribute needed is objectClass
+ searchControls.setReturningAttributes(new String[] { objectClass.name() });
+ // FIXME make one level consistent with deep
+ searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
+
+ // LdapName searchBase = getBaseDn();
+ NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
+
+ results: while (results.hasMoreElements()) {
+ SearchResult searchResult = results.next();
+ Attributes attrs = searchResult.getAttributes();
+ Attribute objectClassAttr = attrs.get(objectClass.name());
+ LdapName dn = toDn(searchBase, searchResult);
+ LdapEntry role;
+ if (objectClassAttr.contains(getDirectory().getGroupObjectClass())
+ || objectClassAttr.contains(getDirectory().getGroupObjectClass().toLowerCase()))
+ role = newGroup(dn);
+ else if (objectClassAttr.contains(getDirectory().getUserObjectClass())
+ || objectClassAttr.contains(getDirectory().getUserObjectClass().toLowerCase()))
+ role = newUser(dn);
+ else {
+// log.warn("Unsupported LDAP type for " + searchResult.getName());
+ continue results;
+ }
+ res.add(role);
+ }
+ return res;
+ } catch (AuthenticationNotSupportedException e) {
+ // ignore (typically an unsupported anonymous bind)
+ // TODO better logging
+ return res;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get roles for filter " + f, e);
+ }
+ }
+
+ private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException {
+ return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName());
+ }
+
+ @Override
+ public List<LdapName> getDirectGroups(LdapName dn) {
+ List<LdapName> directGroups = new ArrayList<LdapName>();
+ try {
+ String searchFilter = "(&(" + objectClass + "=" + getDirectory().getGroupObjectClass() + ")("
+ + getDirectory().getMemberAttributeId() + "=" + dn + "))";
+
+ SearchControls searchControls = new SearchControls();
+ searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+
+ LdapName searchBase = getDirectory().getBaseDn();
+ NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
+
+ while (results.hasMoreElements()) {
+ SearchResult searchResult = (SearchResult) results.nextElement();
+ directGroups.add(toDn(searchBase, searchResult));
+ }
+ return directGroups;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot populate direct members of " + dn, e);
+ }
+ }
+
+ @Override
+ public void prepare(LdapEntryWorkingCopy wc) {
+ try {
+ ldapConnection.prepareChanges(wc);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot prepare LDAP", e);
+ }
+ }
+
+ @Override
+ public void commit(LdapEntryWorkingCopy wc) {
+ try {
+ ldapConnection.commitChanges(wc);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot commit LDAP", e);
+ }
+ }
+
+ @Override
+ public void rollback(LdapEntryWorkingCopy wc) {
+ // prepare not impacting
+ }
+
+ /*
+ * HIERARCHY
+ */
+
+ @Override
+ public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+ List<HierarchyUnit> res = new ArrayList<>();
+ try {
+ String structuralFilter = functionalOnly ? ""
+ : "(" + getDirectory().getUserBaseRdn() + ")(" + getDirectory().getGroupBaseRdn() + ")("
+ + getDirectory().getSystemRoleBaseRdn() + ")";
+ String searchFilter = "(|(" + objectClass + "=" + LdapObj.organizationalUnit.name() + ")(" + objectClass
+ + "=" + LdapObj.organization.name() + ")" + structuralFilter + ")";
+
+ SearchControls searchControls = new SearchControls();
+ searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+ // no attributes needed
+ searchControls.setReturningAttributes(new String[0]);
+
+ NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
+
+ while (results.hasMoreElements()) {
+ SearchResult searchResult = (SearchResult) results.nextElement();
+ LdapName dn = toDn(searchBase, searchResult);
+// Attributes attrs = searchResult.getAttributes();
+ LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn);
+ if (functionalOnly) {
+ if (hierarchyUnit.isFunctional())
+ res.add(hierarchyUnit);
+ } else {
+ res.add(hierarchyUnit);
+ }
+ }
+ return res;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get direct hierarchy units ", e);
+ }
+ }
+
+ @Override
+ public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
+ try {
+ if (getDirectory().getBaseDn().equals(dn))
+ return getDirectory();
+ if (!dn.startsWith(getDirectory().getBaseDn()))
+ throw new IllegalArgumentException(dn + " does not start with base DN " + getDirectory().getBaseDn());
+ if (!ldapConnection.entryExists(dn))
+ return null;
+ return new LdapHierarchyUnit(getDirectory(), dn);
+ } catch (NameNotFoundException e) {
+ return null;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.util.List;
+
+import javax.naming.NameNotFoundException;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.transaction.WorkingCopyProcessor;
+
+/** Low-level access to an LDAP/LDIF directory. */
+public interface LdapDirectoryDao extends WorkingCopyProcessor<LdapEntryWorkingCopy> {
+ boolean checkConnection();
+
+ boolean entryExists(LdapName dn);
+
+ LdapEntry doGetEntry(LdapName name) throws NameNotFoundException;
+
+ Attributes doGetAttributes(LdapName name);
+
+ List<LdapEntry> doGetEntries(LdapName searchBase, String filter, boolean deep);
+
+ List<LdapName> getDirectGroups(LdapName dn);
+
+ Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly);
+
+ HierarchyUnit doGetHierarchyUnit(LdapName dn);
+
+ LdapEntry newUser(LdapName name);
+
+ LdapEntry newGroup(LdapName name);
+
+ void init();
+
+ void destroy();
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.TreeSet;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+
+/** An LDAP entry. */
+public interface LdapEntry {
+ LdapName getDn();
+
+ Attributes getAttributes();
+
+ void publishAttributes(Attributes modifiedAttributes);
+
+ List<LdapName> getReferences(String attributeId);
+
+ Dictionary<String, Object> getProperties();
+
+ boolean hasCredential(String key, Object value);
+
+ /*
+ * UTILITIES
+ */
+ /**
+ * Convert a collection of object classes to the format expected by an LDAP
+ * backend.
+ */
+ public static void addObjectClasses(Dictionary<String, Object> properties, Collection<String> objectClasses) {
+ String value = properties.get(LdapAttr.objectClasses.name()).toString();
+ Set<String> currentObjectClasses = new TreeSet<>(Arrays.asList(value.toString().split("\n")));
+ currentObjectClasses.addAll(objectClasses);
+ StringJoiner values = new StringJoiner("\n");
+ currentObjectClasses.forEach((s) -> values.add(s));
+ properties.put(LdapAttr.objectClasses.name(), values.toString());
+ }
+
+ public static Object getLocalized(Dictionary<String, Object> properties, String key, Locale locale) {
+ if (locale == null)
+ return null;
+ Object value = null;
+ value = properties.get(key + ";lang-" + locale.getLanguage() + "-" + locale.getCountry());
+ if (value == null)
+ value = properties.get(key + ";lang-" + locale.getLanguage());
+ return value;
+ }
+
+ public static String toLocalizedKey(String key, Locale locale) {
+ String country = locale.getCountry();
+ if ("".equals(country)) {
+ return key + ";lang-" + locale.getLanguage();
+ } else {
+ return key + ";lang-" + locale.getLanguage() + "-" + locale.getCountry();
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.transaction.AbstractWorkingCopy;
+
+/** Working copy for a user directory being edited. */
+public class LdapEntryWorkingCopy extends AbstractWorkingCopy<LdapEntry, Attributes, LdapName> {
+ @Override
+ protected LdapName getId(LdapEntry entry) {
+ return (LdapName) entry.getDn().clone();
+ }
+
+ @Override
+ protected Attributes cloneAttributes(LdapEntry entry) {
+ return (Attributes) entry.getAttributes().clone();
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.util.Locale;
+
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+import org.argeo.api.cms.directory.HierarchyUnit;
+
+/** LDIF/LDAP based implementation of {@link HierarchyUnit}. */
+public class LdapHierarchyUnit extends DefaultLdapEntry implements HierarchyUnit {
+// private final boolean functional;
+
+ private final Type type;
+
+ public LdapHierarchyUnit(AbstractLdapDirectory directory, LdapName dn) {
+ super(directory, dn);
+
+ Rdn rdn = LdapNameUtils.getLastRdn(dn);
+ if (directory.getUserBaseRdn().equals(rdn))
+ type = Type.PEOPLE;
+ else if (directory.getGroupBaseRdn().equals(rdn))
+ type = Type.GROUPS;
+ else if (directory.getSystemRoleBaseRdn().equals(rdn))
+ type = Type.ROLES;
+ else
+ type = Type.FUNCTIONAL;
+// functional = !(directory.getUserBaseRdn().equals(rdn) || directory.getGroupBaseRdn().equals(rdn)
+// || directory.getSystemRoleBaseRdn().equals(rdn));
+ }
+
+ @Override
+ public HierarchyUnit getParent() {
+ return getDirectoryDao().doGetHierarchyUnit(LdapNameUtils.getParent(getDn()));
+ }
+
+ @Override
+ public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
+ return getDirectoryDao().doGetDirectHierarchyUnits(getDn(), functionalOnly);
+ }
+
+ @Override
+ public HierarchyUnit getDirectChild(Type type) {
+ return switch (type) {
+ case ROLES ->
+ getDirectoryDao().doGetHierarchyUnit((LdapName) getDn().add(getDirectory().getSystemRoleBaseRdn()));
+ case PEOPLE -> getDirectoryDao().doGetHierarchyUnit((LdapName) getDn().add(getDirectory().getUserBaseRdn()));
+ case GROUPS -> getDirectoryDao().doGetHierarchyUnit((LdapName) getDn().add(getDirectory().getGroupBaseRdn()));
+ case FUNCTIONAL -> throw new IllegalArgumentException("Type must be a technical type");
+ };
+ }
+
+ @Override
+ public boolean isType(Type type) {
+ return this.type.equals(type);
+ }
+
+ @Override
+ public String getHierarchyUnitName() {
+ String name = LdapNameUtils.getLastRdnValue(getDn());
+ // TODO check ou, o, etc.
+ return name;
+ }
+
+ @Override
+ public String getHierarchyUnitLabel(Locale locale) {
+ String key = LdapNameUtils.getLastRdn(getDn()).getType();
+ Object value = LdapEntry.getLocalized(getProperties(), key, locale);
+ if (value == null)
+ value = getHierarchyUnitName();
+ assert value != null;
+ return value.toString();
+ }
+
+ @Override
+ public String getBase() {
+ return getDn().toString();
+ }
+
+ @Override
+ public String toString() {
+ return "Hierarchy Unit " + getDn().toString();
+ }
+
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+/** Utilities to simplify using {@link LdapName}. */
+public class LdapNameUtils {
+
+ public static LdapName relativeName(LdapName prefix, LdapName dn) {
+ try {
+ if (!dn.startsWith(prefix))
+ throw new IllegalArgumentException("Prefix " + prefix + " not consistent with " + dn);
+ LdapName res = (LdapName) dn.clone();
+ for (int i = 0; i < prefix.size(); i++) {
+ res.remove(0);
+ }
+ return res;
+ } catch (InvalidNameException e) {
+ throw new IllegalStateException("Cannot find realtive name", e);
+ }
+ }
+
+ public static LdapName getParent(LdapName dn) {
+ try {
+ LdapName parent = (LdapName) dn.clone();
+ parent.remove(parent.size() - 1);
+ return parent;
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot get parent of " + dn, e);
+ }
+ }
+
+ public static Rdn getParentRdn(LdapName dn) {
+ if (dn.size() < 2)
+ throw new IllegalArgumentException(dn + " has no parent");
+ Rdn parentRdn = dn.getRdn(dn.size() - 2);
+ return parentRdn;
+ }
+
+ public static LdapName toLdapName(String distinguishedName) {
+ try {
+ return new LdapName(distinguishedName);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot parse " + distinguishedName + " as LDAP name", e);
+ }
+ }
+
+ public static Rdn getLastRdn(LdapName dn) {
+ return dn.getRdn(dn.size() - 1);
+ }
+
+ public static String getLastRdnAsString(LdapName dn) {
+ return getLastRdn(dn).toString();
+ }
+
+ public static String getLastRdnValue(String dn) {
+ return getLastRdnValue(toLdapName(dn));
+ }
+
+ public static String getLastRdnValue(LdapName dn) {
+ return getLastRdn(dn).getValue().toString();
+ }
+
+ /** singleton */
+ private LdapNameUtils() {
+
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import static org.argeo.api.acr.ldap.LdapAttr.objectClass;
+import static org.argeo.api.acr.ldap.LdapObj.inetOrgPerson;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.NavigableMap;
+import java.util.Objects;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapObj;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Role;
+
+/** A user admin based on a LDIF files. */
+public class LdifDao extends AbstractLdapDirectoryDao {
+ private NavigableMap<LdapName, LdapEntry> entries = new TreeMap<>();
+ private NavigableMap<LdapName, LdapHierarchyUnit> hierarchy = new TreeMap<>();
+
+ private NavigableMap<LdapName, Attributes> values = new TreeMap<>();
+
+ public LdifDao(AbstractLdapDirectory directory) {
+ super(directory);
+ }
+
+ public void init() {
+ String uri = getDirectory().getUri();
+ if (uri == null)
+ return;
+ try {
+ URI u = new URI(uri);
+ if (u.getScheme().equals("file")) {
+ File file = new File(u);
+ if (!file.exists())
+ return;
+ }
+ load(u.toURL().openStream());
+ } catch (IOException | URISyntaxException e) {
+ throw new IllegalStateException("Cannot open URL " + getDirectory().getUri(), e);
+ }
+ }
+
+ public void save() {
+ if (getDirectory().getUri() == null)
+ return; // ignore
+ if (getDirectory().isReadOnly())
+ throw new IllegalStateException(
+ "Cannot save LDIF user admin: " + getDirectory().getUri() + " is read-only");
+ try (FileOutputStream out = new FileOutputStream(new File(new URI(getDirectory().getUri())))) {
+ save(out);
+ } catch (IOException | URISyntaxException e) {
+ throw new IllegalStateException("Cannot save user admin to " + getDirectory().getUri(), e);
+ }
+ }
+
+ public void save(OutputStream out) throws IOException {
+ try {
+ LdifWriter ldifWriter = new LdifWriter(out);
+ for (LdapName name : hierarchy.keySet())
+ ldifWriter.writeEntry(name, hierarchy.get(name).getAttributes());
+ for (LdapName name : entries.keySet())
+ ldifWriter.writeEntry(name, entries.get(name).getAttributes());
+ } finally {
+ out.close();
+ }
+ }
+
+ public void load(InputStream in) {
+ try {
+ entries.clear();
+ hierarchy.clear();
+
+ LdifParser ldifParser = new LdifParser();
+ SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
+ for (LdapName key : allEntries.keySet()) {
+ Attributes attributes = allEntries.get(key);
+ // check for inconsistency
+ Set<String> lowerCase = new HashSet<String>();
+ NamingEnumeration<String> ids = attributes.getIDs();
+ while (ids.hasMoreElements()) {
+ String id = ids.nextElement().toLowerCase();
+ if (lowerCase.contains(id))
+ throw new IllegalStateException(key + " has duplicate id " + id);
+ lowerCase.add(id);
+ }
+
+ values.put(key, attributes);
+
+ // analyse object classes
+ NamingEnumeration<?> objectClasses = attributes.get(objectClass.name()).getAll();
+ // System.out.println(key);
+ objectClasses: while (objectClasses.hasMore()) {
+ String objectClass = objectClasses.next().toString();
+ // System.out.println(" " + objectClass);
+ if (objectClass.toLowerCase().equals(inetOrgPerson.name().toLowerCase())) {
+ entries.put(key, newUser(key));
+ break objectClasses;
+ } else if (objectClass.toLowerCase().equals(getDirectory().getGroupObjectClass().toLowerCase())) {
+ entries.put(key, newGroup(key));
+ break objectClasses;
+ } else if (objectClass.equalsIgnoreCase(LdapObj.organizationalUnit.name())) {
+ // TODO skip if it does not contain groups or users
+ hierarchy.put(key, new LdapHierarchyUnit(getDirectory(), key));
+ break objectClasses;
+ }
+ }
+ }
+
+ } catch (NamingException | IOException e) {
+ throw new IllegalStateException("Cannot load user admin service from LDIF", e);
+ }
+ }
+
+ public void destroy() {
+// if (users == null || groups == null)
+ if (entries == null)
+ throw new IllegalStateException("User directory " + getDirectory().getBaseDn() + " is already destroyed");
+// users = null;
+// groups = null;
+ entries = null;
+ }
+
+ /*
+ * USER ADMIN
+ */
+
+ @Override
+ public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
+ if (entries.containsKey(key))
+ return entries.get(key);
+ throw new NameNotFoundException(key + " not persisted");
+ }
+
+ @Override
+ public Attributes doGetAttributes(LdapName name) {
+ if (!values.containsKey(name))
+ throw new IllegalStateException(name + " doe not exist in " + getDirectory().getBaseDn());
+ return values.get(name);
+ }
+
+ @Override
+ public boolean checkConnection() {
+ return true;
+ }
+
+ @Override
+ public boolean entryExists(LdapName dn) {
+ return entries.containsKey(dn);// || groups.containsKey(dn);
+ }
+
+ @Override
+ public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
+ Objects.requireNonNull(searchBase);
+ ArrayList<LdapEntry> res = new ArrayList<>();
+ if (f == null && deep && getDirectory().getBaseDn().equals(searchBase)) {
+ res.addAll(entries.values());
+ } else {
+ filterRoles(entries, searchBase, f, deep, res);
+ }
+ return res;
+ }
+
+ private void filterRoles(SortedMap<LdapName, ? extends LdapEntry> map, LdapName searchBase, String f, boolean deep,
+ List<LdapEntry> res) {
+ // FIXME get rid of OSGi references
+ try {
+ // TODO reduce map with search base ?
+ Filter filter = f != null ? FrameworkUtil.createFilter(f) : null;
+ roles: for (LdapEntry user : map.values()) {
+ LdapName dn = user.getDn();
+ if (dn.startsWith(searchBase)) {
+ if (!deep && dn.size() != (searchBase.size() + 1))
+ continue roles;
+ if (filter == null)
+ res.add(user);
+ else {
+ if (user instanceof Role) {
+ if (filter.match(((Role) user).getProperties()))
+ res.add(user);
+ }
+ }
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Cannot create filter " + f, e);
+ }
+
+ }
+
+ @Override
+ public List<LdapName> getDirectGroups(LdapName dn) {
+ List<LdapName> directGroups = new ArrayList<LdapName>();
+ entries: for (LdapName name : entries.keySet()) {
+ LdapEntry group;
+ try {
+ LdapEntry entry = doGetEntry(name);
+ if (AbstractLdapDirectory.hasObjectClass(entry.getAttributes(), getDirectory().getGroupObjectClass())) {
+ group = entry;
+ } else {
+ continue entries;
+ }
+ } catch (NameNotFoundException e) {
+ throw new IllegalArgumentException("Group " + dn + " not found", e);
+ }
+ if (group.getReferences(getDirectory().getMemberAttributeId()).contains(dn)) {
+ directGroups.add(group.getDn());
+ }
+ }
+ return directGroups;
+ }
+
+ @Override
+ public void prepare(LdapEntryWorkingCopy wc) {
+ // delete
+ for (LdapName dn : wc.getDeletedData().keySet()) {
+ if (entries.containsKey(dn))
+ entries.remove(dn);
+ else
+ throw new IllegalStateException("User to delete not found " + dn);
+ }
+ // add
+ for (LdapName dn : wc.getNewData().keySet()) {
+ LdapEntry user = (LdapEntry) wc.getNewData().get(dn);
+ if (entries.containsKey(dn))
+ throw new IllegalStateException("User to create found " + dn);
+ entries.put(dn, user);
+ }
+ // modify
+ for (LdapName dn : wc.getModifiedData().keySet()) {
+ Attributes modifiedAttrs = wc.getModifiedData().get(dn);
+ LdapEntry user;
+ try {
+ user = doGetEntry(dn);
+ } catch (NameNotFoundException e) {
+ throw new IllegalStateException("User to modify no found " + dn, e);
+ }
+ if (user == null)
+ throw new IllegalStateException("User to modify no found " + dn);
+ user.publishAttributes(modifiedAttrs);
+ }
+ }
+
+ @Override
+ public void commit(LdapEntryWorkingCopy wc) {
+ save();
+ }
+
+ @Override
+ public void rollback(LdapEntryWorkingCopy wc) {
+ init();
+ }
+
+ /*
+ * HIERARCHY
+ */
+ @Override
+ public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
+ if (getDirectory().getBaseDn().equals(dn))
+ return getDirectory();
+ return hierarchy.get(dn);
+ }
+
+ @Override
+ public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+ List<HierarchyUnit> res = new ArrayList<>();
+ for (LdapName n : hierarchy.keySet()) {
+ if (n.size() == searchBase.size() + 1) {
+ if (n.startsWith(searchBase)) {
+ HierarchyUnit hu = hierarchy.get(n);
+ if (functionalOnly) {
+ if (hu.isFunctional())
+ res.add(hu);
+ } else {
+ res.add(hu);
+ }
+ }
+ }
+ }
+ return res;
+ }
+
+ public void scope(LdifDao scoped) {
+ scoped.entries = Collections.unmodifiableNavigableMap(entries);
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+
+/** Basic LDIF parser. */
+public class LdifParser {
+ private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+
+ protected Attributes addAttributes(SortedMap<LdapName, Attributes> res, int lineNumber, LdapName currentDn,
+ Attributes currentAttributes) {
+ try {
+ Rdn nameRdn = currentDn.getRdn(currentDn.size() - 1);
+ Attribute nameAttr = currentAttributes.get(nameRdn.getType());
+ if (nameAttr == null)
+ currentAttributes.put(nameRdn.getType(), nameRdn.getValue());
+ else if (!nameAttr.get().equals(nameRdn.getValue()))
+ throw new IllegalStateException(
+ "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + currentDn
+ + " (shortly before line " + lineNumber + " in LDIF file)");
+ Attributes previous = res.put(currentDn, currentAttributes);
+ return previous;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot add " + currentDn, e);
+ }
+ }
+
+ /** With UTF-8 charset */
+ public SortedMap<LdapName, Attributes> read(InputStream in) throws IOException {
+ try (Reader reader = new InputStreamReader(in, DEFAULT_CHARSET)) {
+ return read(reader);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ // silent
+ }
+ }
+ }
+
+ /** Will close the reader. */
+ public SortedMap<LdapName, Attributes> read(Reader reader) throws IOException {
+ SortedMap<LdapName, Attributes> res = new TreeMap<LdapName, Attributes>();
+ try {
+ List<String> lines = new ArrayList<>();
+ try (BufferedReader br = new BufferedReader(reader)) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ lines.add(line);
+ }
+ }
+ if (lines.size() == 0)
+ return res;
+ // add an empty new line since the last line is not checked
+ if (!lines.get(lines.size() - 1).equals(""))
+ lines.add("");
+
+ LdapName currentDn = null;
+ Attributes currentAttributes = null;
+ StringBuilder currentEntry = new StringBuilder();
+
+ readLines: for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
+ String line = lines.get(lineNumber);
+ boolean isLastLine = false;
+ if (lineNumber == lines.size() - 1)
+ isLastLine = true;
+ if (line.startsWith(" ")) {
+ currentEntry.append(line.substring(1));
+ if (!isLastLine)
+ continue readLines;
+ }
+
+ if (currentEntry.length() != 0 || isLastLine) {
+ // read previous attribute
+ StringBuilder attrId = new StringBuilder(8);
+ boolean isBase64 = false;
+ readAttrId: for (int i = 0; i < currentEntry.length(); i++) {
+ char c = currentEntry.charAt(i);
+ if (c == ':') {
+ if (i + 1 < currentEntry.length() && currentEntry.charAt(i + 1) == ':')
+ isBase64 = true;
+ currentEntry.delete(0, i + (isBase64 ? 2 : 1));
+ break readAttrId;
+ } else {
+ attrId.append(c);
+ }
+ }
+
+ String attributeId = attrId.toString();
+ // TODO should we really trim the end of the string as well?
+ String cleanValueStr = currentEntry.toString().trim();
+ Object attributeValue = isBase64 ? Base64.getDecoder().decode(cleanValueStr) : cleanValueStr;
+
+ // manage DN attributes
+ if (attributeId.equals(LdapAttr.DN) || isLastLine) {
+ if (currentDn != null) {
+ //
+ // ADD
+ //
+ Attributes previous = addAttributes(res, lineNumber, currentDn, currentAttributes);
+ if (previous != null) {
+// log.warn("There was already an entry with DN " + currentDn
+// + ", which has been discarded by a subsequent one.");
+ }
+ }
+
+ if (attributeId.equals(LdapAttr.DN))
+ try {
+ currentDn = new LdapName(attributeValue.toString());
+ currentAttributes = new BasicAttributes(true);
+ } catch (InvalidNameException e) {
+// log.error(attributeValue + " not a valid DN, skipping the entry.");
+ currentDn = null;
+ currentAttributes = null;
+ }
+ }
+
+ // store attribute
+ if (currentAttributes != null) {
+ Attribute attribute = currentAttributes.get(attributeId);
+ if (attribute == null) {
+ attribute = new BasicAttribute(attributeId);
+ currentAttributes.put(attribute);
+ }
+ attribute.add(attributeValue);
+ }
+ currentEntry = new StringBuilder();
+ }
+ currentEntry.append(line);
+ }
+ } finally {
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // silent
+ }
+ }
+ return res;
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import static org.argeo.api.acr.ldap.LdapAttr.DN;
+import static org.argeo.api.acr.ldap.LdapAttr.member;
+import static org.argeo.api.acr.ldap.LdapAttr.objectClass;
+import static org.argeo.api.acr.ldap.LdapAttr.uniqueMember;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+
+/** Basic LDIF writer */
+public class LdifWriter {
+ private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+ private final Writer writer;
+
+ /** Writer must be closed by caller */
+ public LdifWriter(Writer writer) {
+ this.writer = writer;
+ }
+
+ /** Stream must be closed by caller */
+ public LdifWriter(OutputStream out) {
+ this(new OutputStreamWriter(out, DEFAULT_CHARSET));
+ }
+
+ public void writeEntry(LdapName name, Attributes attributes) throws IOException {
+ try {
+ // check consistency
+ Rdn nameRdn = name.getRdn(name.size() - 1);
+ Attribute nameAttr = attributes.get(nameRdn.getType());
+ if (!nameAttr.get().equals(nameRdn.getValue()))
+ throw new IllegalArgumentException(
+ "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + name);
+
+ writer.append(DN + ": ").append(name.toString()).append('\n');
+ Attribute objectClassAttr = attributes.get(objectClass.name());
+ if (objectClassAttr != null)
+ writeAttribute(objectClassAttr);
+ attributes: for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
+ Attribute attribute = attrs.next();
+ if (attribute.getID().equals(DN) || attribute.getID().equals(objectClass.name()))
+ continue attributes;// skip DN attribute
+ if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
+ continue attributes;// skip member and uniqueMember attributes, so that they are always written last
+ writeAttribute(attribute);
+ }
+ // write member and uniqueMember attributes last
+ for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
+ Attribute attribute = attrs.next();
+ if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
+ writeMemberAttribute(attribute);
+ }
+ writer.append('\n');
+ writer.flush();
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot write LDIF", e);
+ }
+ }
+
+ public void write(Map<LdapName, Attributes> entries) throws IOException {
+ for (LdapName dn : entries.keySet())
+ writeEntry(dn, entries.get(dn));
+ }
+
+ protected void writeAttribute(Attribute attribute) throws NamingException, IOException {
+ for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
+ Object value = attrValues.next();
+ if (value instanceof byte[]) {
+ String encoded = Base64.getEncoder().encodeToString((byte[]) value);
+ writer.append(attribute.getID()).append(":: ").append(encoded).append('\n');
+ } else {
+ writer.append(attribute.getID()).append(": ").append(value.toString()).append('\n');
+ }
+ }
+ }
+
+ protected void writeMemberAttribute(Attribute attribute) throws NamingException, IOException {
+ // Note: duplicate entries will be swallowed
+ SortedSet<String> values = new TreeSet<>();
+ for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
+ String value = attrValues.next().toString();
+ values.add(value);
+ }
+
+ for (String value : values) {
+ writer.append(attribute.getID()).append(": ").append(value).append('\n');
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.directory.ldap;
+
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+
+import org.argeo.api.acr.ldap.NamingUtils;
+
+public class SharedSecret extends AuthPassword {
+ public final static String X_SHARED_SECRET = "X-SharedSecret";
+ private final Instant expiry;
+
+ public SharedSecret(String authInfo, String authValue) {
+ super(authInfo, authValue);
+ expiry = null;
+ }
+
+ public SharedSecret(AuthPassword authPassword) {
+ super(authPassword);
+ String authInfo = getAuthInfo();
+ if (authInfo.length() == 16) {
+ expiry = NamingUtils.ldapDateToInstant(authInfo);
+ } else {
+ expiry = null;
+ }
+ }
+
+ public SharedSecret(ZonedDateTime expiryTimestamp, String value) {
+ super(NamingUtils.instantToLdapDate(expiryTimestamp), value);
+ expiry = expiryTimestamp.withZoneSameInstant(ZoneOffset.UTC).toInstant();
+ }
+
+ public SharedSecret(int hours, String value) {
+ this(ZonedDateTime.now().plusHours(hours), value);
+ }
+
+ @Override
+ protected String getExpectedAuthScheme() {
+ return X_SHARED_SECRET;
+ }
+
+ public boolean isExpired() {
+ if (expiry == null)
+ return false;
+ return expiry.isBefore(Instant.now());
+ }
+
+}
--- /dev/null
+package org.argeo.cms.dns;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.SortedSet;
+import java.util.StringJoiner;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+
+public class DnsBrowser implements Closeable {
+ private final DirContext initialCtx;
+
+ public DnsBrowser() {
+ this(new ArrayList<>());
+ }
+
+ public DnsBrowser(List<String> dnsServerUrls) {
+ try {
+ Objects.requireNonNull(dnsServerUrls);
+ Hashtable<String, Object> env = new Hashtable<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
+ if (!dnsServerUrls.isEmpty()) {
+ boolean specified = false;
+ StringJoiner providerUrl = new StringJoiner(" ");
+ for (String dnsUrl : dnsServerUrls) {
+ if (dnsUrl != null) {
+ providerUrl.add(dnsUrl);
+ specified = true;
+ }
+ }
+ if (specified)
+ env.put(Context.PROVIDER_URL, providerUrl.toString());
+ }
+ initialCtx = new InitialDirContext(env);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot initialise DNS borowser.", e);
+ }
+ }
+
+ public Map<String, List<String>> getAllRecords(String name) {
+ try {
+ Map<String, List<String>> res = new TreeMap<>();
+ Attributes attrs = initialCtx.getAttributes(name);
+ NamingEnumeration<String> ids = attrs.getIDs();
+ while (ids.hasMore()) {
+ String recordType = ids.next();
+ List<String> lst = new ArrayList<String>();
+ res.put(recordType, lst);
+ Attribute attr = attrs.get(recordType);
+ addValues(attr, lst);
+ }
+ return Collections.unmodifiableMap(res);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get allrecords of " + name, e);
+ }
+ }
+
+ /**
+ * Return a single record (typically A, AAAA, etc. or null if not available.
+ * Will fail if multiple records.
+ */
+ public String getRecord(String name, String recordType) {
+ try {
+ Attributes attrs = initialCtx.getAttributes(name, new String[] { recordType });
+ if (attrs.size() == 0)
+ return null;
+ Attribute attr = attrs.get(recordType);
+ if (attr.size() > 1)
+ throw new IllegalArgumentException("Multiple record type " + recordType);
+ assert attr.size() != 0;
+ Object value = attr.get();
+ assert value != null;
+ return value.toString();
+ } catch (NameNotFoundException e) {
+ return null;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get DNS entry " + recordType + " of " + name, e);
+ }
+ }
+
+ /**
+ * Return records of a given type.
+ */
+ public List<String> getRecords(String name, String recordType) {
+ try {
+ List<String> res = new ArrayList<String>();
+ Attributes attrs = initialCtx.getAttributes(name, new String[] { recordType });
+ Attribute attr = attrs.get(recordType);
+ addValues(attr, res);
+ return res;
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot get records " + recordType + " of " + name, e);
+ }
+ }
+
+ /** Ordered, with preferred first. */
+ public List<String> getSrvRecordsAsHosts(String name, boolean withPort) {
+ List<String> raw = getRecords(name, "SRV");
+ if (raw.size() == 0)
+ return null;
+ SortedSet<SrvRecord> res = new TreeSet<>();
+ for (int i = 0; i < raw.size(); i++) {
+ String record = raw.get(i);
+ String[] arr = record.split(" ");
+ Integer priority = Integer.parseInt(arr[0]);
+ Integer weight = Integer.parseInt(arr[1]);
+ Integer port = Integer.parseInt(arr[2]);
+ String hostname = arr[3];
+ SrvRecord order = new SrvRecord(priority, weight, port, hostname);
+ res.add(order);
+ }
+ List<String> lst = new ArrayList<>();
+ for (SrvRecord order : res) {
+ lst.add(order.toHost(withPort));
+ }
+ return Collections.unmodifiableList(lst);
+ }
+
+ private void addValues(Attribute attr, List<String> lst) throws NamingException {
+ NamingEnumeration<?> values = attr.getAll();
+ while (values.hasMore()) {
+ Object value = values.next();
+ if (value != null) {
+ if (value instanceof byte[]) {
+ String str = Base64.getEncoder().encodeToString((byte[]) value);
+ lst.add(str);
+ } else
+ lst.add(value.toString());
+ }
+ }
+
+ }
+
+ public List<String> listEntries(String name) {
+ try {
+ List<String> res = new ArrayList<String>();
+ NamingEnumeration<Binding> ne = initialCtx.listBindings(name);
+ while (ne.hasMore()) {
+ Binding b = ne.next();
+ res.add(b.getName());
+ }
+ return Collections.unmodifiableList(res);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot list entries of " + name, e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ destroy();
+ }
+
+ public void destroy() {
+ try {
+ initialCtx.close();
+ } catch (NamingException e) {
+ // silent
+ }
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ printUsage(System.err);
+ System.exit(1);
+ }
+ try (DnsBrowser dnsBrowser = new DnsBrowser()) {
+ String hostname = args[0];
+ String recordType = args.length > 1 ? args[1] : "A";
+ if (recordType.equals("*")) {
+ Map<String, List<String>> records = dnsBrowser.getAllRecords(hostname);
+ for (String type : records.keySet()) {
+ for (String record : records.get(type)) {
+ String typeLabel;
+ if ("44".equals(type))
+ typeLabel = "SSHFP";
+ else if ("46".equals(type))
+ typeLabel = "RRSIG";
+ else if ("48".equals(type))
+ typeLabel = "DNSKEY";
+ else
+ typeLabel = type;
+ System.out.println(typeLabel + "\t" + record);
+ }
+ }
+ } else {
+ System.out.println(dnsBrowser.getRecord(hostname, recordType));
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void printUsage(PrintStream out) {
+ out.println("java org.argeo.naming.DnsBrowser <hostname> [<record type> | *]");
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.argeo.cms.dns;
+
+class SrvRecord implements Comparable<SrvRecord> {
+ private final Integer priority;
+ private final Integer weight;
+ private final Integer port;
+ private final String hostname;
+
+ public SrvRecord(Integer priority, Integer weight, Integer port, String hostname) {
+ this.priority = priority;
+ this.weight = weight;
+ this.port = port;
+ this.hostname = hostname;
+ }
+
+ @Override
+ public int compareTo(SrvRecord other) {
+ // https: // en.wikipedia.org/wiki/SRV_record
+ if (priority != other.priority)
+ return priority - other.priority;
+ if (weight != other.weight)
+ return other.weight - other.weight;
+ String host = toHost(false);
+ String otherHost = other.toHost(false);
+ if (host.length() == otherHost.length())
+ return host.compareTo(otherHost);
+ else
+ return host.length() - otherHost.length();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof SrvRecord) {
+ SrvRecord other = (SrvRecord) obj;
+ return priority == other.priority && weight == other.weight && port == other.port
+ && hostname.equals(other.hostname);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return priority + " " + weight;
+ }
+
+ public String toHost(boolean withPort) {
+ String hostStr = hostname;
+ if (hostname.charAt(hostname.length() - 1) == '.')
+ hostStr = hostname.substring(0, hostname.length() - 1);
+ return hostStr + (withPort ? ":" + port : "");
+ }
+}
--- /dev/null
+package org.argeo.cms.file;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Base64;
+import java.util.zip.Checksum;
+
+/** Allows to fine tune how files are read. */
+public class ChecksumFactory {
+ private int regionSize = 10 * 1024 * 1024;
+
+ public byte[] digest(Path path, final String algo) {
+ try {
+ final MessageDigest md = MessageDigest.getInstance(algo);
+ if (Files.isDirectory(path)) {
+ long begin = System.currentTimeMillis();
+ Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ if (!Files.isDirectory(file)) {
+ byte[] digest = digest(file, algo);
+ md.update(digest);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ });
+ byte[] digest = md.digest();
+ long duration = System.currentTimeMillis() - begin;
+ System.out.println(printBase64Binary(digest) + " " + path + " (" + duration / 1000 + "s)");
+ return digest;
+ } else {
+ long begin = System.nanoTime();
+ long length = -1;
+ try (FileChannel channel = (FileChannel) Files.newByteChannel(path);) {
+ length = channel.size();
+ long cursor = 0;
+ while (cursor < length) {
+ long effectiveSize = Math.min(regionSize, length - cursor);
+ MappedByteBuffer mb = channel.map(FileChannel.MapMode.READ_ONLY, cursor, effectiveSize);
+ // md.update(mb);
+ byte[] buffer = new byte[1024];
+ while (mb.hasRemaining()) {
+ mb.get(buffer);
+ md.update(buffer);
+ }
+
+ // sub digest
+ // mb.flip();
+ // MessageDigest subMd =
+ // MessageDigest.getInstance(algo);
+ // subMd.update(mb);
+ // byte[] subDigest = subMd.digest();
+ // System.out.println(" -> " + cursor);
+ // System.out.println(IOUtils.encodeHexString(subDigest));
+ // System.out.println(new BigInteger(1,
+ // subDigest).toString(16));
+ // System.out.println(new BigInteger(1, subDigest)
+ // .toString(Character.MAX_RADIX));
+ // System.out.println(printBase64Binary(subDigest));
+
+ cursor = cursor + regionSize;
+ }
+ byte[] digest = md.digest();
+ long duration = System.nanoTime() - begin;
+ System.out.println(printBase64Binary(digest) + " " + path.getFileName() + " (" + duration / 1000000
+ + "ms, " + (length / 1024) + "kB, " + (length / (duration / 1000000)) * 1000 / (1024 * 1024)
+ + " MB/s)");
+ return digest;
+ }
+ }
+ } catch (NoSuchAlgorithmException | IOException e) {
+ throw new IllegalStateException("Cannot digest " + path, e);
+ }
+ }
+
+ /** Whether the file should be mapped. */
+ protected boolean mapFile(FileChannel fileChannel) throws IOException {
+ long size = fileChannel.size();
+ if (size > (regionSize / 10))
+ return true;
+ return false;
+ }
+
+ public long checksum(Path path, Checksum crc) {
+ final int bufferSize = 2 * 1024 * 1024;
+ long begin = System.currentTimeMillis();
+ try (FileChannel channel = (FileChannel) Files.newByteChannel(path);) {
+ byte[] bytes = new byte[bufferSize];
+ long length = channel.size();
+ long cursor = 0;
+ while (cursor < length) {
+ long effectiveSize = Math.min(regionSize, length - cursor);
+ MappedByteBuffer mb = channel.map(FileChannel.MapMode.READ_ONLY, cursor, effectiveSize);
+ int nGet;
+ while (mb.hasRemaining()) {
+ nGet = Math.min(mb.remaining(), bufferSize);
+ mb.get(bytes, 0, nGet);
+ crc.update(bytes, 0, nGet);
+ }
+ cursor = cursor + regionSize;
+ }
+ return crc.getValue();
+ } catch (IOException e) {
+ throw new IllegalStateException("Cannot checksum " + path, e);
+ } finally {
+ long duration = System.currentTimeMillis() - begin;
+ System.out.println(duration / 1000 + "s");
+ }
+ }
+
+ public static void main(String... args) {
+ ChecksumFactory cf = new ChecksumFactory();
+ // Path path =
+ // Paths.get("/home/mbaudier/apache-maven-3.2.3-bin.tar.gz");
+ Path path;
+ if (args.length > 0) {
+ path = Paths.get(args[0]);
+ } else {
+ path = Paths.get("/home/mbaudier/Downloads/torrents/CentOS-7-x86_64-DVD-1503-01/"
+ + "CentOS-7-x86_64-DVD-1503-01.iso");
+ }
+ // long adler = cf.checksum(path, new Adler32());
+ // System.out.format("Adler=%d%n", adler);
+ // long crc = cf.checksum(path, new CRC32());
+ // System.out.format("CRC=%d%n", crc);
+ String algo = "SHA1";
+ byte[] digest = cf.digest(path, algo);
+ System.out.println(algo + " " + printBase64Binary(digest));
+ System.out.println(algo + " " + new BigInteger(1, digest).toString(16));
+ // String sha1 = printBase64Binary(cf.digest(path, "SHA1"));
+ // System.out.format("SHA1=%s%n", sha1);
+ }
+
+ private static String printBase64Binary(byte[] arr) {
+ return Base64.getEncoder().encodeToString(arr);
+ }
+}
--- /dev/null
+package org.argeo.cms.http;
+
+/** Selection of standard or common HTTP headers (including WebDav). */
+public enum HttpHeader {
+ AUTHORIZATION("Authorization"), //
+ WWW_AUTHENTICATE("WWW-Authenticate"), //
+ ALLOW("Allow"), //
+ VIA("Via"), //
+
+ // WebDav
+ DAV("DAV"), //
+ DEPTH("Depth"), //
+
+ // Non-standard
+ X_FORWARDED_HOST("X-Forwarded-Host"), //
+ ;
+
+ public final static String BASIC = "Basic";
+ public final static String REALM = "realm";
+ public final static String NEGOTIATE = "Negotiate";
+
+ private final String name;
+
+ private HttpHeader(String headerName) {
+ this.name = headerName;
+ }
+
+ public String getHeaderName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return getHeaderName();
+ }
+
+}
--- /dev/null
+package org.argeo.cms.http;
+
+/** Generic HTTP methods. */
+public enum HttpMethod {
+ OPTIONS, //
+ HEAD, //
+ GET, //
+ POST, //
+ PUT, //
+ DELETE, //
+
+ // WebDav
+ PROPFIND, //
+ PROPPATCH, //
+ MKCOL, //
+ MOVE, //
+ COPY, //
+ ;
+}
--- /dev/null
+package org.argeo.cms.http;
+
+/**
+ * Standard HTTP response status codes (including WebDav ones).
+ *
+ * @see "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
+ */
+public enum HttpStatus {
+ // Successful responses (200–299)
+ OK(200, "OK"), //
+ NO_CONTENT(204, "No Content"), //
+ MULTI_STATUS(207, "Multi-Status"), // WebDav
+ // Client error responses (400–499)
+ UNAUTHORIZED(401, "Unauthorized"), //
+ FORBIDDEN(403, "Forbidden"), //
+ NOT_FOUND(404, "Not Found"), //
+ // Server error responses (500-599)
+ INTERNAL_SERVER_ERROR(500, "Internal Server Error"), //
+ NOT_IMPLEMENTED(501, "Not Implemented"), //
+ ;
+
+ private final int code;
+ private final String reasonPhrase;
+
+ HttpStatus(int statusCode, String reasonPhrase) {
+ this.code = statusCode;
+ this.reasonPhrase = reasonPhrase;
+ }
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getReasonPhrase() {
+ return reasonPhrase;
+ }
+
+ /**
+ * The status line, as defined by RFC2616.
+ *
+ * @see "https://www.rfc-editor.org/rfc/rfc2616#section-6.1"
+ */
+ public String getStatusLine(String httpVersion) {
+ return httpVersion + " " + code + " " + reasonPhrase;
+ }
+
+ public static HttpStatus parseStatusLine(String statusLine) {
+ try {
+ String[] arr = statusLine.split(" ");
+ int code = Integer.parseInt(arr[1]);
+ for (HttpStatus status : values()) {
+ if (status.getCode() == code)
+ return status;
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Invalid status line: " + statusLine, e);
+ }
+ throw new IllegalArgumentException("Unkown status code: " + statusLine);
+ }
+
+ @Override
+ public String toString() {
+ return code + " " + reasonPhrase;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.http.server;
+
+import java.net.URI;
+import java.util.Objects;
+
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+
+/** HTTP utilities on the server-side. */
+public class HttpServerUtils {
+ private final static String SLASH = "/";
+
+ private static String extractPathWithingContext(HttpContext httpContext, String fullPath, boolean startWithSlash) {
+ Objects.requireNonNull(fullPath);
+ String contextPath = httpContext.getPath();
+ if (!fullPath.startsWith(contextPath))
+ throw new IllegalArgumentException(fullPath + " does not belong to context" + contextPath);
+ String path = fullPath.substring(contextPath.length());
+ // TODO optimise?
+ if (!startWithSlash && path.startsWith(SLASH)) {
+ path = path.substring(1);
+ } else if (startWithSlash && !path.startsWith(SLASH)) {
+ path = SLASH + path;
+ }
+ return path;
+ }
+
+ /** Path within the context, NOT starting with a slash. */
+ public static String relativize(HttpExchange exchange) {
+ URI uri = exchange.getRequestURI();
+ HttpContext httpContext = exchange.getHttpContext();
+ return extractPathWithingContext(httpContext, uri.getPath(), false);
+ }
+
+ /** Path within the context, starting with a slash. */
+ public static String subPath(HttpExchange exchange) {
+ URI uri = exchange.getRequestURI();
+ HttpContext httpContext = exchange.getHttpContext();
+ return extractPathWithingContext(httpContext, uri.getPath(), true);
+ }
+
+ /** singleton */
+ private HttpServerUtils() {
+
+ }
+}
+++ /dev/null
-package org.argeo.cms.internal.auth;
-
-import static org.argeo.util.naming.LdapAttrs.cn;
-import static org.argeo.util.naming.LdapAttrs.description;
-import static org.argeo.util.naming.LdapAttrs.owner;
-
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.NavigableMap;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.UUID;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.security.auth.Subject;
-
-import org.argeo.api.acr.NamespaceUtils;
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.api.cms.CmsLog;
-import org.argeo.cms.CmsUserManager;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.auth.SystemRole;
-import org.argeo.cms.auth.UserAdminUtils;
-import org.argeo.osgi.useradmin.AggregatingUserAdmin;
-import org.argeo.osgi.useradmin.TokenUtils;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.directory.DirectoryConf;
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.directory.ldap.LdapEntry;
-import org.argeo.util.directory.ldap.SharedSecret;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.NamingUtils;
-import org.argeo.util.transaction.WorkTransaction;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Canonical implementation of the people {@link CmsUserManager}. Wraps
- * interaction with users and groups.
- *
- * In a *READ-ONLY* mode. We want to be able to:
- * <ul>
- * <li>Retrieve my user and corresponding information (main info,
- * groups...)</li>
- * <li>List all local groups (not the system roles)</li>
- * <li>If sufficient rights: retrieve a given user and its information</li>
- * </ul>
- */
-public class CmsUserManagerImpl implements CmsUserManager {
- private final static CmsLog log = CmsLog.getLog(CmsUserManagerImpl.class);
-
- private UserAdmin userAdmin;
-// private Map<String, String> serviceProperties;
- private WorkTransaction userTransaction;
-
- private final String[] knownProps = { LdapAttrs.cn.name(), LdapAttrs.sn.name(), LdapAttrs.givenName.name(),
- LdapAttrs.uid.name() };
-
-// private Map<UserDirectory, Hashtable<String, Object>> userDirectories = Collections
-// .synchronizedMap(new LinkedHashMap<>());
-
- private Set<UserDirectory> userDirectories = new HashSet<>();
-
- public void start() {
- log.debug(() -> "CMS user manager available");
- }
-
- public void stop() {
-
- }
-
- @Override
- public String getMyMail() {
- return getUserMail(CurrentUser.getUsername());
- }
-
- @Override
- public Role[] getRoles(String filter) throws InvalidSyntaxException {
- return userAdmin.getRoles(filter);
- }
-
- // ALL USER: WARNING access to this will be later reduced
-
- /** Retrieve a user given his dn, or <code>null</code> if it doesn't exist. */
- public User getUser(String dn) {
- return (User) getUserAdmin().getRole(dn);
- }
-
- /** Can be a group or a user */
- public String getUserDisplayName(String dn) {
- // FIXME: during initialisation phase, the system logs "admin" as user
- // name rather than the corresponding dn
- if ("admin".equals(dn))
- return "System Administrator";
- else
- return UserAdminUtils.getUserDisplayName(getUserAdmin(), dn);
- }
-
- @Override
- public String getUserMail(String dn) {
- return UserAdminUtils.getUserMail(getUserAdmin(), dn);
- }
-
- /** Lists all roles of the given user */
- @Override
- public String[] getUserRoles(String dn) {
- Authorization currAuth = getUserAdmin().getAuthorization(getUser(dn));
- return currAuth.getRoles();
- }
-
- @Override
- public boolean isUserInRole(String userDn, String roleDn) {
- String[] roles = getUserRoles(userDn);
- for (String role : roles) {
- if (role.equalsIgnoreCase(roleDn))
- return true;
- }
- return false;
- }
-
- public Set<User> listUsersInGroup(String groupDn, String filter) {
- Group group = (Group) userAdmin.getRole(groupDn);
- if (group == null)
- throw new IllegalArgumentException("Group " + groupDn + " not found");
- Set<User> users = new HashSet<User>();
- addUsers(users, group, filter);
- return users;
- }
-
-// @Override
-// public Set<User> listAccounts(HierarchyUnit hierarchyUnit, boolean deep) {
-// if(!hierarchyUnit.isFunctional())
-// throw new IllegalArgumentException("Hierarchy unit "+hierarchyUnit.getBase()+" is not functional");
-// UserDirectory directory = (UserDirectory)hierarchyUnit.getDirectory();
-// Set<User> res = new HashSet<>();
-// for(HierarchyUnit technicalHu:hierarchyUnit.getDirectHierarchyUnits(false)) {
-// if(technicalHu.isFunctional())
-// continue;
-// for(Role role:directory.getHierarchyUnitRoles(technicalHu, null, false)) {
-// if(role)
-// }
-// }
-// return res;
-// }
-
- /** Recursively add users to list */
- private void addUsers(Set<User> users, Group group, String filter) {
- Role[] roles = group.getMembers();
- for (Role role : roles) {
- if (role.getType() == Role.GROUP) {
- addUsers(users, (Group) role, filter);
- } else if (role.getType() == Role.USER) {
- if (match(role, filter))
- users.add((User) role);
- } else {
- // ignore
- }
- }
- }
-
- public List<User> listGroups(String filter, boolean includeUsers, boolean includeSystemRoles) {
- Role[] roles = null;
- try {
- roles = getUserAdmin().getRoles(filter);
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Unable to get roles with filter: " + filter, e);
- }
-
- List<User> users = new ArrayList<User>();
- for (Role role : roles) {
- if ((includeUsers && role.getType() == Role.USER || role.getType() == Role.GROUP) && !users.contains(role)
- && (includeSystemRoles
- || !role.getName().toLowerCase().endsWith(CmsConstants.SYSTEM_ROLES_BASEDN))) {
- if (match(role, filter))
- users.add((User) role);
- }
- }
- return users;
- }
-
- private boolean match(Role role, String filter) {
- boolean doFilter = filter != null && !"".equals(filter);
- if (doFilter) {
- for (String prop : knownProps) {
- Object currProp = null;
- try {
- currProp = role.getProperties().get(prop);
- } catch (Exception e) {
- throw e;
- }
- if (currProp != null) {
- String currPropStr = ((String) currProp).toLowerCase();
- if (currPropStr.contains(filter.toLowerCase())) {
- return true;
- }
- }
- }
- return false;
- } else
- return true;
- }
-
- @Override
- public User getUserFromLocalId(String localId) {
- User user = getUserAdmin().getUser(LdapAttrs.uid.name(), localId);
- if (user == null)
- user = getUserAdmin().getUser(LdapAttrs.cn.name(), localId);
- return user;
- }
-
- @Override
- public String buildDefaultDN(String localId, int type) {
- return buildDistinguishedName(localId, getDefaultDomainName(), type);
- }
-
- /*
- * EDITION
- */
- @Override
- public User createUser(String username, Map<String, Object> properties, Map<String, Object> credentials) {
- try {
- userTransaction.begin();
- User user = (User) userAdmin.createRole(username, Role.USER);
- if (properties != null) {
- for (String key : properties.keySet())
- user.getProperties().put(key, properties.get(key));
- }
- if (credentials != null) {
- for (String key : credentials.keySet())
- user.getCredentials().put(key, credentials.get(key));
- }
- userTransaction.commit();
- return user;
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot create user " + username, e);
- }
- }
-
- @Override
- public Group getOrCreateGroup(HierarchyUnit groups, String commonName) {
- try {
- String dn = LdapAttrs.cn.name() + "=" + commonName + "," + groups.getBase();
- Group group = (Group) getUserAdmin().getRole(dn);
- if (group != null)
- return group;
- userTransaction.begin();
- group = (Group) userAdmin.createRole(dn, Role.GROUP);
- userTransaction.commit();
- return group;
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot create group " + commonName + " in " + groups, e);
- }
- }
-
- @Override
- public Group getOrCreateSystemRole(HierarchyUnit roles, SystemRole systemRole) {
- try {
- String dn = LdapAttrs.cn.name() + "=" + NamespaceUtils.toPrefixedName(systemRole.getName()) + ","
- + roles.getBase();
- Group group = (Group) getUserAdmin().getRole(dn);
- if (group != null)
- return group;
- userTransaction.begin();
- group = (Group) userAdmin.createRole(dn, Role.GROUP);
- userTransaction.commit();
- return group;
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot create system role " + systemRole + " in " + roles, e);
- }
- }
-
- @Override
- public HierarchyUnit getOrCreateHierarchyUnit(UserDirectory directory, String path) {
- HierarchyUnit hi = directory.getHierarchyUnit(path);
- if (hi != null)
- return hi;
- try {
- userTransaction.begin();
- HierarchyUnit hierarchyUnit = directory.createHierarchyUnit(path);
- userTransaction.commit();
- return hierarchyUnit;
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot create hierarchy unit " + path + " in directory " + directory, e1);
- }
- }
-
- @Override
- public void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties) {
- try {
- userTransaction.begin();
- LdapEntry.addObjectClasses(role.getProperties(), objectClasses);
- for (String key : additionalProperties.keySet()) {
- role.getProperties().put(key, additionalProperties.get(key));
- }
- userTransaction.commit();
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot add object classes " + objectClasses + " to " + role, e1);
- }
- }
-
- @Override
- public void addObjectClasses(HierarchyUnit hierarchyUnit, Set<String> objectClasses,
- Map<String, Object> additionalProperties) {
- try {
- userTransaction.begin();
- LdapEntry.addObjectClasses(hierarchyUnit.getProperties(), objectClasses);
- for (String key : additionalProperties.keySet()) {
- hierarchyUnit.getProperties().put(key, additionalProperties.get(key));
- }
- userTransaction.commit();
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot add object classes " + objectClasses + " to " + hierarchyUnit, e1);
- }
- }
-
- @Override
- public void edit(Runnable action) {
- Objects.requireNonNull(action);
- try {
- userTransaction.begin();
- action.run();
- userTransaction.commit();
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot edit", e1);
- }
- }
-
- @Override
- public void addMember(Group group, Role role) {
- try {
- userTransaction.begin();
- group.addMember(role);
- userTransaction.commit();
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot add object classes " + role + " to group " + group, e1);
- }
- }
-
- @Override
- public String getDefaultDomainName() {
- Map<String, String> dns = getKnownBaseDns(true);
- if (dns.size() == 1)
- return dns.keySet().iterator().next();
- else
- throw new IllegalStateException("Current context contains " + dns.size() + " base dns: "
- + dns.keySet().toString() + ". Unable to chose a default one.");
- }
-
- public Map<String, String> getKnownBaseDns(boolean onlyWritable) {
- Map<String, String> dns = new HashMap<String, String>();
- for (UserDirectory userDirectory : userDirectories) {
- Boolean readOnly = userDirectory.isReadOnly();
- String baseDn = userDirectory.getBase();
-
- if (onlyWritable && readOnly)
- continue;
- if (baseDn.equalsIgnoreCase(CmsConstants.SYSTEM_ROLES_BASEDN))
- continue;
- if (baseDn.equalsIgnoreCase(CmsConstants.TOKENS_BASEDN))
- continue;
- dns.put(baseDn, DirectoryConf.propertiesAsUri(userDirectory.getProperties()).toString());
-
- }
- return dns;
- }
-
- public Set<UserDirectory> getUserDirectories() {
- TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getBase().compareTo(o2.getBase()));
- res.addAll(userDirectories);
- return res;
- }
-
- public String buildDistinguishedName(String localId, String baseDn, int type) {
- Map<String, String> dns = getKnownBaseDns(true);
- Dictionary<String, ?> props = DirectoryConf.uriAsProperties(dns.get(baseDn));
- String dn = null;
- if (Role.GROUP == type)
- dn = LdapAttrs.cn.name() + "=" + localId + "," + DirectoryConf.groupBase.getValue(props) + "," + baseDn;
- else if (Role.USER == type)
- dn = LdapAttrs.uid.name() + "=" + localId + "," + DirectoryConf.userBase.getValue(props) + "," + baseDn;
- else
- throw new IllegalStateException("Unknown role type. " + "Cannot deduce dn for " + localId);
- return dn;
- }
-
- @Override
- public void changeOwnPassword(char[] oldPassword, char[] newPassword) {
- String name = CurrentUser.getUsername();
- LdapName dn;
- try {
- dn = new LdapName(name);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Invalid user dn " + name, e);
- }
- User user = (User) userAdmin.getRole(dn.toString());
- if (!user.hasCredential(null, oldPassword))
- throw new IllegalArgumentException("Invalid password");
- if (Arrays.equals(newPassword, new char[0]))
- throw new IllegalArgumentException("New password empty");
- try {
- userTransaction.begin();
- user.getCredentials().put(null, newPassword);
- userTransaction.commit();
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot change password", e);
- }
- }
-
- public void resetPassword(String username, char[] newPassword) {
- LdapName dn;
- try {
- dn = new LdapName(username);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Invalid user dn " + username, e);
- }
- User user = (User) userAdmin.getRole(dn.toString());
- if (Arrays.equals(newPassword, new char[0]))
- throw new IllegalArgumentException("New password empty");
- try {
- userTransaction.begin();
- user.getCredentials().put(null, newPassword);
- userTransaction.commit();
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot change password", e);
- }
- }
-
- public String addSharedSecret(String email, int hours) {
- User user = (User) userAdmin.getUser(LdapAttrs.mail.name(), email);
- try {
- userTransaction.begin();
- String uuid = UUID.randomUUID().toString();
- SharedSecret sharedSecret = new SharedSecret(hours, uuid);
- user.getCredentials().put(SharedSecret.X_SHARED_SECRET, sharedSecret.toAuthPassword());
- String tokenStr = sharedSecret.getAuthInfo() + '$' + sharedSecret.getAuthValue();
- userTransaction.commit();
- return tokenStr;
- } catch (Exception e) {
- try {
- userTransaction.rollback();
- } catch (Exception e1) {
- log.error("Could not roll back", e1);
- }
- if (e instanceof RuntimeException)
- throw (RuntimeException) e;
- else
- throw new RuntimeException("Cannot change password", e);
- }
- }
-
- @Deprecated
- public String addSharedSecret(String username, String authInfo, String authToken) {
- try {
- userTransaction.begin();
- User user = (User) userAdmin.getRole(username);
- SharedSecret sharedSecret = new SharedSecret(authInfo, authToken);
- user.getCredentials().put(SharedSecret.X_SHARED_SECRET, sharedSecret.toAuthPassword());
- String tokenStr = sharedSecret.getAuthInfo() + '$' + sharedSecret.getAuthValue();
- userTransaction.commit();
- return tokenStr;
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot add shared secret", e1);
- }
- }
-
- @Override
- public void expireAuthToken(String token) {
- try {
- userTransaction.begin();
- String dn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN;
- Group tokenGroup = (Group) userAdmin.getRole(dn);
- String ldapDate = NamingUtils.instantToLdapDate(ZonedDateTime.now(ZoneOffset.UTC));
- tokenGroup.getProperties().put(description.name(), ldapDate);
- userTransaction.commit();
- if (log.isDebugEnabled())
- log.debug("Token " + token + " expired.");
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot expire token", e1);
- }
- }
-
- @Override
- public void expireAuthTokens(Subject subject) {
- Set<String> tokens = TokenUtils.tokensUsed(subject, CmsConstants.TOKENS_BASEDN);
- for (String token : tokens)
- expireAuthToken(token);
- }
-
- @Override
- public void addAuthToken(String userDn, String token, Integer hours, String... roles) {
- addAuthToken(userDn, token, ZonedDateTime.now().plusHours(hours), roles);
- }
-
- @Override
- public void addAuthToken(String userDn, String token, ZonedDateTime expiryDate, String... roles) {
- try {
- userTransaction.begin();
- User user = (User) userAdmin.getRole(userDn);
- String tokenDn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN;
- Group tokenGroup = (Group) userAdmin.createRole(tokenDn, Role.GROUP);
- if (roles != null)
- for (String role : roles) {
- Role r = userAdmin.getRole(role);
- if (r != null)
- tokenGroup.addMember(r);
- else {
- if (!role.equals(CmsConstants.ROLE_USER)) {
- throw new IllegalStateException(
- "Cannot add role " + role + " to token " + token + " for " + userDn);
- }
- }
- }
- tokenGroup.getProperties().put(owner.name(), user.getName());
- if (expiryDate != null) {
- String ldapDate = NamingUtils.instantToLdapDate(expiryDate);
- tokenGroup.getProperties().put(description.name(), ldapDate);
- }
- userTransaction.commit();
- } catch (Exception e1) {
- try {
- if (!userTransaction.isNoTransactionStatus())
- userTransaction.rollback();
- } catch (Exception e2) {
- if (log.isTraceEnabled())
- log.trace("Cannot rollback transaction", e2);
- }
- throw new RuntimeException("Cannot add token", e1);
- }
- }
-
- @Override
- public UserDirectory getDirectory(Role user) {
- String name = user.getName();
- NavigableMap<String, UserDirectory> possible = new TreeMap<>();
- for (UserDirectory userDirectory : userDirectories) {
- if (name.endsWith(userDirectory.getBase())) {
- possible.put(userDirectory.getBase(), userDirectory);
- }
- }
- if (possible.size() == 0)
- throw new IllegalStateException("No user directory found for user " + name);
- return possible.lastEntry().getValue();
- }
-
-// public User createUserFromPerson(Node person) {
-// String email = JcrUtils.get(person, LdapAttrs.mail.property());
-// String dn = buildDefaultDN(email, Role.USER);
-// User user;
-// try {
-// userTransaction.begin();
-// user = (User) userAdmin.createRole(dn, Role.USER);
-// Dictionary<String, Object> userProperties = user.getProperties();
-// String name = JcrUtils.get(person, LdapAttrs.displayName.property());
-// userProperties.put(LdapAttrs.cn.name(), name);
-// userProperties.put(LdapAttrs.displayName.name(), name);
-// String givenName = JcrUtils.get(person, LdapAttrs.givenName.property());
-// String surname = JcrUtils.get(person, LdapAttrs.sn.property());
-// userProperties.put(LdapAttrs.givenName.name(), givenName);
-// userProperties.put(LdapAttrs.sn.name(), surname);
-// userProperties.put(LdapAttrs.mail.name(), email.toLowerCase());
-// userTransaction.commit();
-// } catch (Exception e) {
-// try {
-// userTransaction.rollback();
-// } catch (Exception e1) {
-// log.error("Could not roll back", e1);
-// }
-// if (e instanceof RuntimeException)
-// throw (RuntimeException) e;
-// else
-// throw new RuntimeException("Cannot create user", e);
-// }
-// return user;
-// }
-
- public UserAdmin getUserAdmin() {
- return userAdmin;
- }
-
-// public UserTransaction getUserTransaction() {
-// return userTransaction;
-// }
-
- /* DEPENDENCY INJECTION */
- public void setUserAdmin(UserAdmin userAdmin) {
- this.userAdmin = userAdmin;
-
- if (userAdmin instanceof AggregatingUserAdmin) {
- userDirectories = ((AggregatingUserAdmin) userAdmin).getUserDirectories();
- } else {
- throw new IllegalArgumentException("Only " + AggregatingUserAdmin.class.getName() + " is supported.");
- }
-
-// this.serviceProperties = serviceProperties;
- }
-
- public void setUserTransaction(WorkTransaction userTransaction) {
- this.userTransaction = userTransaction;
- }
-
-// public void addUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
-// userDirectories.put(userDirectory, new Hashtable<>(properties));
-// }
-//
-// public void removeUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
-// userDirectories.remove(userDirectory);
-// }
-
-}
package org.argeo.cms.internal.auth;
-import static org.argeo.api.acr.RuntimeNamespaceContext.getNamespaceContext;
-
import java.security.Principal;
import java.util.HashSet;
import java.util.Set;
import javax.xml.namespace.QName;
-import org.argeo.api.acr.CrName;
-import org.argeo.api.acr.NamespaceUtils;
-import org.argeo.cms.auth.RoleNameUtils;
+import org.argeo.cms.RoleNameUtils;
import org.osgi.service.useradmin.Authorization;
/**
*/
public final class ImpliedByPrincipal implements Principal {
private final String name;
- private Set<Principal> causes = new HashSet<Principal>();
-
- private QName roleName;
-// private int type = Role.ROLE;
+ private final QName roleName;
+ private final boolean systemRole;
+ private final String context;
- private boolean systemRole = false;
- private String context;
+ private Set<Principal> causes = new HashSet<Principal>();
public ImpliedByPrincipal(String name, Principal userPrincipal) {
this.name = name;
- String cn = RoleNameUtils.getLastRdnValue(name);
- roleName = NamespaceUtils.parsePrefixedName(getNamespaceContext(), cn);
- if (roleName.getNamespaceURI().equals(CrName.ROLE_NAMESPACE_URI)) {
- systemRole = true;
- }
+ roleName = RoleNameUtils.getLastRdnAsName(name);
+ systemRole = RoleNameUtils.isSystemRole(roleName);
context = RoleNameUtils.getContext(name);
-// try {
-// this.name = new LdapName(name);
-// } catch (InvalidNameException e) {
-// throw new IllegalArgumentException("Badly formatted role name", e);
-// }
if (userPrincipal != null)
causes.add(userPrincipal);
}
-// public ImpliedByPrincipal(LdapName name, Principal userPrincipal) {
-// this.name = name;
-// if (userPrincipal != null)
-// causes.add(userPrincipal);
-// }
-
public String getName() {
return name;
}
- /*
- * USER ADMIN
- */
-// public boolean addMember(Principal user) {
-// throw new UnsupportedOperationException();
-// }
-//
-// public boolean removeMember(Principal user) {
-// throw new UnsupportedOperationException();
-// }
-//
-// public boolean isMember(Principal member) {
-// return causes.contains(member);
-// }
-//
-// public Enumeration<? extends Principal> members() {
-// return Collections.enumeration(causes);
-// }
-//
-//
-// /** Type of {@link Role}, if known. */
-// public int getType() {
-// return type;
-// }
-//
-// /** Not supported for the time being. */
-// public Dictionary<String, Object> getProperties() {
-// throw new UnsupportedOperationException();
-// }
-
/*
* OBJECT
*/
@Override
public boolean equals(Object obj) {
- // if (this == obj)
- // return true;
if (obj instanceof ImpliedByPrincipal) {
ImpliedByPrincipal that = (ImpliedByPrincipal) obj;
// TODO check members too?
@Override
public String toString() {
- // return name.toString() + " implied by " + causes;
return name.toString();
}
}
import javax.security.auth.login.LoginException;
import org.argeo.api.cms.CmsAuth;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
import org.argeo.cms.auth.RemoteAuthRequest;
import org.argeo.cms.auth.RemoteAuthResponse;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpPrincipal;
+/** An {@link Authenticator} implementation based on CMS authentication. */
public class CmsAuthenticator extends Authenticator {
-// final static String HEADER_AUTHORIZATION = "Authorization";
-// final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
-// private final static CmsLog log = CmsLog.getLog(CmsAuthenticator.class);
-
// TODO make it configurable
private final String httpAuthRealm = "Argeo";
private final boolean forceBasic = false;
@Override
public Result authenticate(HttpExchange exch) {
-// if (log.isTraceEnabled())
-// HttpUtils.logRequestHeaders(log, request);
RemoteAuthHttpExchange remoteAuthExchange = new RemoteAuthHttpExchange(exch);
ClassLoader currentThreadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(CmsAuthenticator.class.getClassLoader());
Subject subject = lc.getSubject();
-// CurrentSubject.callAs(subject, () -> {
-// RemoteAuthUtils.configureRequestSecurity(remoteAuthExchange);
-// return null;
-// });
-// Subject.doAs(subject, new PrivilegedAction<Void>() {
-//
-// @Override
-// public Void run() {
-// // TODO also set login context in order to log out ?
-// RemoteAuthUtils.configureRequestSecurity(new ServletHttpRequest(request));
-// return null;
-// }
-//
-// });
String username = CurrentUser.getUsername(subject);
HttpPrincipal httpPrincipal = new HttpPrincipal(username, httpAuthRealm);
return new Authenticator.Success(httpPrincipal);
package org.argeo.cms.internal.http;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
}
@Override
- public void setHeader(String keys, String value) {
- httpExchange.getResponseHeaders().put(keys, Collections.singletonList(value));
+ public void setHeader(String headerName, String value) {
+ httpExchange.getResponseHeaders().put(headerName, Collections.singletonList(value));
+ }
+
+ @Override
+ public void addHeader(String headerName, String value) {
+ List<String> values = httpExchange.getResponseHeaders().getOrDefault(headerName, new ArrayList<>());
+ values.add(value);
}
@Override
private static BundleContext bundleContext;
-// private LogReaderService logReaderService;
-//
-// private CmsOsgiLogger logger;
-
void init() {
-// Runtime.getRuntime().addShutdownHook(new CmsShutdown());
-// instance = this;
-// this.bc = bundleContext;
-// if (bundleContext != null)
-// this.logReaderService = getService(LogReaderService.class);
-// initArgeoLogger();
-// this.internalExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-//
-// try {
-// initSecurity();
-//// initArgeoLogger();
-// initNode();
-//
-// if (log.isTraceEnabled())
-// log.trace("Kernel bundle started");
-// } catch (Throwable e) {
-// log.error("## FATAL: CMS activator failed", e);
-// }
}
void destroy() {
}
-// private void initArgeoLogger() {
-// logger = new CmsOsgiLogger(logReaderService);
-// if (bundleContext != null)
-// bundleContext.registerService(ArgeoLogger.class, logger, null);
-// }
-
public static <T> void registerService(Class<T> clss, T service, Dictionary<String, ?> properties) {
if (bundleContext != null) {
bundleContext.registerService(clss, service, properties);
import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.CmsLog;
-import org.argeo.util.directory.DirectoryConf;
+import org.argeo.cms.runtime.DirectoryConf;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.argeo.cms.dav.DavHttpHandler;
import org.argeo.cms.dav.DavPropfind;
import org.argeo.cms.dav.DavResponse;
+import org.argeo.cms.http.HttpStatus;
import org.argeo.cms.internal.http.RemoteAuthHttpExchange;
-import org.argeo.util.StreamUtils;
-import org.argeo.util.http.HttpStatus;
+import org.argeo.cms.util.StreamUtils;
import com.sun.net.httpserver.HttpExchange;
import org.ietf.jgss.GSSCredential;
import org.osgi.service.useradmin.UserAdmin;
+/** Reference implementation of {@link CmsContext}. */
public class CmsContextImpl implements CmsContext {
private final CmsLog log = CmsLog.getLog(getClass());
private static CompletableFuture<CmsContextImpl> instance = new CompletableFuture<CmsContextImpl>();
-// private static CmsContextImpl instance = null;
private CmsState cmsState;
private CmsDeployment cmsDeployment;
private UserAdmin userAdmin;
private UuidFactory uuidFactory;
private CmsEventBus cmsEventBus;
-// private ProvidedRepository contentRepository;
// i18n
private Locale defaultLocale;
}
}
}, "Check readiness").start();
-
- // checkReadiness();
-
setInstance(this);
}
this.uuidFactory = uuidFactory;
}
-// public ProvidedRepository getContentRepository() {
-// return contentRepository;
-// }
-//
-// public void setContentRepository(ProvidedRepository contentRepository) {
-// this.contentRepository = contentRepository;
-// }
-
@Override
public Locale getDefaultLocale() {
return defaultLocale;
}
private static void setInstance(CmsContextImpl cmsContextImpl) {
-// if (cmsContextImpl != null) {
-// if (instance != null)
-// throw new IllegalStateException("CMS Context is already set");
-// instance = cmsContextImpl;
-// } else {
-// instance = null;
-// }
-// CmsContextImpl.class.notifyAll();
-
if (cmsContextImpl != null) {
if (instance.isDone())
throw new IllegalStateException("CMS Context is already set");
}
private static CmsContextImpl getInstance() {
-// while (instance == null) {
-// try {
-// CmsContextImpl.class.wait();
-// } catch (InterruptedException e) {
-// throw new IllegalStateException("Cannot wait for CMS context instance", e);
-// }
-// }
-// return instance;
-
try {
return instance.get();
} catch (InterruptedException | ExecutionException e) {
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
-/** Implementation of a CMS deployment. */
+/** Reference implementation of {@link CmsDeployment}. */
public class CmsDeploymentImpl implements CmsDeployment {
private final CmsLog log = CmsLog.getLog(getClass());
import org.argeo.api.cms.CmsEventSubscriber;
import org.argeo.api.cms.CmsLog;
+/** {@link CmsEventBus} implementation based on {@link Flow}. */
public class CmsEventBusImpl implements CmsEventBus {
private final CmsLog log = CmsLog.getLog(CmsEventBus.class);
- // CMS events
private Map<String, SubmissionPublisher<Map<String, Object>>> topics = new TreeMap<>();
-// private IdentityHashMap<CmsEventSubscriber, List<CmsEventFlowSubscriber>> subscriptions = new IdentityHashMap<>();
- /*
- * CMS Events
- */
@Override
public void sendEvent(String topic, Map<String, Object> event) {
SubmissionPublisher<Map<String, Object>> publisher = topics.get(topic);
}
}
+ /** A subscriber to a topic. */
static class CmsEventFlowSubscriber implements Flow.Subscriber<Map<String, Object>> {
private String topic;
private CmsEventSubscriber eventSubscriber;
import org.argeo.api.uuid.UuidFactory;
import org.argeo.cms.CmsDeployProperty;
import org.argeo.cms.auth.ident.IdentClient;
-import org.argeo.util.FsUtils;
+import org.argeo.cms.util.FsUtils;
/**
* Implementation of a {@link CmsState}, initialising the required services.
posixPermissions.add(PosixFilePermission.OWNER_WRITE);
posixPermissions.add(PosixFilePermission.OWNER_EXECUTE);
try {
+ if (!Files.exists(privateDir))
+ Files.createDirectories(privateDir);
Files.setPosixFilePermissions(privateDir, posixPermissions);
} catch (IOException e) {
- log.error("Cannot set permissions on " + privateDir);
+ log.error("Cannot set permissions on " + privateDir, e);
}
}
import org.argeo.api.cms.CmsConstants;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.CmsState;
+import org.argeo.api.cms.directory.UserDirectory;
+import org.argeo.api.cms.transaction.WorkControl;
+import org.argeo.api.cms.transaction.WorkTransaction;
import org.argeo.cms.CmsDeployProperty;
-import org.argeo.osgi.useradmin.AggregatingUserAdmin;
-import org.argeo.osgi.useradmin.DirectoryUserAdmin;
-import org.argeo.osgi.useradmin.UserDirectory;
-import org.argeo.util.directory.DirectoryConf;
-import org.argeo.util.naming.dns.DnsBrowser;
-import org.argeo.util.transaction.WorkControl;
-import org.argeo.util.transaction.WorkTransaction;
+import org.argeo.cms.dns.DnsBrowser;
+import org.argeo.cms.osgi.useradmin.AggregatingUserAdmin;
+import org.argeo.cms.osgi.useradmin.DirectoryUserAdmin;
+import org.argeo.cms.runtime.DirectoryConf;
import org.ietf.jgss.GSSCredential;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
--- /dev/null
+package org.argeo.cms.internal.runtime;
+
+import static org.argeo.api.acr.ldap.LdapAttr.cn;
+import static org.argeo.api.acr.ldap.LdapAttr.description;
+import static org.argeo.api.acr.ldap.LdapAttr.owner;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+import javax.xml.namespace.QName;
+
+import org.argeo.api.acr.NamespaceUtils;
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.acr.ldap.NamingUtils;
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.directory.CmsGroup;
+import org.argeo.api.cms.directory.CmsUser;
+import org.argeo.api.cms.directory.CmsUserManager;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.UserDirectory;
+import org.argeo.api.cms.transaction.WorkTransaction;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.auth.UserAdminUtils;
+import org.argeo.cms.directory.ldap.LdapEntry;
+import org.argeo.cms.directory.ldap.SharedSecret;
+import org.argeo.cms.osgi.useradmin.AggregatingUserAdmin;
+import org.argeo.cms.osgi.useradmin.TokenUtils;
+import org.argeo.cms.runtime.DirectoryConf;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Authorization;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Canonical implementation of the people {@link CmsUserManager}. Wraps
+ * interaction with users and groups.
+ *
+ * In a *READ-ONLY* mode. We want to be able to:
+ * <ul>
+ * <li>Retrieve my user and corresponding information (main info,
+ * groups...)</li>
+ * <li>List all local groups (not the system roles)</li>
+ * <li>If sufficient rights: retrieve a given user and its information</li>
+ * </ul>
+ */
+public class CmsUserManagerImpl implements CmsUserManager {
+ private final static CmsLog log = CmsLog.getLog(CmsUserManagerImpl.class);
+
+ private UserAdmin userAdmin;
+// private Map<String, String> serviceProperties;
+ private WorkTransaction userTransaction;
+
+ private final String[] knownProps = { LdapAttr.cn.name(), LdapAttr.sn.name(), LdapAttr.givenName.name(),
+ LdapAttr.uid.name() };
+
+// private Map<UserDirectory, Hashtable<String, Object>> userDirectories = Collections
+// .synchronizedMap(new LinkedHashMap<>());
+
+ private Set<UserDirectory> userDirectories = new HashSet<>();
+
+ public void start() {
+ log.debug(() -> "CMS user manager available");
+ }
+
+ public void stop() {
+
+ }
+
+ @Override
+ public String getMyMail() {
+ return getUserMail(CurrentUser.getUsername());
+ }
+
+ @Override
+ public Role[] getRoles(String filter) {
+ try {
+ return userAdmin.getRoles(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Invalid filter " + filter, e);
+ }
+ }
+
+ // ALL USER: WARNING access to this will be later reduced
+
+ /** Retrieve a user given his dn, or <code>null</code> if it doesn't exist. */
+ public CmsUser getUser(String dn) {
+ return (CmsUser) getUserAdmin().getRole(dn);
+ }
+
+ /** Can be a group or a user */
+ public String getUserDisplayName(String dn) {
+ // FIXME: during initialisation phase, the system logs "admin" as user
+ // name rather than the corresponding dn
+ if ("admin".equals(dn))
+ return "System Administrator";
+ else
+ return UserAdminUtils.getUserDisplayName(getUserAdmin(), dn);
+ }
+
+ @Override
+ public String getUserMail(String dn) {
+ return UserAdminUtils.getUserMail(getUserAdmin(), dn);
+ }
+
+ /** Lists all roles of the given user */
+ @Override
+ public String[] getUserRoles(String dn) {
+ Authorization currAuth = getUserAdmin().getAuthorization(getUser(dn));
+ return currAuth.getRoles();
+ }
+
+ @Override
+ public boolean isUserInRole(String userDn, String roleDn) {
+ String[] roles = getUserRoles(userDn);
+ for (String role : roles) {
+ if (role.equalsIgnoreCase(roleDn))
+ return true;
+ }
+ return false;
+ }
+
+ public Set<CmsUser> listUsersInGroup(String groupDn, String filter) {
+ Group group = (Group) userAdmin.getRole(groupDn);
+ if (group == null)
+ throw new IllegalArgumentException("Group " + groupDn + " not found");
+ Set<CmsUser> users = new HashSet<>();
+ addUsers(users, group, filter);
+ return users;
+ }
+
+// @Override
+// public Set<User> listAccounts(HierarchyUnit hierarchyUnit, boolean deep) {
+// if(!hierarchyUnit.isFunctional())
+// throw new IllegalArgumentException("Hierarchy unit "+hierarchyUnit.getBase()+" is not functional");
+// UserDirectory directory = (UserDirectory)hierarchyUnit.getDirectory();
+// Set<User> res = new HashSet<>();
+// for(HierarchyUnit technicalHu:hierarchyUnit.getDirectHierarchyUnits(false)) {
+// if(technicalHu.isFunctional())
+// continue;
+// for(Role role:directory.getHierarchyUnitRoles(technicalHu, null, false)) {
+// if(role)
+// }
+// }
+// return res;
+// }
+
+ /** Recursively add users to list */
+ private void addUsers(Set<CmsUser> users, Group group, String filter) {
+ Role[] roles = group.getMembers();
+ for (Role role : roles) {
+ if (role.getType() == Role.GROUP) {
+ addUsers(users, (CmsGroup) role, filter);
+ } else if (role.getType() == Role.USER) {
+ if (match(role, filter))
+ users.add((CmsUser) role);
+ } else {
+ // ignore
+ }
+ }
+ }
+
+ public List<CmsUser> listGroups(String filter, boolean includeUsers, boolean includeSystemRoles) {
+ Role[] roles = null;
+ try {
+ roles = getUserAdmin().getRoles(filter);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Unable to get roles with filter: " + filter, e);
+ }
+
+ List<CmsUser> users = new ArrayList<>();
+ for (Role role : roles) {
+ if ((includeUsers && role.getType() == Role.USER || role.getType() == Role.GROUP) && !users.contains(role)
+ && (includeSystemRoles
+ || !role.getName().toLowerCase().endsWith(CmsConstants.SYSTEM_ROLES_BASEDN))) {
+ if (match(role, filter))
+ users.add((CmsUser) role);
+ }
+ }
+ return users;
+ }
+
+ private boolean match(Role role, String filter) {
+ boolean doFilter = filter != null && !"".equals(filter);
+ if (doFilter) {
+ for (String prop : knownProps) {
+ Object currProp = null;
+ try {
+ currProp = role.getProperties().get(prop);
+ } catch (Exception e) {
+ throw e;
+ }
+ if (currProp != null) {
+ String currPropStr = ((String) currProp).toLowerCase();
+ if (currPropStr.contains(filter.toLowerCase())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } else
+ return true;
+ }
+
+ @Override
+ public CmsUser getUserFromLocalId(String localId) {
+ CmsUser user = (CmsUser) getUserAdmin().getUser(LdapAttr.uid.name(), localId);
+ if (user == null)
+ user = (CmsUser) getUserAdmin().getUser(LdapAttr.cn.name(), localId);
+ return user;
+ }
+
+ @Override
+ public String buildDefaultDN(String localId, int type) {
+ return buildDistinguishedName(localId, getDefaultDomainName(), type);
+ }
+
+ /*
+ * EDITION
+ */
+ @Override
+ public CmsUser createUser(String username, Map<String, Object> properties, Map<String, Object> credentials) {
+ try {
+ userTransaction.begin();
+ CmsUser user = (CmsUser) userAdmin.createRole(username, Role.USER);
+ if (properties != null) {
+ for (String key : properties.keySet())
+ user.getProperties().put(key, properties.get(key));
+ }
+ if (credentials != null) {
+ for (String key : credentials.keySet())
+ user.getCredentials().put(key, credentials.get(key));
+ }
+ userTransaction.commit();
+ return user;
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot create user " + username, e);
+ }
+ }
+
+ @Override
+ public CmsGroup createGroup(String dn) {
+ try {
+ userTransaction.begin();
+ CmsGroup group = (CmsGroup) userAdmin.createRole(dn, Role.GROUP);
+ userTransaction.commit();
+ return group;
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot create group " + dn, e);
+ }
+ }
+
+ @Override
+ public CmsGroup getOrCreateGroup(HierarchyUnit groups, String commonName) {
+ String dn = LdapAttr.cn.name() + "=" + commonName + "," + groups.getBase();
+ CmsGroup group = (CmsGroup) getUserAdmin().getRole(dn);
+ if (group != null)
+ return group;
+ try {
+ userTransaction.begin();
+ group = (CmsGroup) userAdmin.createRole(dn, Role.GROUP);
+ userTransaction.commit();
+ return group;
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot create group " + commonName + " in " + groups, e);
+ }
+ }
+
+ @Override
+ public CmsGroup getOrCreateSystemRole(HierarchyUnit roles, QName systemRole) {
+ String dn = LdapAttr.cn.name() + "=" + NamespaceUtils.toPrefixedName(systemRole) + "," + roles.getBase();
+ CmsGroup group = (CmsGroup) getUserAdmin().getRole(dn);
+ if (group != null)
+ return group;
+ try {
+ userTransaction.begin();
+ group = (CmsGroup) userAdmin.createRole(dn, Role.GROUP);
+ userTransaction.commit();
+ return group;
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot create system role " + systemRole + " in " + roles, e);
+ }
+ }
+
+ @Override
+ public HierarchyUnit getOrCreateHierarchyUnit(UserDirectory directory, String path) {
+ HierarchyUnit hi = directory.getHierarchyUnit(path);
+ if (hi != null)
+ return hi;
+ try {
+ userTransaction.begin();
+ HierarchyUnit hierarchyUnit = directory.createHierarchyUnit(path);
+ userTransaction.commit();
+ return hierarchyUnit;
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot create hierarchy unit " + path + " in directory " + directory, e1);
+ }
+ }
+
+ @Override
+ public void addObjectClasses(Role role, Set<String> objectClasses, Map<String, Object> additionalProperties) {
+ try {
+ userTransaction.begin();
+ LdapEntry.addObjectClasses(role.getProperties(), objectClasses);
+ for (String key : additionalProperties.keySet()) {
+ role.getProperties().put(key, additionalProperties.get(key));
+ }
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot add object classes " + objectClasses + " to " + role, e1);
+ }
+ }
+
+ @Override
+ public void addObjectClasses(HierarchyUnit hierarchyUnit, Set<String> objectClasses,
+ Map<String, Object> additionalProperties) {
+ try {
+ userTransaction.begin();
+ LdapEntry.addObjectClasses(hierarchyUnit.getProperties(), objectClasses);
+ for (String key : additionalProperties.keySet()) {
+ hierarchyUnit.getProperties().put(key, additionalProperties.get(key));
+ }
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot add object classes " + objectClasses + " to " + hierarchyUnit, e1);
+ }
+ }
+
+ @Override
+ public void edit(Runnable action) {
+ Objects.requireNonNull(action);
+ try {
+ userTransaction.begin();
+ action.run();
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot edit", e1);
+ }
+ }
+
+ @Override
+ public void addMember(CmsGroup group, Role role) {
+ try {
+ userTransaction.begin();
+ group.addMember(role);
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot add member " + role + " to group " + group, e1);
+ }
+ }
+
+ @Override
+ public void removeMember(CmsGroup group, Role role) {
+ try {
+ userTransaction.begin();
+ group.removeMember(role);
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot remove member " + role + " from group " + group, e1);
+ }
+ }
+
+ @Override
+ public String getDefaultDomainName() {
+ Map<String, String> dns = getKnownBaseDns(true);
+ if (dns.size() == 1)
+ return dns.keySet().iterator().next();
+ else
+ throw new IllegalStateException("Current context contains " + dns.size() + " base dns: "
+ + dns.keySet().toString() + ". Unable to chose a default one.");
+ }
+
+ public Map<String, String> getKnownBaseDns(boolean onlyWritable) {
+ Map<String, String> dns = new HashMap<String, String>();
+ for (UserDirectory userDirectory : userDirectories) {
+ Boolean readOnly = userDirectory.isReadOnly();
+ String baseDn = userDirectory.getBase();
+
+ if (onlyWritable && readOnly)
+ continue;
+ if (baseDn.equalsIgnoreCase(CmsConstants.SYSTEM_ROLES_BASEDN))
+ continue;
+ if (baseDn.equalsIgnoreCase(CmsConstants.TOKENS_BASEDN))
+ continue;
+ dns.put(baseDn, DirectoryConf.propertiesAsUri(userDirectory.getProperties()).toString());
+
+ }
+ return dns;
+ }
+
+ public Set<UserDirectory> getUserDirectories() {
+ TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getBase().compareTo(o2.getBase()));
+ res.addAll(userDirectories);
+ return res;
+ }
+
+ public String buildDistinguishedName(String localId, String baseDn, int type) {
+ Map<String, String> dns = getKnownBaseDns(true);
+ Dictionary<String, ?> props = DirectoryConf.uriAsProperties(dns.get(baseDn));
+ String dn = null;
+ if (Role.GROUP == type)
+ dn = LdapAttr.cn.name() + "=" + localId + "," + DirectoryConf.groupBase.getValue(props) + "," + baseDn;
+ else if (Role.USER == type)
+ dn = LdapAttr.uid.name() + "=" + localId + "," + DirectoryConf.userBase.getValue(props) + "," + baseDn;
+ else
+ throw new IllegalStateException("Unknown role type. " + "Cannot deduce dn for " + localId);
+ return dn;
+ }
+
+ @Override
+ public void changeOwnPassword(char[] oldPassword, char[] newPassword) {
+ String name = CurrentUser.getUsername();
+ LdapName dn;
+ try {
+ dn = new LdapName(name);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Invalid user dn " + name, e);
+ }
+ User user = (User) userAdmin.getRole(dn.toString());
+ if (!user.hasCredential(null, oldPassword))
+ throw new IllegalArgumentException("Invalid password");
+ if (Arrays.equals(newPassword, new char[0]))
+ throw new IllegalArgumentException("New password empty");
+ try {
+ userTransaction.begin();
+ user.getCredentials().put(null, newPassword);
+ userTransaction.commit();
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot change password", e);
+ }
+ }
+
+ public void resetPassword(String username, char[] newPassword) {
+ LdapName dn;
+ try {
+ dn = new LdapName(username);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Invalid user dn " + username, e);
+ }
+ User user = (User) userAdmin.getRole(dn.toString());
+ if (Arrays.equals(newPassword, new char[0]))
+ throw new IllegalArgumentException("New password empty");
+ try {
+ userTransaction.begin();
+ user.getCredentials().put(null, newPassword);
+ userTransaction.commit();
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot change password", e);
+ }
+ }
+
+ public String addSharedSecret(String email, int hours) {
+ User user = (User) userAdmin.getUser(LdapAttr.mail.name(), email);
+ try {
+ userTransaction.begin();
+ String uuid = UUID.randomUUID().toString();
+ SharedSecret sharedSecret = new SharedSecret(hours, uuid);
+ user.getCredentials().put(SharedSecret.X_SHARED_SECRET, sharedSecret.toAuthPassword());
+ String tokenStr = sharedSecret.getAuthInfo() + '$' + sharedSecret.getAuthValue();
+ userTransaction.commit();
+ return tokenStr;
+ } catch (Exception e) {
+ try {
+ userTransaction.rollback();
+ } catch (Exception e1) {
+ log.error("Could not roll back", e1);
+ }
+ if (e instanceof RuntimeException)
+ throw (RuntimeException) e;
+ else
+ throw new RuntimeException("Cannot change password", e);
+ }
+ }
+
+ @Deprecated
+ public String addSharedSecret(String username, String authInfo, String authToken) {
+ try {
+ userTransaction.begin();
+ User user = (User) userAdmin.getRole(username);
+ SharedSecret sharedSecret = new SharedSecret(authInfo, authToken);
+ user.getCredentials().put(SharedSecret.X_SHARED_SECRET, sharedSecret.toAuthPassword());
+ String tokenStr = sharedSecret.getAuthInfo() + '$' + sharedSecret.getAuthValue();
+ userTransaction.commit();
+ return tokenStr;
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot add shared secret", e1);
+ }
+ }
+
+ @Override
+ public void expireAuthToken(String token) {
+ try {
+ userTransaction.begin();
+ String dn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN;
+ Group tokenGroup = (Group) userAdmin.getRole(dn);
+ String ldapDate = NamingUtils.instantToLdapDate(ZonedDateTime.now(ZoneOffset.UTC));
+ tokenGroup.getProperties().put(description.name(), ldapDate);
+ userTransaction.commit();
+ if (log.isDebugEnabled())
+ log.debug("Token " + token + " expired.");
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot expire token", e1);
+ }
+ }
+
+ @Override
+ public void expireAuthTokens(Subject subject) {
+ Set<String> tokens = TokenUtils.tokensUsed(subject, CmsConstants.TOKENS_BASEDN);
+ for (String token : tokens)
+ expireAuthToken(token);
+ }
+
+ @Override
+ public void addAuthToken(String userDn, String token, Integer hours, String... roles) {
+ addAuthToken(userDn, token, ZonedDateTime.now().plusHours(hours), roles);
+ }
+
+ @Override
+ public void addAuthToken(String userDn, String token, ZonedDateTime expiryDate, String... roles) {
+ try {
+ userTransaction.begin();
+ User user = (User) userAdmin.getRole(userDn);
+ String tokenDn = cn + "=" + token + "," + CmsConstants.TOKENS_BASEDN;
+ Group tokenGroup = (Group) userAdmin.createRole(tokenDn, Role.GROUP);
+ if (roles != null)
+ for (String role : roles) {
+ Role r = userAdmin.getRole(role);
+ if (r != null)
+ tokenGroup.addMember(r);
+ else {
+ if (!role.equals(CmsConstants.ROLE_USER)) {
+ throw new IllegalStateException(
+ "Cannot add role " + role + " to token " + token + " for " + userDn);
+ }
+ }
+ }
+ tokenGroup.getProperties().put(owner.name(), user.getName());
+ if (expiryDate != null) {
+ String ldapDate = NamingUtils.instantToLdapDate(expiryDate);
+ tokenGroup.getProperties().put(description.name(), ldapDate);
+ }
+ userTransaction.commit();
+ } catch (Exception e1) {
+ try {
+ if (!userTransaction.isNoTransactionStatus())
+ userTransaction.rollback();
+ } catch (Exception e2) {
+ if (log.isTraceEnabled())
+ log.trace("Cannot rollback transaction", e2);
+ }
+ throw new RuntimeException("Cannot add token", e1);
+ }
+ }
+
+ @Override
+ public UserDirectory getDirectory(Role user) {
+ String name = user.getName();
+ NavigableMap<String, UserDirectory> possible = new TreeMap<>();
+ for (UserDirectory userDirectory : userDirectories) {
+ if (name.endsWith(userDirectory.getBase())) {
+ possible.put(userDirectory.getBase(), userDirectory);
+ }
+ }
+ if (possible.size() == 0)
+ throw new IllegalStateException("No user directory found for user " + name);
+ return possible.lastEntry().getValue();
+ }
+
+// public User createUserFromPerson(Node person) {
+// String email = JcrUtils.get(person, LdapAttrs.mail.property());
+// String dn = buildDefaultDN(email, Role.USER);
+// User user;
+// try {
+// userTransaction.begin();
+// user = (User) userAdmin.createRole(dn, Role.USER);
+// Dictionary<String, Object> userProperties = user.getProperties();
+// String name = JcrUtils.get(person, LdapAttrs.displayName.property());
+// userProperties.put(LdapAttrs.cn.name(), name);
+// userProperties.put(LdapAttrs.displayName.name(), name);
+// String givenName = JcrUtils.get(person, LdapAttrs.givenName.property());
+// String surname = JcrUtils.get(person, LdapAttrs.sn.property());
+// userProperties.put(LdapAttrs.givenName.name(), givenName);
+// userProperties.put(LdapAttrs.sn.name(), surname);
+// userProperties.put(LdapAttrs.mail.name(), email.toLowerCase());
+// userTransaction.commit();
+// } catch (Exception e) {
+// try {
+// userTransaction.rollback();
+// } catch (Exception e1) {
+// log.error("Could not roll back", e1);
+// }
+// if (e instanceof RuntimeException)
+// throw (RuntimeException) e;
+// else
+// throw new RuntimeException("Cannot create user", e);
+// }
+// return user;
+// }
+
+ public UserAdmin getUserAdmin() {
+ return userAdmin;
+ }
+
+// public UserTransaction getUserTransaction() {
+// return userTransaction;
+// }
+
+ /* DEPENDENCY INJECTION */
+ public void setUserAdmin(UserAdmin userAdmin) {
+ this.userAdmin = userAdmin;
+
+ if (userAdmin instanceof AggregatingUserAdmin) {
+ userDirectories = ((AggregatingUserAdmin) userAdmin).getUserDirectories();
+ } else {
+ throw new IllegalArgumentException("Only " + AggregatingUserAdmin.class.getName() + " is supported.");
+ }
+
+// this.serviceProperties = serviceProperties;
+ }
+
+ public void setUserTransaction(WorkTransaction userTransaction) {
+ this.userTransaction = userTransaction;
+ }
+
+// public void addUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
+// userDirectories.put(userDirectory, new Hashtable<>(properties));
+// }
+//
+// public void removeUserDirectory(UserDirectory userDirectory, Map<String, Object> properties) {
+// userDirectories.remove(userDirectory);
+// }
+
+}
import java.nio.file.Path;
import org.argeo.api.cms.CmsLog;
-import org.argeo.cms.CmsUserManager;
+import org.argeo.api.cms.directory.CmsUserManager;
import org.argeo.cms.acr.CmsContentRepository;
import org.argeo.cms.acr.directory.DirectoryContentProvider;
import org.argeo.cms.acr.fs.FsContentProvider;
Path executionDir = Paths.get(getFrameworkProp("user.dir"));
if (relativePath == null)
return executionDir;
-// try {
return executionDir.resolve(relativePath);
-// } catch (IOException e) {
-// throw new IllegalArgumentException("Cannot get canonical file", e);
-// }
}
-// static File getOsgiInstanceDir() {
-// return new File(CmsActivator.getBundleContext().getProperty(OSGI_INSTANCE_AREA).substring("file:".length()))
-// .getAbsoluteFile();
-// }
-
public static Path getOsgiInstancePath(String relativePath) {
URI uri = getOsgiInstanceUri(relativePath);
if (uri == null) // no data area available
if (!osgiInstanceBaseUri.endsWith("/"))
osgiInstanceBaseUri = osgiInstanceBaseUri + "/";
-// if (osgiInstanceBaseUri != null)
return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : ""));
-// else
-// return Paths.get(System.getProperty("user.dir"), (relativePath != null ? relativePath : "")).toUri();
}
-// static File getOsgiConfigurationFile(String relativePath) {
-// try {
-// return new File(
-// new URI(CmsActivator.getBundleContext().getProperty(OSGI_CONFIGURATION_AREA) + relativePath))
-// .getCanonicalFile();
-// } catch (Exception e) {
-// throw new IllegalArgumentException("Cannot get configuration file for " + relativePath, e);
-// }
-// }
-
static String getFrameworkProp(String key, String def) {
String value;
if (CmsActivator.getBundleContext() != null)
return getFrameworkProp(key, null);
}
- // Security
- // static Subject anonymousLogin() {
- // Subject subject = new Subject();
- // LoginContext lc;
- // try {
- // lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject);
- // lc.login();
- // return subject;
- // } catch (LoginException e) {
- // throw new CmsException("Cannot login as anonymous", e);
- // }
- // }
-
static void logFrameworkProperties(CmsLog log) {
for (Object sysProp : new TreeSet<Object>(System.getProperties().keySet())) {
log.debug(sysProp + "=" + getFrameworkProp(sysProp.toString()));
}
- // String[] keys = { Constants.FRAMEWORK_STORAGE,
- // Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION,
- // Constants.FRAMEWORK_PROCESSOR, Constants.FRAMEWORK_SECURITY,
- // Constants.FRAMEWORK_TRUST_REPOSITORIES,
- // Constants.FRAMEWORK_WINDOWSYSTEM, Constants.FRAMEWORK_VENDOR,
- // Constants.FRAMEWORK_VERSION, Constants.FRAMEWORK_STORAGE_CLEAN,
- // Constants.FRAMEWORK_LANGUAGE, Constants.FRAMEWORK_UUID };
- // for (String key : keys)
- // log.debug(key + "=" + bc.getProperty(key));
}
static void printSystemProperties(PrintStream out) {
out.println(key + "=" + display.get(key));
}
-// static Session openAdminSession(Repository repository) {
-// return openAdminSession(repository, null);
-// }
-//
-// static Session openAdminSession(final Repository repository, final String workspaceName) {
-// LoginContext loginContext = loginAsDataAdmin();
-// return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
-//
-// @Override
-// public Session run() {
-// try {
-// return repository.login(workspaceName);
-// } catch (RepositoryException e) {
-// throw new IllegalStateException("Cannot open admin session", e);
-// } finally {
-// try {
-// loginContext.logout();
-// } catch (LoginException e) {
-// throw new IllegalStateException(e);
-// }
-// }
-// }
-//
-// });
-// }
-//
-// static LoginContext loginAsDataAdmin() {
-// ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
-// Thread.currentThread().setContextClassLoader(KernelUtils.class.getClassLoader());
-// LoginContext loginContext;
-// try {
-// loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN);
-// loginContext.login();
-// } catch (LoginException e1) {
-// throw new IllegalStateException("Could not login as data admin", e1);
-// } finally {
-// Thread.currentThread().setContextClassLoader(currentCl);
-// }
-// return loginContext;
-// }
-
-// static void doAsDataAdmin(Runnable action) {
-// LoginContext loginContext = loginAsDataAdmin();
-// Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {
-//
-// @Override
-// public Void run() {
-// try {
-// action.run();
-// return null;
-// } finally {
-// try {
-// loginContext.logout();
-// } catch (LoginException e) {
-// throw new IllegalStateException(e);
-// }
-// }
-// }
-//
-// });
-// }
-
-// public static void asyncOpen(ServiceTracker<?, ?> st) {
-// Runnable run = new Runnable() {
-//
-// @Override
-// public void run() {
-// st.open();
-// }
-// };
-// Activator.getInternalExecutorService().execute(run);
-//// new Thread(run, "Open service tracker " + st).start();
-// }
-
-// static BundleContext getBundleContext() {
-// return Activator.getBundleContext();
-// }
-
static boolean asBoolean(String value) {
if (value == null)
return false;
import java.util.stream.Collectors;
import org.argeo.api.cms.ux.CmsTheme;
-import org.argeo.util.StreamUtils;
+import org.argeo.cms.util.StreamUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
--- /dev/null
+package org.argeo.cms.osgi;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/** Simplify filtering resources. */
+public class FilterRequirement implements Requirement {
+ private String namespace;
+ private String filter;
+
+ public FilterRequirement(String namespace, String filter) {
+ this.namespace = namespace;
+ this.filter = filter;
+ }
+
+ @Override
+ public Resource getResource() {
+ return null;
+ }
+
+ @Override
+ public String getNamespace() {
+ return namespace;
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ Map<String, String> directives = new HashMap<>();
+ directives.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
+ return directives;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return new HashMap<>();
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.argeo.api.cms.directory.CmsAuthorization;
+import org.osgi.service.useradmin.Authorization;
+
+/** An {@link Authorization} which combines roles form various auth sources. */
+class AggregatingAuthorization implements CmsAuthorization {
+ private final String name;
+ private final String displayName;
+ private final Set<String> systemRoles;
+ private final Set<String> roles;
+
+ public AggregatingAuthorization(String name, String displayName, Set<String> systemRoles, String[] roles) {
+ this.name = new X500Principal(name).getName();
+ this.displayName = displayName;
+ this.systemRoles = Collections.unmodifiableSet(new HashSet<>(systemRoles));
+ Set<String> temp = new HashSet<>();
+ for (String role : roles) {
+ if (!temp.contains(role))
+ temp.add(role);
+ }
+ this.roles = Collections.unmodifiableSet(temp);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean hasRole(String name) {
+ if (systemRoles.contains(name))
+ return true;
+ if (roles.contains(name))
+ return true;
+ return false;
+ }
+
+ @Override
+ public String[] getRoles() {
+ int size = systemRoles.size() + roles.size();
+ List<String> res = new ArrayList<String>(size);
+ res.addAll(systemRoles);
+ res.addAll(roles);
+ return res.toArray(new String[size]);
+ }
+
+ @Override
+ public int hashCode() {
+ if (name == null)
+ return super.hashCode();
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Authorization))
+ return false;
+ Authorization that = (Authorization) obj;
+ if (name == null)
+ return that.getName() == null;
+ return name.equals(that.getName());
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import static org.argeo.cms.osgi.useradmin.DirectoryUserAdmin.toLdapName;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.directory.CmsUser;
+import org.argeo.api.cms.directory.UserDirectory;
+import org.argeo.cms.runtime.DirectoryConf;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Authorization;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/**
+ * Aggregates multiple {@link UserDirectory} and integrates them with system
+ * roles.
+ */
+public class AggregatingUserAdmin implements UserAdmin {
+ private final LdapName systemRolesBaseDn;
+ private final LdapName tokensBaseDn;
+
+ // DAOs
+ private DirectoryUserAdmin systemRoles = null;
+ private DirectoryUserAdmin tokens = null;
+ private Map<LdapName, DirectoryUserAdmin> businessRoles = new HashMap<LdapName, DirectoryUserAdmin>();
+
+ // TODO rather use an empty constructor and an init method
+ public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) {
+ try {
+ this.systemRolesBaseDn = new LdapName(systemRolesBaseDn);
+ if (tokensBaseDn != null)
+ this.tokensBaseDn = new LdapName(tokensBaseDn);
+ else
+ this.tokensBaseDn = null;
+ } catch (InvalidNameException e) {
+ throw new IllegalStateException("Cannot initialize " + AggregatingUserAdmin.class, e);
+ }
+ }
+
+ @Override
+ public Role createRole(String name, int type) {
+ return findUserAdmin(name).createRole(name, type);
+ }
+
+ @Override
+ public boolean removeRole(String name) {
+ boolean actuallyDeleted = findUserAdmin(name).removeRole(name);
+ systemRoles.removeRole(name);
+ return actuallyDeleted;
+ }
+
+ @Override
+ public Role getRole(String name) {
+ return findUserAdmin(name).getRole(name);
+ }
+
+ @Override
+ public Role[] getRoles(String filter) throws InvalidSyntaxException {
+ List<Role> res = new ArrayList<Role>();
+ for (UserAdmin userAdmin : businessRoles.values()) {
+ res.addAll(Arrays.asList(userAdmin.getRoles(filter)));
+ }
+ res.addAll(Arrays.asList(systemRoles.getRoles(filter)));
+ return res.toArray(new Role[res.size()]);
+ }
+
+ @Override
+ public User getUser(String key, String value) {
+ List<User> res = new ArrayList<User>();
+ for (UserAdmin userAdmin : businessRoles.values()) {
+ User u = userAdmin.getUser(key, value);
+ if (u != null)
+ res.add(u);
+ }
+ // Note: node roles cannot contain users, so it is not searched
+ return res.size() == 1 ? res.get(0) : null;
+ }
+
+ /** Builds an authorisation by scanning all referentials. */
+ @Override
+ public Authorization getAuthorization(User user) {
+ if (user == null) {// anonymous
+ return systemRoles.getAuthorization(null);
+ }
+ DirectoryUserAdmin userReferentialOfThisUser = findUserAdmin(user.getName());
+ Authorization rawAuthorization = userReferentialOfThisUser.getAuthorization(user);
+ User retrievedUser = (User) userReferentialOfThisUser.getRole(user.getName());
+ String usernameToUse;
+ String displayNameToUse;
+ if (user instanceof Group) {
+ // TODO check whether this is still working
+ String ownerDn = TokenUtils.userDn((Group) user);
+ if (ownerDn != null) {// tokens
+ UserAdmin ownerUserAdmin = findUserAdmin(ownerDn);
+ User ownerUser = (User) ownerUserAdmin.getRole(ownerDn);
+ usernameToUse = ownerDn;
+ displayNameToUse = LdifAuthorization.extractDisplayName(ownerUser);
+ } else {
+ usernameToUse = rawAuthorization.getName();
+ displayNameToUse = rawAuthorization.toString();
+ }
+ } else {// regular users
+ usernameToUse = rawAuthorization.getName();
+ displayNameToUse = rawAuthorization.toString();
+ }
+
+ // gather roles from other referentials
+ List<String> rawRoles = Arrays.asList(rawAuthorization.getRoles());
+ List<String> allRoles = new ArrayList<>(rawRoles);
+ for (LdapName otherBaseDn : businessRoles.keySet()) {
+ if (otherBaseDn.equals(userReferentialOfThisUser.getBaseDn()))
+ continue;
+ DirectoryUserAdmin otherUserAdmin = userAdminToUse(user, businessRoles.get(otherBaseDn));
+ if (otherUserAdmin == null)
+ continue;
+ for (String roleStr : rawRoles) {
+ User role = (User) findUserAdmin(roleStr).getRole(roleStr);
+ Authorization auth = otherUserAdmin.getAuthorization(role);
+ allRoles.addAll(Arrays.asList(auth.getRoles()));
+ }
+
+ }
+
+ // integrate system roles
+ final DirectoryUserAdmin userAdminToUse = userAdminToUse(retrievedUser, userReferentialOfThisUser);
+ Objects.requireNonNull(userAdminToUse);
+
+ try {
+ Set<String> sysRoles = new HashSet<String>();
+ for (String role : rawAuthorization.getRoles()) {
+ User userOrGroup = (User) userAdminToUse.getRole(role);
+ Authorization auth = systemRoles.getAuthorization(userOrGroup);
+ systemRoles: for (String systemRole : auth.getRoles()) {
+ if (role.equals(systemRole))
+ continue systemRoles;
+ sysRoles.add(systemRole);
+ }
+// sysRoles.addAll(Arrays.asList(auth.getRoles()));
+ }
+ addAbstractSystemRoles(rawAuthorization, sysRoles);
+ Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
+ allRoles.toArray(new String[allRoles.size()]));
+ return authorization;
+ } finally {
+ if (userAdminToUse != null && userAdminToUse.isScoped()) {
+ userAdminToUse.destroy();
+ }
+ }
+ }
+
+ /** Decide whether to scope or not */
+ private DirectoryUserAdmin userAdminToUse(User user, DirectoryUserAdmin userAdmin) {
+ if (userAdmin.isAuthenticated())
+ return userAdmin;
+ if (user instanceof CmsUser) {
+ return userAdmin;
+ } else if (user instanceof AuthenticatingUser) {
+ return userAdmin.scope(user).orElse(null);
+ } else {
+ throw new IllegalArgumentException("Unsupported user type " + user.getClass());
+ }
+
+ }
+
+ /**
+ * Enrich with application-specific roles which are strictly programmatic, such
+ * as anonymous/user semantics.
+ */
+ protected void addAbstractSystemRoles(Authorization rawAuthorization, Set<String> sysRoles) {
+
+ }
+
+ //
+ // USER ADMIN AGGREGATOR
+ //
+ protected void addUserDirectory(UserDirectory ud) {
+ if (!(ud instanceof DirectoryUserAdmin))
+ throw new IllegalArgumentException("Only " + DirectoryUserAdmin.class.getName() + " is supported");
+ DirectoryUserAdmin userDirectory = (DirectoryUserAdmin) ud;
+ String basePath = userDirectory.getBase();
+ if (isSystemRolesBaseDn(basePath)) {
+ this.systemRoles = userDirectory;
+ systemRoles.setExternalRoles(this);
+ } else if (isTokensBaseDn(basePath)) {
+ this.tokens = userDirectory;
+ tokens.setExternalRoles(this);
+ } else {
+ LdapName baseDn = toLdapName(basePath);
+ if (businessRoles.containsKey(baseDn))
+ throw new IllegalStateException("There is already a user admin for " + baseDn);
+ businessRoles.put(baseDn, userDirectory);
+ }
+ userDirectory.init();
+ postAdd(userDirectory);
+ }
+
+ /** Called after a new user directory has been added */
+ protected void postAdd(UserDirectory userDirectory) {
+ }
+
+ private DirectoryUserAdmin findUserAdmin(String name) {
+ try {
+ return findUserAdmin(new LdapName(name));
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Badly formatted name " + name, e);
+ }
+ }
+
+ private DirectoryUserAdmin findUserAdmin(LdapName name) {
+ if (name.startsWith(systemRolesBaseDn))
+ return systemRoles;
+ if (tokensBaseDn != null && name.startsWith(tokensBaseDn))
+ return tokens;
+ List<DirectoryUserAdmin> res = new ArrayList<>(1);
+ userDirectories: for (LdapName baseDn : businessRoles.keySet()) {
+ DirectoryUserAdmin userDirectory = businessRoles.get(baseDn);
+ if (name.startsWith(baseDn)) {
+ if (userDirectory.isDisabled())
+ continue userDirectories;
+// if (res.isEmpty()) {
+ res.add(userDirectory);
+// } else {
+// for (AbstractUserDirectory ud : res) {
+// LdapName bd = ud.getBaseDn();
+// if (userDirectory.getBaseDn().startsWith(bd)) {
+// // child user directory
+// }
+// }
+// }
+ }
+ }
+ if (res.size() == 0)
+ throw new IllegalStateException("Cannot find user admin for " + name);
+ if (res.size() > 1)
+ throw new IllegalStateException("Multiple user admin found for " + name);
+ return res.get(0);
+ }
+
+ protected boolean isSystemRolesBaseDn(String basePath) {
+ return toLdapName(basePath).equals(systemRolesBaseDn);
+ }
+
+ protected boolean isTokensBaseDn(String basePath) {
+ return tokensBaseDn != null && toLdapName(basePath).equals(tokensBaseDn);
+ }
+
+// protected Dictionary<String, Object> currentState() {
+// Dictionary<String, Object> res = new Hashtable<String, Object>();
+// // res.put(NodeConstants.CN, NodeConstants.DEFAULT);
+// for (LdapName name : businessRoles.keySet()) {
+// AbstractUserDirectory userDirectory = businessRoles.get(name);
+// String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString();
+// res.put(uri, "");
+// }
+// return res;
+// }
+
+ public void start() {
+ if (systemRoles == null) {
+ // TODO do we really need separate system roles?
+ Hashtable<String, Object> properties = new Hashtable<>();
+ properties.put(DirectoryConf.baseDn.name(), "ou=roles,ou=system");
+ systemRoles = new DirectoryUserAdmin(properties);
+ }
+ }
+
+ public void stop() {
+ for (LdapName name : businessRoles.keySet()) {
+ DirectoryUserAdmin userDirectory = businessRoles.get(name);
+ destroy(userDirectory);
+ }
+ businessRoles.clear();
+ businessRoles = null;
+ destroy(systemRoles);
+ systemRoles = null;
+ }
+
+ private void destroy(DirectoryUserAdmin userDirectory) {
+ preDestroy(userDirectory);
+ userDirectory.destroy();
+ }
+
+// protected void removeUserDirectory(UserDirectory userDirectory) {
+// LdapName baseDn = toLdapName(userDirectory.getContext());
+// businessRoles.remove(baseDn);
+// if (userDirectory instanceof DirectoryUserAdmin)
+// destroy((DirectoryUserAdmin) userDirectory);
+// }
+
+ @Deprecated
+ protected void removeUserDirectory(String basePath) {
+ if (isSystemRolesBaseDn(basePath))
+ throw new IllegalArgumentException("System roles cannot be removed ");
+ LdapName baseDn = toLdapName(basePath);
+ if (!businessRoles.containsKey(baseDn))
+ throw new IllegalStateException("No user directory registered for " + baseDn);
+ DirectoryUserAdmin userDirectory = businessRoles.remove(baseDn);
+ destroy(userDirectory);
+ }
+
+ /**
+ * Called before each user directory is destroyed, so that additional actions
+ * can be performed.
+ */
+ protected void preDestroy(UserDirectory userDirectory) {
+ }
+
+ public Set<UserDirectory> getUserDirectories() {
+ TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getBase().compareTo(o2.getBase()));
+ res.addAll(businessRoles.values());
+ res.add(systemRoles);
+ return res;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.directory.DirectoryDigestUtils;
+import org.osgi.service.useradmin.User;
+
+/**
+ * A special user type used during authentication in order to provide the
+ * credentials required for scoping the user admin.
+ */
+public class AuthenticatingUser implements User {
+ /** From com.sun.security.auth.module.*LoginModule */
+ public final static String SHARED_STATE_NAME = "javax.security.auth.login.name";
+ /** From com.sun.security.auth.module.*LoginModule */
+ public final static String SHARED_STATE_PWD = "javax.security.auth.login.password";
+
+ private final String name;
+ private final Dictionary<String, Object> credentials;
+
+ public AuthenticatingUser(LdapName name) {
+ if (name == null)
+ throw new NullPointerException("Provided name cannot be null.");
+ this.name = name.toString();
+ this.credentials = new Hashtable<>();
+ }
+
+ public AuthenticatingUser(String name, Dictionary<String, Object> credentials) {
+ this.name = name;
+ this.credentials = credentials;
+ }
+
+ public AuthenticatingUser(String name, char[] password) {
+ if (name == null)
+ throw new NullPointerException("Provided name cannot be null.");
+ this.name = name;
+ credentials = new Hashtable<>();
+ credentials.put(SHARED_STATE_NAME, name);
+ byte[] pwd = DirectoryDigestUtils.charsToBytes(password);
+ credentials.put(SHARED_STATE_PWD, pwd);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getType() {
+ return User.USER;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Dictionary getProperties() {
+ throw new UnsupportedOperationException();
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Dictionary getCredentials() {
+ return credentials;
+ }
+
+ @Override
+ public boolean hasCredential(String key, Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return "Authenticating user " + name;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import static org.argeo.api.acr.ldap.LdapAttr.objectClass;
+import static org.argeo.api.acr.ldap.LdapObj.extensibleObject;
+import static org.argeo.api.acr.ldap.LdapObj.inetOrgPerson;
+import static org.argeo.api.acr.ldap.LdapObj.organizationalPerson;
+import static org.argeo.api.acr.ldap.LdapObj.person;
+import static org.argeo.api.acr.ldap.LdapObj.top;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+
+import org.argeo.api.cms.directory.DirectoryDigestUtils;
+import org.argeo.api.cms.directory.CmsUser;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.api.cms.directory.UserDirectory;
+import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
+import org.argeo.cms.directory.ldap.LdapDao;
+import org.argeo.cms.directory.ldap.LdapEntry;
+import org.argeo.cms.directory.ldap.LdapEntryWorkingCopy;
+import org.argeo.cms.directory.ldap.LdapNameUtils;
+import org.argeo.cms.directory.ldap.LdifDao;
+import org.argeo.cms.runtime.DirectoryConf;
+import org.argeo.cms.util.CurrentSubject;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Authorization;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.osgi.service.useradmin.UserAdmin;
+
+/** Base class for a {@link UserDirectory}. */
+public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdmin, UserDirectory {
+
+ private UserAdmin externalRoles;
+
+ // Transaction
+ public DirectoryUserAdmin(URI uriArg, Dictionary<String, ?> props) {
+ this(uriArg, props, false);
+ }
+
+ public DirectoryUserAdmin(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
+ super(uriArg, props, scoped);
+ }
+
+ public DirectoryUserAdmin(Dictionary<String, ?> props) {
+ this(null, props);
+ }
+
+ /*
+ * ABSTRACT METHODS
+ */
+
+ protected Optional<DirectoryUserAdmin> scope(User user) {
+ if (getDirectoryDao() instanceof LdapDao) {
+ return scopeLdap(user);
+ } else if (getDirectoryDao() instanceof LdifDao) {
+ return scopeLdif(user);
+ } else {
+ throw new IllegalStateException("Unsupported DAO " + getDirectoryDao().getClass());
+ }
+ }
+
+ protected Optional<DirectoryUserAdmin> scopeLdap(User user) {
+ Dictionary<String, Object> credentials = user.getCredentials();
+ String username = (String) credentials.get(SHARED_STATE_USERNAME);
+ if (username == null)
+ username = user.getName();
+ Dictionary<String, Object> properties = cloneConfigProperties();
+ properties.put(Context.SECURITY_PRINCIPAL, username.toString());
+ Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
+ byte[] pwd = (byte[]) pwdCred;
+ if (pwd != null) {
+ char[] password = DirectoryDigestUtils.bytesToChars(pwd);
+ properties.put(Context.SECURITY_CREDENTIALS, new String(password));
+ } else {
+ properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
+ }
+ DirectoryUserAdmin scopedDirectory = new DirectoryUserAdmin(null, properties, true);
+ scopedDirectory.init();
+ // check connection
+ if (!scopedDirectory.getDirectoryDao().checkConnection())
+ return Optional.empty();
+ return Optional.of(scopedDirectory);
+ }
+
+ protected Optional<DirectoryUserAdmin> scopeLdif(User user) {
+ Dictionary<String, Object> credentials = user.getCredentials();
+ String username = (String) credentials.get(SHARED_STATE_USERNAME);
+ if (username == null)
+ username = user.getName();
+ Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
+ byte[] pwd = (byte[]) pwdCred;
+ if (pwd != null) {
+ char[] password = DirectoryDigestUtils.bytesToChars(pwd);
+ User directoryUser = (User) getRole(username);
+ if (!directoryUser.hasCredential(null, password))
+ throw new IllegalStateException("Invalid credentials");
+ } else {
+ throw new IllegalStateException("Password is required");
+ }
+ Dictionary<String, Object> properties = cloneConfigProperties();
+ properties.put(DirectoryConf.readOnly.name(), "true");
+ DirectoryUserAdmin scopedUserAdmin = new DirectoryUserAdmin(null, properties, true);
+ // FIXME do it better
+ ((LdifDao) getDirectoryDao()).scope((LdifDao) scopedUserAdmin.getDirectoryDao());
+ // no need to check authentication
+ scopedUserAdmin.init();
+ return Optional.of(scopedUserAdmin);
+ }
+
+ @Override
+ public String getRolePath(Role role) {
+ return nameToRelativePath(LdapNameUtils.toLdapName(role.getName()));
+ }
+
+ @Override
+ public String getRoleSimpleName(Role role) {
+ LdapName dn = LdapNameUtils.toLdapName(role.getName());
+ String name = LdapNameUtils.getLastRdnValue(dn);
+ return name;
+ }
+
+ @Override
+ public Role getRoleByPath(String path) {
+ LdapEntry entry = doGetRole(pathToName(path));
+ if (!(entry instanceof Role)) {
+ return null;
+// throw new IllegalStateException("Path must be a UserAdmin Role.");
+ } else {
+ return (Role) entry;
+ }
+ }
+
+ protected List<Role> getAllRoles(CmsUser user) {
+ List<Role> allRoles = new ArrayList<Role>();
+ if (user != null) {
+ collectRoles((LdapEntry) user, allRoles);
+ allRoles.add(user);
+ } else
+ collectAnonymousRoles(allRoles);
+ return allRoles;
+ }
+
+ private void collectRoles(LdapEntry user, List<Role> allRoles) {
+ List<LdapEntry> allEntries = new ArrayList<>();
+ LdapEntry entry = user;
+ collectGroups(entry, allEntries);
+ for (LdapEntry e : allEntries) {
+ if (e instanceof Role)
+ allRoles.add((Role) e);
+ }
+ }
+
+ private void collectAnonymousRoles(List<Role> allRoles) {
+ // TODO gather anonymous roles
+ }
+
+ // USER ADMIN
+ @Override
+ public Role getRole(String name) {
+ return (Role) doGetRole(toLdapName(name));
+ }
+
+ @Override
+ public Role[] getRoles(String filter) throws InvalidSyntaxException {
+ List<? extends Role> res = getRoles(getBaseDn(), filter, true);
+ return res.toArray(new Role[res.size()]);
+ }
+
+ List<CmsUser> getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException {
+ LdapEntryWorkingCopy wc = getWorkingCopy();
+// Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
+ List<LdapEntry> searchRes = getDirectoryDao().doGetEntries(searchBase, filter, deep);
+ List<CmsUser> res = new ArrayList<>();
+ for (LdapEntry entry : searchRes)
+ res.add((CmsUser) entry);
+ if (wc != null) {
+ for (Iterator<CmsUser> it = res.iterator(); it.hasNext();) {
+ CmsUser user = (CmsUser) it.next();
+ LdapName dn = LdapNameUtils.toLdapName(user.getName());
+ if (wc.getDeletedData().containsKey(dn))
+ it.remove();
+ }
+ Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
+ for (LdapEntry ldapEntry : wc.getNewData().values()) {
+ CmsUser user = (CmsUser) ldapEntry;
+ if (f == null || f.match(user.getProperties()))
+ res.add(user);
+ }
+ // no need to check modified users,
+ // since doGetRoles was already based on the modified attributes
+ }
+ return res;
+ }
+
+ @Override
+ public User getUser(String key, String value) {
+ // TODO check value null or empty
+ List<CmsUser> collectedUsers = new ArrayList<CmsUser>();
+ if (key != null) {
+ doGetUser(key, value, collectedUsers);
+ } else {
+ throw new IllegalArgumentException("Key cannot be null");
+ }
+
+ if (collectedUsers.size() == 1) {
+ return collectedUsers.get(0);
+ } else if (collectedUsers.size() > 1) {
+ // log.warn(collectedUsers.size() + " users for " + (key != null ? key + "=" :
+ // "") + value);
+ }
+ return null;
+ }
+
+ protected void doGetUser(String key, String value, List<CmsUser> collectedUsers) {
+ String f = "(" + key + "=" + value + ")";
+ List<LdapEntry> users = getDirectoryDao().doGetEntries(getBaseDn(), f, true);
+ for (LdapEntry entry : users)
+ collectedUsers.add((CmsUser) entry);
+ }
+
+ @Override
+ public Authorization getAuthorization(User user) {
+ if (user == null) {// anonymous
+ return new LdifAuthorization(user, getAllRoles(null));
+ }
+ LdapName userName = toLdapName(user.getName());
+ if (isExternal(userName) && user instanceof LdapEntry) {
+ List<Role> allRoles = new ArrayList<Role>();
+ collectRoles((LdapEntry) user, allRoles);
+ return new LdifAuthorization(user, allRoles);
+ } else {
+
+ Subject currentSubject = CurrentSubject.current();
+ if (currentSubject != null //
+ && getRealm().isPresent() //
+ && !currentSubject.getPrivateCredentials(Authorization.class).isEmpty() //
+ && !currentSubject.getPrivateCredentials(KerberosTicket.class).isEmpty()) //
+ {
+ // TODO not only Kerberos but also bind scope with kept password ?
+ Authorization auth = currentSubject.getPrivateCredentials(Authorization.class).iterator().next();
+ // bind with authenticating user
+ DirectoryUserAdmin scopedUserAdmin = CurrentSubject.callAs(currentSubject, () -> {
+ return scope(new AuthenticatingUser(auth.getName(), new Hashtable<>())).orElseThrow();
+ });
+ return getAuthorizationFromScoped(scopedUserAdmin, user);
+ }
+
+ if (user instanceof CmsUser) {
+ return new LdifAuthorization(user, getAllRoles((CmsUser) user));
+ } else {
+ // bind with authenticating user
+ DirectoryUserAdmin scopedUserAdmin = scope(user).orElseThrow();
+ return getAuthorizationFromScoped(scopedUserAdmin, user);
+ }
+ }
+ }
+
+ private Authorization getAuthorizationFromScoped(DirectoryUserAdmin scopedUserAdmin, User user) {
+ try {
+ CmsUser directoryUser = (CmsUser) scopedUserAdmin.getRole(user.getName());
+ if (directoryUser == null)
+ throw new IllegalStateException("No scoped user found for " + user);
+ LdifAuthorization authorization = new LdifAuthorization(directoryUser,
+ scopedUserAdmin.getAllRoles(directoryUser));
+ return authorization;
+ } finally {
+ scopedUserAdmin.destroy();
+ }
+ }
+
+ @Override
+ public Role createRole(String name, int type) {
+ checkEdit();
+ LdapEntryWorkingCopy wc = getWorkingCopy();
+ LdapName dn = toLdapName(name);
+ if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
+ || wc.getNewData().containsKey(dn))
+ throw new IllegalArgumentException("Already a role " + name);
+ BasicAttributes attrs = new BasicAttributes(true);
+ // attrs.put(LdifName.dn.name(), dn.toString());
+ Rdn nameRdn = dn.getRdn(dn.size() - 1);
+ // TODO deal with multiple attr RDN
+ attrs.put(nameRdn.getType(), nameRdn.getValue());
+ if (wc.getDeletedData().containsKey(dn)) {
+ wc.getDeletedData().remove(dn);
+ wc.getModifiedData().put(dn, attrs);
+ return getRole(name);
+ } else {
+ wc.getModifiedData().put(dn, attrs);
+ LdapEntry newRole = doCreateRole(dn, type, attrs);
+ wc.getNewData().put(dn, newRole);
+ return (Role) newRole;
+ }
+ }
+
+ private LdapEntry doCreateRole(LdapName dn, int type, Attributes attrs) {
+ LdapEntry newRole;
+ BasicAttribute objClass = new BasicAttribute(objectClass.name());
+ if (type == Role.USER) {
+ String userObjClass = getUserObjectClass();
+ objClass.add(userObjClass);
+ if (inetOrgPerson.name().equals(userObjClass)) {
+ objClass.add(organizationalPerson.name());
+ objClass.add(person.name());
+ } else if (organizationalPerson.name().equals(userObjClass)) {
+ objClass.add(person.name());
+ }
+ objClass.add(top.name());
+ objClass.add(extensibleObject.name());
+ attrs.put(objClass);
+ newRole = newUser(dn);
+ } else if (type == Role.GROUP) {
+ String groupObjClass = getGroupObjectClass();
+ objClass.add(groupObjClass);
+ // objClass.add(LdifName.extensibleObject.name());
+ objClass.add(top.name());
+ attrs.put(objClass);
+ newRole = newGroup(dn);
+ } else
+ throw new IllegalArgumentException("Unsupported type " + type);
+ return newRole;
+ }
+
+ @Override
+ public boolean removeRole(String name) {
+ return removeEntry(LdapNameUtils.toLdapName(name));
+ }
+
+ /*
+ * HIERARCHY
+ */
+ @Override
+ public HierarchyUnit getHierarchyUnit(Role role) {
+ LdapName dn = LdapNameUtils.toLdapName(role.getName());
+ LdapName huDn = LdapNameUtils.getParent(dn);
+ HierarchyUnit hierarchyUnit = getDirectoryDao().doGetHierarchyUnit(huDn);
+ if (hierarchyUnit == null)
+ throw new IllegalStateException("No hierarchy unit found for " + role);
+ return hierarchyUnit;
+ }
+
+ @Override
+ public Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) {
+ LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getBase());
+ try {
+ return getRoles(dn, filter, deep);
+ } catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Cannot filter " + filter + " " + dn, e);
+ }
+ }
+
+ /*
+ * ROLES CREATION
+ */
+ protected LdapEntry newUser(LdapName name) {
+ // TODO support devices, applications, etc.
+ return new LdifUser(this, name);
+ }
+
+ protected LdapEntry newGroup(LdapName name) {
+ return new LdifGroup(this, name);
+
+ }
+
+ // GETTERS
+ protected UserAdmin getExternalRoles() {
+ return externalRoles;
+ }
+
+ public void setExternalRoles(UserAdmin externalRoles) {
+ this.externalRoles = externalRoles;
+ }
+
+ /*
+ * STATIC UTILITIES
+ */
+ static LdapName toLdapName(String name) {
+ try {
+ return new LdapName(name);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException(name + " is not an LDAP name", e);
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.List;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.osgi.service.useradmin.Authorization;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+
+/** Basic authorization. */
+class LdifAuthorization implements Authorization {
+ private final String name;
+ private final String displayName;
+ private final List<String> allRoles;
+
+ public LdifAuthorization(User user, List<Role> allRoles) {
+ if (user == null) {
+ this.name = null;
+ this.displayName = "anonymous";
+ } else {
+ this.name = user.getName();
+ this.displayName = extractDisplayName(user);
+ }
+ // roles
+ String[] roles = new String[allRoles.size()];
+ for (int i = 0; i < allRoles.size(); i++) {
+ roles[i] = allRoles.get(i).getName();
+ }
+ this.allRoles = Collections.unmodifiableList(Arrays.asList(roles));
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean hasRole(String name) {
+ return allRoles.contains(name);
+ }
+
+ @Override
+ public String[] getRoles() {
+ return allRoles.toArray(new String[allRoles.size()]);
+ }
+
+ @Override
+ public int hashCode() {
+ if (name == null)
+ return super.hashCode();
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Authorization))
+ return false;
+ Authorization that = (Authorization) obj;
+ if (name == null)
+ return that.getName() == null;
+ return name.equals(that.getName());
+ }
+
+ @Override
+ public String toString() {
+ return displayName;
+ }
+
+ final static String extractDisplayName(User user) {
+ Dictionary<String, Object> props = user.getProperties();
+ Object displayName = props.get(LdapAttr.displayName.name());
+ if (displayName == null)
+ displayName = props.get(LdapAttr.cn.name());
+ if (displayName == null)
+ displayName = props.get(LdapAttr.uid.name());
+ if (displayName == null)
+ displayName = user.getName();
+ if (displayName == null)
+ throw new IllegalStateException("Cannot set display name for " + user);
+ return displayName.toString();
+ }
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.InvalidNameException;
+import javax.naming.directory.Attribute;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.directory.CmsGroup;
+import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
+import org.osgi.service.useradmin.Role;
+
+/** Directory group implementation */
+class LdifGroup extends LdifUser implements CmsGroup {
+ private final String memberAttributeId;
+
+ LdifGroup(AbstractLdapDirectory userAdmin, LdapName dn) {
+ super(userAdmin, dn);
+ memberAttributeId = userAdmin.getMemberAttributeId();
+ }
+
+ @Override
+ public boolean addMember(Role role) {
+ try {
+ Role foundRole = findRole(new LdapName(role.getName()));
+ if (foundRole == null)
+ throw new UnsupportedOperationException(
+ "Adding role " + role.getName() + " is unsupported within this context.");
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Role name" + role.getName() + " is badly formatted");
+ }
+
+ getUserAdmin().checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ Attribute member = getAttributes().get(memberAttributeId);
+ if (member != null) {
+ if (member.contains(role.getName()))
+ return false;
+ else
+ member.add(role.getName());
+ } else
+ getAttributes().put(memberAttributeId, role.getName());
+ return true;
+ }
+
+ @Override
+ public boolean addRequiredMember(Role role) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean removeMember(Role role) {
+ getUserAdmin().checkEdit();
+ if (!isEditing())
+ startEditing();
+
+ Attribute member = getAttributes().get(memberAttributeId);
+ if (member != null) {
+ if (!member.contains(role.getName()))
+ return false;
+ member.remove(role.getName());
+ return true;
+ } else
+ return false;
+ }
+
+ @Override
+ public Role[] getMembers() {
+ List<Role> directMembers = new ArrayList<Role>();
+ for (LdapName ldapName : getReferences(memberAttributeId)) {
+ Role role = findRole(ldapName);
+ if (role == null) {
+ throw new IllegalStateException("Role " + ldapName + " not found.");
+ }
+ directMembers.add(role);
+ }
+ return directMembers.toArray(new Role[directMembers.size()]);
+ }
+
+ /**
+ * Whether a role with this name can be found from this context.
+ *
+ * @return The related {@link Role} or <code>null</code>.
+ */
+ protected Role findRole(LdapName ldapName) {
+ Role role = getUserAdmin().getRole(ldapName.toString());
+ if (role == null) {
+ if (getUserAdmin().getExternalRoles() != null)
+ role = getUserAdmin().getExternalRoles().getRole(ldapName.toString());
+ }
+ return role;
+ }
+
+// @Override
+// public List<LdapName> getMemberNames() {
+// Attribute memberAttribute = getAttributes().get(memberAttributeId);
+// if (memberAttribute == null)
+// return new ArrayList<LdapName>();
+// try {
+// List<LdapName> roles = new ArrayList<LdapName>();
+// NamingEnumeration<?> values = memberAttribute.getAll();
+// while (values.hasMore()) {
+// LdapName dn = new LdapName(values.next().toString());
+// roles.add(dn);
+// }
+// return roles;
+// } catch (NamingException e) {
+// throw new IllegalStateException("Cannot get members", e);
+// }
+// }
+
+ @Override
+ public Role[] getRequiredMembers() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getType() {
+ return GROUP;
+ }
+
+ protected DirectoryUserAdmin getUserAdmin() {
+ return (DirectoryUserAdmin) getDirectory();
+ }
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.cms.directory.CmsUser;
+import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
+import org.argeo.cms.directory.ldap.DefaultLdapEntry;
+
+/** Directory user implementation */
+class LdifUser extends DefaultLdapEntry implements CmsUser {
+ LdifUser(AbstractLdapDirectory userAdmin, LdapName dn) {
+ super(userAdmin, dn);
+ }
+
+ @Override
+ public String getName() {
+ return getDn().toString();
+ }
+
+ @Override
+ public int getType() {
+ return USER;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.api.acr.ldap.LdapAttr;
+import org.argeo.api.cms.directory.HierarchyUnit;
+import org.argeo.cms.directory.ldap.AbstractLdapDirectory;
+import org.argeo.cms.directory.ldap.AbstractLdapDirectoryDao;
+import org.argeo.cms.directory.ldap.LdapEntry;
+import org.argeo.cms.directory.ldap.LdapEntryWorkingCopy;
+
+/** Pseudo user directory to be used when logging in as OS user. */
+public class OsUserDirectory extends AbstractLdapDirectoryDao {
+ private final String osUsername = System.getProperty("user.name");
+ private final LdapName osUserDn;
+ private final LdapEntry osUser;
+
+ public OsUserDirectory(AbstractLdapDirectory directory) {
+ super(directory);
+ try {
+ osUserDn = new LdapName(LdapAttr.uid.name() + "=" + osUsername + "," + directory.getUserBaseRdn() + ","
+ + directory.getBaseDn());
+// Attributes attributes = new BasicAttributes();
+// attributes.put(LdapAttrs.uid.name(), osUsername);
+ osUser = newUser(osUserDn);
+ } catch (NamingException e) {
+ throw new IllegalStateException("Cannot create system user", e);
+ }
+ }
+
+ @Override
+ public List<LdapName> getDirectGroups(LdapName dn) {
+ return new ArrayList<>();
+ }
+
+ @Override
+ public boolean entryExists(LdapName dn) {
+ return osUserDn.equals(dn);
+ }
+
+ @Override
+ public boolean checkConnection() {
+ return true;
+ }
+
+ @Override
+ public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
+ if (osUserDn.equals(key))
+ return osUser;
+ else
+ throw new NameNotFoundException("Not an OS role");
+ }
+
+ @Override
+ public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
+ List<LdapEntry> res = new ArrayList<>();
+// if (f == null || f.match(osUser.getProperties()))
+ res.add(osUser);
+ return res;
+ }
+
+ @Override
+ public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
+ return null;
+ }
+
+ @Override
+ public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
+ return new ArrayList<>();
+ }
+
+ public void prepare(LdapEntryWorkingCopy wc) {
+
+ }
+
+ public void commit(LdapEntryWorkingCopy wc) {
+
+ }
+
+ public void rollback(LdapEntryWorkingCopy wc) {
+
+ }
+
+ @Override
+ public void init() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void destroy() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public Attributes doGetAttributes(LdapName name) {
+ try {
+ return doGetEntry(name).getAttributes();
+ } catch (NameNotFoundException e) {
+ throw new IllegalStateException(name + " doe not exist in " + getDirectory().getBaseDn(), e);
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.NoSuchAlgorithmException;
+import java.security.URIParameter;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+/** Log in based on JDK-provided OS integration. */
+public class OsUserUtils {
+ private final static String LOGIN_CONTEXT_USER_NIX = "USER_NIX";
+ private final static String LOGIN_CONTEXT_USER_NT = "USER_NT";
+
+ public static String getOsUsername() {
+ return System.getProperty("user.name");
+ }
+
+ public static LoginContext loginAsSystemUser(Subject subject) {
+ try {
+ URL jaasConfigurationUrl = OsUserUtils.class.getClassLoader()
+ .getResource("org/argeo/osgi/useradmin/jaas-os.cfg");
+ URIParameter uriParameter = new URIParameter(jaasConfigurationUrl.toURI());
+ Configuration jaasConfiguration = Configuration.getInstance("JavaLoginConfig", uriParameter);
+ LoginContext lc = new LoginContext(isWindows() ? LOGIN_CONTEXT_USER_NT : LOGIN_CONTEXT_USER_NIX, subject,
+ null, jaasConfiguration);
+ lc.login();
+ return lc;
+ } catch (URISyntaxException | NoSuchAlgorithmException | LoginException e) {
+ throw new RuntimeException("Cannot login as system user", e);
+ }
+ }
+
+ public static void main(String args[]) {
+ Subject subject = new Subject();
+ LoginContext loginContext = loginAsSystemUser(subject);
+ System.out.println(subject);
+ try {
+ loginContext.logout();
+ } catch (LoginException e) {
+ // silent
+ }
+ }
+
+ private static boolean isWindows() {
+ return System.getProperty("os.name").startsWith("Windows");
+ }
+
+ private OsUserUtils() {
+ }
+}
--- /dev/null
+package org.argeo.cms.osgi.useradmin;
+
+import static org.argeo.api.acr.ldap.LdapAttr.description;
+import static org.argeo.api.acr.ldap.LdapAttr.owner;
+
+import java.security.Principal;
+import java.time.Instant;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+import javax.security.auth.Subject;
+
+import org.argeo.api.acr.ldap.NamingUtils;
+import org.osgi.service.useradmin.Group;
+
+/**
+ * Canonically implements the Argeo token conventions.
+ */
+public class TokenUtils {
+ public static Set<String> tokensUsed(Subject subject, String tokensBaseDn) {
+ Set<String> res = new HashSet<>();
+ for (Principal principal : subject.getPrincipals()) {
+ String name = principal.getName();
+ if (name.endsWith(tokensBaseDn)) {
+ try {
+ LdapName ldapName = new LdapName(name);
+ String token = ldapName.getRdn(ldapName.size()).getValue().toString();
+ res.add(token);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Invalid principal " + principal, e);
+ }
+ }
+ }
+ return res;
+ }
+
+ /** The user related to this token group */
+ public static String userDn(Group tokenGroup) {
+ return (String) tokenGroup.getProperties().get(owner.name());
+ }
+
+ public static boolean isExpired(Group tokenGroup) {
+ return isExpired(tokenGroup, Instant.now());
+
+ }
+
+ public static boolean isExpired(Group tokenGroup, Instant instant) {
+ String expiryDateStr = (String) tokenGroup.getProperties().get(description.name());
+ if (expiryDateStr != null) {
+ Instant expiryDate = NamingUtils.ldapDateToInstant(expiryDateStr);
+ if (expiryDate.isBefore(instant)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+// private final String token;
+//
+// public TokenUtils(String token) {
+// this.token = token;
+// }
+//
+// public String getToken() {
+// return token;
+// }
+//
+// @Override
+// public int hashCode() {
+// return token.hashCode();
+// }
+//
+// @Override
+// public boolean equals(Object obj) {
+// if ((obj instanceof TokenUtils) && ((TokenUtils) obj).token.equals(token))
+// return true;
+// return false;
+// }
+//
+// @Override
+// public String toString() {
+// return "Token #" + hashCode();
+// }
+
+}
--- /dev/null
+USER_NIX {
+ com.sun.security.auth.module.UnixLoginModule requisite;
+};
+
+USER_NT {
+ com.sun.security.auth.module.NTLoginModule requisite;
+};
+
--- /dev/null
+/** LDAP and LDIF based OSGi useradmin implementation. */
+package org.argeo.cms.osgi.useradmin;
\ No newline at end of file
--- /dev/null
+package org.argeo.cms.runtime;
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.UnknownHostException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.argeo.api.acr.ldap.NamingUtils;
+import org.argeo.api.cms.directory.DirectoryDigestUtils;
+import org.argeo.cms.directory.ldap.IpaUtils;
+
+/** Properties used to configure user admins. */
+public enum DirectoryConf {
+ /** Base DN (cannot be configured externally) */
+ baseDn(null),
+
+ /** URI of the underlying resource (cannot be configured externally) */
+ uri(null),
+
+ /** User objectClass */
+ userObjectClass("inetOrgPerson"),
+
+ /** Relative base DN for users */
+ userBase("ou=People"),
+
+ /** Groups objectClass */
+ groupObjectClass("groupOfNames"),
+
+ /** Relative base DN for users */
+ groupBase("ou=Groups"),
+
+ /** Relative base DN for users */
+ systemRoleBase("ou=Roles"),
+
+ /** Read-only source */
+ readOnly(null),
+
+ /** Disabled source */
+ disabled(null),
+
+ /** Authentication realm */
+ realm(null),
+
+ /** Override all passwords with this value (typically for testing purposes) */
+ forcedPassword(null);
+
+ public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config";
+
+ public final static String SCHEME_LDAP = "ldap";
+ public final static String SCHEME_LDAPS = "ldaps";
+ public final static String SCHEME_FILE = "file";
+ public final static String SCHEME_OS = "os";
+ public final static String SCHEME_IPA = "ipa";
+
+ private final static String SECURITY_PRINCIPAL = "java.naming.security.principal";
+ private final static String SECURITY_CREDENTIALS = "java.naming.security.credentials";
+
+ /** The default value. */
+ private Object def;
+
+ DirectoryConf(Object def) {
+ this.def = def;
+ }
+
+ public Object getDefault() {
+ return def;
+ }
+
+ /**
+ * For use as Java property.
+ *
+ * @deprecated use {@link #name()} instead
+ */
+ @Deprecated
+ public String property() {
+ return name();
+ }
+
+ public String getValue(Dictionary<String, ?> properties) {
+ Object res = getRawValue(properties);
+ if (res == null)
+ return null;
+ return res.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getRawValue(Dictionary<String, ?> properties) {
+ Object res = properties.get(name());
+ if (res == null)
+ res = getDefault();
+ return (T) res;
+ }
+
+ /** @deprecated use {@link #valueOf(String)} instead */
+ @Deprecated
+ public static DirectoryConf local(String property) {
+ return DirectoryConf.valueOf(property);
+ }
+
+ /** Hides host and credentials. */
+ public static URI propertiesAsUri(Dictionary<String, ?> properties) {
+ StringBuilder query = new StringBuilder();
+
+ boolean first = true;
+// for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
+// String key = keys.nextElement();
+// // TODO clarify which keys are relevant (list only the enum?)
+// if (!key.equals("service.factoryPid") && !key.equals("cn") && !key.equals("dn")
+// && !key.equals(Constants.SERVICE_PID) && !key.startsWith("java") && !key.equals(baseDn.name())
+// && !key.equals(uri.name()) && !key.equals(Constants.OBJECTCLASS)
+// && !key.equals(Constants.SERVICE_ID) && !key.equals("bundle.id")) {
+// if (first)
+// first = false;
+// else
+// query.append('&');
+// query.append(valueOf(key).name());
+// query.append('=').append(properties.get(key).toString());
+// }
+// }
+
+ keys: for (DirectoryConf key : DirectoryConf.values()) {
+ if (key.equals(baseDn) || key.equals(uri))
+ continue keys;
+ Object value = properties.get(key.name());
+ if (value == null)
+ continue keys;
+ if (first)
+ first = false;
+ else
+ query.append('&');
+ query.append(key.name());
+ query.append('=').append(value.toString());
+
+ }
+
+ Object bDnObj = properties.get(baseDn.name());
+ String bDn = bDnObj != null ? bDnObj.toString() : null;
+ try {
+ return new URI(null, null, bDn != null ? '/' + bDn : null, query.length() != 0 ? query.toString() : null,
+ null);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Cannot create URI from properties", e);
+ }
+ }
+
+ public static Dictionary<String, Object> uriAsProperties(String uriStr) {
+ try {
+ Hashtable<String, Object> res = new Hashtable<String, Object>();
+ URI u = new URI(uriStr);
+ String scheme = u.getScheme();
+ if (scheme != null && scheme.equals(SCHEME_IPA)) {
+ return IpaUtils.convertIpaUri(u);
+// scheme = u.getScheme();
+ }
+ String path = u.getPath();
+ // base DN
+ String bDn = path.substring(path.lastIndexOf('/') + 1, path.length());
+ if (bDn.equals("") && SCHEME_OS.equals(scheme)) {
+ bDn = getBaseDnFromHostname();
+ }
+
+ if (bDn.endsWith(".ldif"))
+ bDn = bDn.substring(0, bDn.length() - ".ldif".length());
+
+ // Normalize base DN as LDAP name
+// bDn = new LdapName(bDn).toString();
+
+ String principal = null;
+ String credentials = null;
+ if (scheme != null)
+ if (scheme.equals(SCHEME_LDAP) || scheme.equals(SCHEME_LDAPS)) {
+ // TODO additional checks
+ if (u.getUserInfo() != null) {
+ String[] userInfo = u.getUserInfo().split(":");
+ principal = userInfo.length > 0 ? userInfo[0] : null;
+ credentials = userInfo.length > 1 ? userInfo[1] : null;
+ }
+ } else if (scheme.equals(SCHEME_FILE)) {
+ } else if (scheme.equals(SCHEME_IPA)) {
+ } else if (scheme.equals(SCHEME_OS)) {
+ } else
+ throw new IllegalArgumentException("Unsupported scheme " + scheme);
+ Map<String, List<String>> query = NamingUtils.queryToMap(u);
+ for (String key : query.keySet()) {
+ DirectoryConf ldapProp = DirectoryConf.valueOf(key);
+ List<String> values = query.get(key);
+ if (values.size() == 1) {
+ res.put(ldapProp.name(), values.get(0));
+ } else {
+ throw new IllegalArgumentException("Only single values are supported");
+ }
+ }
+ res.put(baseDn.name(), bDn);
+ if (SCHEME_OS.equals(scheme))
+ res.put(readOnly.name(), "true");
+ if (principal != null)
+ res.put(SECURITY_PRINCIPAL, principal);
+ if (credentials != null)
+ res.put(SECURITY_CREDENTIALS, credentials);
+ if (scheme != null) {// relative URIs are dealt with externally
+ if (SCHEME_OS.equals(scheme)) {
+ res.put(uri.name(), SCHEME_OS + ":///");
+ } else {
+ URI bareUri = new URI(scheme, null, u.getHost(), u.getPort(),
+ scheme.equals(SCHEME_FILE) ? u.getPath() : null, null, null);
+ res.put(uri.name(), bareUri.toString());
+ }
+ }
+ return res;
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Cannot convert " + uri + " to properties", e);
+ }
+ }
+
+ private static String getBaseDnFromHostname() {
+ String hostname;
+ try {
+ hostname = InetAddress.getLocalHost().getHostName();
+ } catch (UnknownHostException e) {
+ hostname = "localhost.localdomain";
+ }
+ int dotIdx = hostname.indexOf('.');
+ if (dotIdx >= 0) {
+ String domain = hostname.substring(dotIdx + 1, hostname.length());
+ String bDn = ("." + domain).replaceAll("\\.", ",dc=");
+ bDn = bDn.substring(1, bDn.length());
+ return bDn;
+ } else {
+ return "dc=" + hostname;
+ }
+ }
+
+ /**
+ * Hash the base DN in order to have a deterministic string to be used as a cn
+ * for the underlying user directory.
+ */
+ public static String baseDnHash(Dictionary<String, Object> properties) {
+ String bDn = (String) properties.get(baseDn.name());
+ if (bDn == null)
+ throw new IllegalStateException("No baseDn in " + properties);
+ return DirectoryDigestUtils.sha1str(bDn);
+ }
+}
import org.argeo.api.cms.CmsContext;
import org.argeo.api.cms.CmsDeployment;
import org.argeo.api.cms.CmsState;
+import org.argeo.api.cms.directory.CmsUserManager;
+import org.argeo.api.cms.transaction.SimpleTransactionManager;
+import org.argeo.api.cms.transaction.WorkControl;
+import org.argeo.api.cms.transaction.WorkTransaction;
+import org.argeo.api.register.Component;
+import org.argeo.api.register.ComponentRegister;
+import org.argeo.api.register.SimpleRegister;
import org.argeo.api.uuid.UuidFactory;
-import org.argeo.cms.CmsUserManager;
import org.argeo.cms.acr.CmsUuidFactory;
-import org.argeo.cms.internal.auth.CmsUserManagerImpl;
import org.argeo.cms.internal.runtime.CmsContextImpl;
import org.argeo.cms.internal.runtime.CmsDeploymentImpl;
import org.argeo.cms.internal.runtime.CmsStateImpl;
import org.argeo.cms.internal.runtime.CmsUserAdmin;
+import org.argeo.cms.internal.runtime.CmsUserManagerImpl;
import org.argeo.cms.internal.runtime.DeployedContentRepository;
-import org.argeo.util.register.Component;
-import org.argeo.util.register.ComponentRegister;
-import org.argeo.util.register.SimpleRegister;
-import org.argeo.util.transaction.SimpleTransactionManager;
-import org.argeo.util.transaction.WorkControl;
-import org.argeo.util.transaction.WorkTransaction;
import org.osgi.service.useradmin.UserAdmin;
/**
+++ /dev/null
-package org.argeo.cms.security;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.CharArrayWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.Reader;
-import java.io.Writer;
-import java.security.Provider;
-import java.security.Security;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import javax.crypto.SecretKey;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.TextOutputCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.argeo.api.cms.CmsAuth;
-import org.argeo.util.CurrentSubject;
-import org.argeo.util.StreamUtils;
-
-/** username / password based keyring. TODO internationalize */
-public abstract class AbstractKeyring implements Keyring, CryptoKeyring {
- // public final static String DEFAULT_KEYRING_LOGIN_CONTEXT = "KEYRING";
-
- // private String loginContextName = DEFAULT_KEYRING_LOGIN_CONTEXT;
- private CallbackHandler defaultCallbackHandler;
-
- private String charset = "UTF-8";
-
- /**
- * Default provider is bouncy castle, in order to have consistent behaviour
- * across implementations
- */
- private String securityProviderName = "BC";
-
- /**
- * Whether the keyring has already been created in the past with a master
- * password
- */
- protected abstract Boolean isSetup();
-
- /**
- * Setup the keyring persistently, {@link #isSetup()} must return true
- * afterwards
- */
- protected abstract void setup(char[] password);
-
- /** Populates the key spec callback */
- protected abstract void handleKeySpecCallback(PBEKeySpecCallback pbeCallback);
-
- protected abstract void encrypt(String path, InputStream unencrypted);
-
- protected abstract InputStream decrypt(String path);
-
- /** Triggers lazy initialization */
- protected SecretKey getSecretKey(char[] password) {
- Subject subject = CurrentSubject.current();
- if (subject == null)
- throw new IllegalStateException("Current subject cannot be null");
- // we assume only one secrete key is available
- Iterator<SecretKey> iterator = subject.getPrivateCredentials(SecretKey.class).iterator();
- if (!iterator.hasNext() || password != null) {// not initialized
- CallbackHandler callbackHandler = password == null ? new KeyringCallbackHandler()
- : new PasswordProvidedCallBackHandler(password);
- ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
- try {
- LoginContext loginContext = new LoginContext(CmsAuth.LOGIN_CONTEXT_KEYRING, subject, callbackHandler);
- loginContext.login();
- // FIXME will login even if password is wrong
- iterator = subject.getPrivateCredentials(SecretKey.class).iterator();
- return iterator.next();
- } catch (LoginException e) {
- throw new IllegalStateException("Keyring login failed", e);
- } finally {
- Thread.currentThread().setContextClassLoader(currentContextClassLoader);
- }
-
- } else {
- SecretKey secretKey = iterator.next();
- if (iterator.hasNext())
- throw new IllegalStateException("More than one secret key in private credentials");
- return secretKey;
- }
- }
-
- public InputStream getAsStream(String path) {
- return decrypt(path);
- }
-
- public void set(String path, InputStream in) {
- encrypt(path, in);
- }
-
- public char[] getAsChars(String path) {
- // InputStream in = getAsStream(path);
- // CharArrayWriter writer = null;
- // Reader reader = null;
- try (InputStream in = getAsStream(path);
- CharArrayWriter writer = new CharArrayWriter();
- Reader reader = new InputStreamReader(in, charset);) {
- StreamUtils.copy(reader, writer);
- return writer.toCharArray();
- } catch (IOException e) {
- throw new IllegalStateException("Cannot decrypt to char array", e);
- } finally {
- // IOUtils.closeQuietly(reader);
- // IOUtils.closeQuietly(in);
- // IOUtils.closeQuietly(writer);
- }
- }
-
- public void set(String path, char[] arr) {
- // ByteArrayOutputStream out = new ByteArrayOutputStream();
- // ByteArrayInputStream in = null;
- // Writer writer = null;
- try (ByteArrayOutputStream out = new ByteArrayOutputStream();
- Writer writer = new OutputStreamWriter(out, charset);) {
- // writer = new OutputStreamWriter(out, charset);
- writer.write(arr);
- writer.flush();
- // in = new ByteArrayInputStream(out.toByteArray());
- try (ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());) {
- set(path, in);
- }
- } catch (IOException e) {
- throw new IllegalStateException("Cannot encrypt to char array", e);
- } finally {
- // IOUtils.closeQuietly(writer);
- // IOUtils.closeQuietly(out);
- // IOUtils.closeQuietly(in);
- }
- }
-
- public void unlock(char[] password) {
- if (!isSetup())
- setup(password);
- SecretKey secretKey = getSecretKey(password);
- if (secretKey == null)
- throw new IllegalStateException("Could not unlock keyring");
- }
-
- protected Provider getSecurityProvider() {
- return Security.getProvider(securityProviderName);
- }
-
- public void setDefaultCallbackHandler(CallbackHandler defaultCallbackHandler) {
- this.defaultCallbackHandler = defaultCallbackHandler;
- }
-
- public void setCharset(String charset) {
- this.charset = charset;
- }
-
- public void setSecurityProviderName(String securityProviderName) {
- this.securityProviderName = securityProviderName;
- }
-
- // @Deprecated
- // protected static byte[] hash(char[] password, byte[] salt, Integer
- // iterationCount) {
- // ByteArrayOutputStream out = null;
- // OutputStreamWriter writer = null;
- // try {
- // out = new ByteArrayOutputStream();
- // writer = new OutputStreamWriter(out, "UTF-8");
- // writer.write(password);
- // MessageDigest pwDigest = MessageDigest.getInstance("SHA-256");
- // pwDigest.reset();
- // pwDigest.update(salt);
- // byte[] btPass = pwDigest.digest(out.toByteArray());
- // for (int i = 0; i < iterationCount; i++) {
- // pwDigest.reset();
- // btPass = pwDigest.digest(btPass);
- // }
- // return btPass;
- // } catch (Exception e) {
- // throw new CmsException("Cannot hash", e);
- // } finally {
- // IOUtils.closeQuietly(out);
- // IOUtils.closeQuietly(writer);
- // }
- //
- // }
-
- /**
- * Convenience method using the underlying callback to ask for a password
- * (typically used when the password is not saved in the keyring)
- */
- protected char[] ask() {
- PasswordCallback passwordCb = new PasswordCallback("Password", false);
- Callback[] dialogCbs = new Callback[] { passwordCb };
- try {
- defaultCallbackHandler.handle(dialogCbs);
- char[] password = passwordCb.getPassword();
- return password;
- } catch (Exception e) {
- throw new IllegalStateException("Cannot ask for a password", e);
- }
-
- }
-
- class KeyringCallbackHandler implements CallbackHandler {
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- // checks
- if (callbacks.length != 2)
- throw new IllegalArgumentException(
- "Keyring requires 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}");
- if (!(callbacks[0] instanceof PasswordCallback))
- throw new UnsupportedCallbackException(callbacks[0]);
- if (!(callbacks[1] instanceof PBEKeySpecCallback))
- throw new UnsupportedCallbackException(callbacks[0]);
-
- PasswordCallback passwordCb = (PasswordCallback) callbacks[0];
- PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1];
-
- if (isSetup()) {
- Callback[] dialogCbs = new Callback[] { passwordCb };
- defaultCallbackHandler.handle(dialogCbs);
- } else {// setup keyring
- TextOutputCallback textCb1 = new TextOutputCallback(TextOutputCallback.INFORMATION,
- "Enter a master password which will protect your private data");
- TextOutputCallback textCb2 = new TextOutputCallback(TextOutputCallback.INFORMATION,
- "(for example your credentials to third-party services)");
- TextOutputCallback textCb3 = new TextOutputCallback(TextOutputCallback.INFORMATION,
- "Don't forget this password since the data cannot be read without it");
- PasswordCallback confirmPasswordCb = new PasswordCallback("Confirm password", false);
- // first try
- Callback[] dialogCbs = new Callback[] { textCb1, textCb2, textCb3, passwordCb, confirmPasswordCb };
- defaultCallbackHandler.handle(dialogCbs);
-
- // if passwords different, retry (except if cancelled)
- while (passwordCb.getPassword() != null
- && !Arrays.equals(passwordCb.getPassword(), confirmPasswordCb.getPassword())) {
- TextOutputCallback textCb = new TextOutputCallback(TextOutputCallback.ERROR,
- "The passwords do not match");
- dialogCbs = new Callback[] { textCb, passwordCb, confirmPasswordCb };
- defaultCallbackHandler.handle(dialogCbs);
- }
-
- if (passwordCb.getPassword() != null) {// not cancelled
- setup(passwordCb.getPassword());
- }
- }
-
- if (passwordCb.getPassword() != null)
- handleKeySpecCallback(pbeCb);
- }
-
- }
-
- class PasswordProvidedCallBackHandler implements CallbackHandler {
- private final char[] password;
-
- public PasswordProvidedCallBackHandler(char[] password) {
- this.password = password;
- }
-
- @Override
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- // checks
- if (callbacks.length != 2)
- throw new IllegalArgumentException(
- "Keyring requires 2 and only 2 callbacks: {PasswordCallback,PBEKeySpecCallback}");
- if (!(callbacks[0] instanceof PasswordCallback))
- throw new UnsupportedCallbackException(callbacks[0]);
- if (!(callbacks[1] instanceof PBEKeySpecCallback))
- throw new UnsupportedCallbackException(callbacks[0]);
-
- PasswordCallback passwordCb = (PasswordCallback) callbacks[0];
- passwordCb.setPassword(password);
- PBEKeySpecCallback pbeCb = (PBEKeySpecCallback) callbacks[1];
- handleKeySpecCallback(pbeCb);
- }
-
- }
-}
+++ /dev/null
-package org.argeo.cms.security;
-
-import java.io.IOException;
-import java.math.BigInteger;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Base64;
-import java.util.zip.Checksum;
-
-/** Allows to fine tune how files are read. */
-public class ChecksumFactory {
- private int regionSize = 10 * 1024 * 1024;
-
- public byte[] digest(Path path, final String algo) {
- try {
- final MessageDigest md = MessageDigest.getInstance(algo);
- if (Files.isDirectory(path)) {
- long begin = System.currentTimeMillis();
- Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- if (!Files.isDirectory(file)) {
- byte[] digest = digest(file, algo);
- md.update(digest);
- }
- return FileVisitResult.CONTINUE;
- }
-
- });
- byte[] digest = md.digest();
- long duration = System.currentTimeMillis() - begin;
- System.out.println(printBase64Binary(digest) + " " + path + " (" + duration / 1000 + "s)");
- return digest;
- } else {
- long begin = System.nanoTime();
- long length = -1;
- try (FileChannel channel = (FileChannel) Files.newByteChannel(path);) {
- length = channel.size();
- long cursor = 0;
- while (cursor < length) {
- long effectiveSize = Math.min(regionSize, length - cursor);
- MappedByteBuffer mb = channel.map(FileChannel.MapMode.READ_ONLY, cursor, effectiveSize);
- // md.update(mb);
- byte[] buffer = new byte[1024];
- while (mb.hasRemaining()) {
- mb.get(buffer);
- md.update(buffer);
- }
-
- // sub digest
- // mb.flip();
- // MessageDigest subMd =
- // MessageDigest.getInstance(algo);
- // subMd.update(mb);
- // byte[] subDigest = subMd.digest();
- // System.out.println(" -> " + cursor);
- // System.out.println(IOUtils.encodeHexString(subDigest));
- // System.out.println(new BigInteger(1,
- // subDigest).toString(16));
- // System.out.println(new BigInteger(1, subDigest)
- // .toString(Character.MAX_RADIX));
- // System.out.println(printBase64Binary(subDigest));
-
- cursor = cursor + regionSize;
- }
- byte[] digest = md.digest();
- long duration = System.nanoTime() - begin;
- System.out.println(printBase64Binary(digest) + " " + path.getFileName() + " (" + duration / 1000000
- + "ms, " + (length / 1024) + "kB, " + (length / (duration / 1000000)) * 1000 / (1024 * 1024)
- + " MB/s)");
- return digest;
- }
- }
- } catch (NoSuchAlgorithmException | IOException e) {
- throw new IllegalStateException("Cannot digest " + path, e);
- }
- }
-
- /** Whether the file should be mapped. */
- protected boolean mapFile(FileChannel fileChannel) throws IOException {
- long size = fileChannel.size();
- if (size > (regionSize / 10))
- return true;
- return false;
- }
-
- public long checksum(Path path, Checksum crc) {
- final int bufferSize = 2 * 1024 * 1024;
- long begin = System.currentTimeMillis();
- try (FileChannel channel = (FileChannel) Files.newByteChannel(path);) {
- byte[] bytes = new byte[bufferSize];
- long length = channel.size();
- long cursor = 0;
- while (cursor < length) {
- long effectiveSize = Math.min(regionSize, length - cursor);
- MappedByteBuffer mb = channel.map(FileChannel.MapMode.READ_ONLY, cursor, effectiveSize);
- int nGet;
- while (mb.hasRemaining()) {
- nGet = Math.min(mb.remaining(), bufferSize);
- mb.get(bytes, 0, nGet);
- crc.update(bytes, 0, nGet);
- }
- cursor = cursor + regionSize;
- }
- return crc.getValue();
- } catch (IOException e) {
- throw new IllegalStateException("Cannot checksum " + path, e);
- } finally {
- long duration = System.currentTimeMillis() - begin;
- System.out.println(duration / 1000 + "s");
- }
- }
-
- public static void main(String... args) {
- ChecksumFactory cf = new ChecksumFactory();
- // Path path =
- // Paths.get("/home/mbaudier/apache-maven-3.2.3-bin.tar.gz");
- Path path;
- if (args.length > 0) {
- path = Paths.get(args[0]);
- } else {
- path = Paths.get("/home/mbaudier/Downloads/torrents/CentOS-7-x86_64-DVD-1503-01/"
- + "CentOS-7-x86_64-DVD-1503-01.iso");
- }
- // long adler = cf.checksum(path, new Adler32());
- // System.out.format("Adler=%d%n", adler);
- // long crc = cf.checksum(path, new CRC32());
- // System.out.format("CRC=%d%n", crc);
- String algo = "SHA1";
- byte[] digest = cf.digest(path, algo);
- System.out.println(algo + " " + printBase64Binary(digest));
- System.out.println(algo + " " + new BigInteger(1, digest).toString(16));
- // String sha1 = printBase64Binary(cf.digest(path, "SHA1"));
- // System.out.format("SHA1=%s%n", sha1);
- }
-
- private static String printBase64Binary(byte[] arr) {
- return Base64.getEncoder().encodeToString(arr);
- }
-}
+++ /dev/null
-package org.argeo.cms.security;
-
-/**
- * Marker interface for an advanced keyring based on cryptography.
- */
-public interface CryptoKeyring extends Keyring {
- public void changePassword(char[] oldPassword, char[] newPassword);
-
- public void unlock(char[] password);
-}
+++ /dev/null
-package org.argeo.cms.security;
-
-import java.io.InputStream;
-
-/**
- * Access to private (typically encrypted) data. The keyring is responsible for
- * retrieving the necessary credentials. <b>Experimental. This API may
- * change.</b>
- */
-public interface Keyring {
- /**
- * Returns the confidential information as chars. Must ask for it if it is
- * not stored.
- */
- public char[] getAsChars(String path);
-
- /**
- * Returns the confidential information as a stream. Must ask for it if it
- * is not stored.
- */
- public InputStream getAsStream(String path);
-
- public void set(String path, char[] arr);
-
- public void set(String path, InputStream in);
-}
+++ /dev/null
-package org.argeo.cms.security;
-
-import javax.crypto.spec.PBEKeySpec;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.PasswordCallback;
-
-/**
- * All information required to set up a {@link PBEKeySpec} bar the password
- * itself (use a {@link PasswordCallback})
- */
-public class PBEKeySpecCallback implements Callback {
- private String secretKeyFactory;
- private byte[] salt;
- private Integer iterationCount;
- /** Can be null for some algorithms */
- private Integer keyLength;
- /** Can be null, will trigger secret key encryption if not */
- private String secretKeyEncryption;
-
- private String encryptedPasswordHashCipher;
- private byte[] encryptedPasswordHash;
-
- public void set(String secretKeyFactory, byte[] salt,
- Integer iterationCount, Integer keyLength,
- String secretKeyEncryption) {
- this.secretKeyFactory = secretKeyFactory;
- this.salt = salt;
- this.iterationCount = iterationCount;
- this.keyLength = keyLength;
- this.secretKeyEncryption = secretKeyEncryption;
-// this.encryptedPasswordHashCipher = encryptedPasswordHashCipher;
-// this.encryptedPasswordHash = encryptedPasswordHash;
- }
-
- public String getSecretKeyFactory() {
- return secretKeyFactory;
- }
-
- public byte[] getSalt() {
- return salt;
- }
-
- public Integer getIterationCount() {
- return iterationCount;
- }
-
- public Integer getKeyLength() {
- return keyLength;
- }
-
- public String getSecretKeyEncryption() {
- return secretKeyEncryption;
- }
-
- public String getEncryptedPasswordHashCipher() {
- return encryptedPasswordHashCipher;
- }
-
- public byte[] getEncryptedPasswordHash() {
- return encryptedPasswordHash;
- }
-
-}
+++ /dev/null
-/** Argeo CMS reusable security components. */
-package org.argeo.cms.security;
\ No newline at end of file
+++ /dev/null
-package org.argeo.cms.tabular;
-
-import java.util.List;
-
-/** Minimal tabular row wrapping an {@link Object} array */
-public class ArrayTabularRow implements TabularRow {
- private final Object[] arr;
-
- public ArrayTabularRow(List<?> objs) {
- this.arr = objs.toArray();
- }
-
- public Object get(Integer col) {
- return arr[col];
- }
-
- public int size() {
- return arr.length;
- }
-
- public Object[] toArray() {
- return arr;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.tabular;
-
-/** The column in a tabular content */
-public class TabularColumn {
- private String name;
- /**
- * JCR types, see
- * http://www.day.com/maven/javax.jcr/javadocs/jcr-2.0/index.html
- * ?javax/jcr/PropertyType.html
- */
- private Integer type;
-
- /** column with default type */
- public TabularColumn(String name) {
- super();
- this.name = name;
- }
-
- public TabularColumn(String name, Integer type) {
- super();
- this.name = name;
- this.type = type;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Integer getType() {
- return type;
- }
-
- public void setType(Integer type) {
- this.type = type;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.tabular;
-
-import java.util.List;
-
-/**
- * Content organized as a table, possibly with headers. Only JCR types are
- * supported even though there is not direct dependency on JCR.
- */
-public interface TabularContent {
- /** The headers of this table or <code>null</code> is none available. */
- public List<TabularColumn> getColumns();
-
- public TabularRowIterator read();
-}
+++ /dev/null
-package org.argeo.cms.tabular;
-
-/** A row of tabular data */
-public interface TabularRow {
- /** The value at this column index */
- public Object get(Integer col);
-
- /** The raw objects (direct references) */
- public Object[] toArray();
-
- /** Number of columns */
- public int size();
-}
+++ /dev/null
-package org.argeo.cms.tabular;
-
-import java.util.Iterator;
-
-/** Navigation of rows */
-public interface TabularRowIterator extends Iterator<TabularRow> {
- /**
- * Current row number, has to be incremented by each call to next() ; starts at 0, will
- * therefore be 1 for the first row returned.
- */
- public Long getCurrentRowNumber();
-}
+++ /dev/null
-package org.argeo.cms.tabular;
-
-
-/** Write to a tabular content */
-public interface TabularWriter {
- /** Append a new row of data */
- public void appendRow(Object[] row);
-
- /** Finish persisting data and release resources */
- public void close();
-}
+++ /dev/null
-/** Tabular format API. */
-package org.argeo.cms.tabular;
\ No newline at end of file
--- /dev/null
+package org.argeo.cms.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringTokenizer;
+
+/** A name that can be expressed with various conventions. */
+public class CompositeString {
+ public final static Character UNDERSCORE = Character.valueOf('_');
+ public final static Character SPACE = Character.valueOf(' ');
+ public final static Character DASH = Character.valueOf('-');
+
+ private final String[] parts;
+
+ // optimisation
+ private final int hashCode;
+
+ public CompositeString(String str) {
+ Objects.requireNonNull(str, "String cannot be null");
+ if ("".equals(str.trim()))
+ throw new IllegalArgumentException("String cannot be empty");
+ if (!str.equals(str.trim()))
+ throw new IllegalArgumentException("String must be trimmed");
+ this.parts = toParts(str);
+ hashCode = hashCode(this.parts);
+ }
+
+ public String toString(char separator, boolean upperCase) {
+ StringBuilder sb = null;
+ for (String part : parts) {
+ if (sb == null) {
+ sb = new StringBuilder();
+ } else {
+ sb.append(separator);
+ }
+ sb.append(upperCase ? part.toUpperCase() : part);
+ }
+ return sb.toString();
+ }
+
+ public String toStringCaml(boolean firstCharUpperCase) {
+ StringBuilder sb = null;
+ for (String part : parts) {
+ if (sb == null) {// first
+ sb = new StringBuilder();
+ sb.append(firstCharUpperCase ? Character.toUpperCase(part.charAt(0)) : part.charAt(0));
+ } else {
+ sb.append(Character.toUpperCase(part.charAt(0)));
+ }
+
+ if (part.length() > 1)
+ sb.append(part.substring(1));
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return hashCode;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof CompositeString))
+ return false;
+
+ CompositeString other = (CompositeString) obj;
+ return Arrays.equals(parts, other.parts);
+ }
+
+ @Override
+ public String toString() {
+ return toString(DASH, false);
+ }
+
+ public static String[] toParts(String str) {
+ Character separator = null;
+ if (str.indexOf(UNDERSCORE) >= 0) {
+ checkNo(str, SPACE);
+ checkNo(str, DASH);
+ separator = UNDERSCORE;
+ } else if (str.indexOf(DASH) >= 0) {
+ checkNo(str, SPACE);
+ checkNo(str, UNDERSCORE);
+ separator = DASH;
+ } else if (str.indexOf(SPACE) >= 0) {
+ checkNo(str, DASH);
+ checkNo(str, UNDERSCORE);
+ separator = SPACE;
+ }
+
+ List<String> res = new ArrayList<>();
+ if (separator != null) {
+ StringTokenizer st = new StringTokenizer(str, separator.toString());
+ while (st.hasMoreTokens()) {
+ res.add(st.nextToken().toLowerCase());
+ }
+ } else {
+ // single
+ String strLowerCase = str.toLowerCase();
+ if (str.toUpperCase().equals(str) || strLowerCase.equals(str))
+ return new String[] { strLowerCase };
+
+ // CAML
+ StringBuilder current = null;
+ for (char c : str.toCharArray()) {
+ if (Character.isUpperCase(c)) {
+ if (current != null)
+ res.add(current.toString());
+ current = new StringBuilder();
+ }
+ if (current == null)// first char is lower case
+ current = new StringBuilder();
+ current.append(Character.toLowerCase(c));
+ }
+ res.add(current.toString());
+ }
+ return res.toArray(new String[res.size()]);
+ }
+
+ private static void checkNo(String str, Character c) {
+ if (str.indexOf(c) >= 0) {
+ throw new IllegalArgumentException("Only one kind of sperator is allowed");
+ }
+ }
+
+ private static int hashCode(String[] parts) {
+ int hashCode = 0;
+ for (String part : parts) {
+ hashCode = hashCode + part.hashCode();
+ }
+ return hashCode;
+ }
+
+ static boolean smokeTests() {
+ CompositeString plainName = new CompositeString("NAME");
+ assert "name".equals(plainName.toString());
+ assert "NAME".equals(plainName.toString(UNDERSCORE, true));
+ assert "name".equals(plainName.toString(UNDERSCORE, false));
+ assert "name".equals(plainName.toStringCaml(false));
+ assert "Name".equals(plainName.toStringCaml(true));
+
+ CompositeString camlName = new CompositeString("myComplexName");
+
+ assert new CompositeString("my-complex-name").equals(camlName);
+ assert new CompositeString("MY_COMPLEX_NAME").equals(camlName);
+ assert new CompositeString("My complex Name").equals(camlName);
+ assert new CompositeString("MyComplexName").equals(camlName);
+
+ assert "my-complex-name".equals(camlName.toString());
+ assert "MY_COMPLEX_NAME".equals(camlName.toString(UNDERSCORE, true));
+ assert "my_complex_name".equals(camlName.toString(UNDERSCORE, false));
+ assert "myComplexName".equals(camlName.toStringCaml(false));
+ assert "MyComplexName".equals(camlName.toStringCaml(true));
+
+ return CompositeString.class.desiredAssertionStatus();
+ }
+
+ public static void main(String[] args) {
+ System.out.println(smokeTests());
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Parses a CSV file interpreting the first line as a header. The
+ * {@link #parse(InputStream)} method and the setters are synchronized so that
+ * the object cannot be modified when parsing.
+ */
+public abstract class CsvParser {
+ private char separator = ',';
+ private char quote = '\"';
+
+ private Boolean noHeader = false;
+ private Boolean strictLineAsLongAsHeader = true;
+
+ /**
+ * Actually process a parsed line. If
+ * {@link #setStrictLineAsLongAsHeader(Boolean)} is true (default) the header
+ * and the tokens are guaranteed to have the same size.
+ *
+ * @param lineNumber the current line number, starts at 1 (the header, if header
+ * processing is enabled, the first line otherwise)
+ * @param header the read-only header or null if
+ * {@link #setNoHeader(Boolean)} is true (default is false)
+ * @param tokens the parsed tokens
+ */
+ protected abstract void processLine(Integer lineNumber, List<String> header, List<String> tokens);
+
+ /**
+ * Parses the CSV file (stream is closed at the end)
+ *
+ * @param in the stream to parse
+ *
+ * @deprecated Use {@link #parse(InputStream, Charset)} instead.
+ */
+ @Deprecated
+ public synchronized void parse(InputStream in) {
+ parse(in, (Charset) null);
+ }
+
+ /**
+ * Parses the CSV file (stream is closed at the end)
+ *
+ * @param in the stream to parse
+ * @param encoding the encoding to use.
+ *
+ * @deprecated Use {@link #parse(InputStream, Charset)} instead.
+ */
+ @Deprecated
+ public synchronized void parse(InputStream in, String encoding) {
+ Reader reader;
+ if (encoding == null)
+ reader = new InputStreamReader(in);
+ else
+ try {
+ reader = new InputStreamReader(in, encoding);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ parse(reader);
+ }
+
+ /**
+ * Parses the CSV file (stream is closed at the end)
+ *
+ * @param in the stream to parse
+ * @param charset the charset to use
+ */
+ public synchronized void parse(InputStream in, Charset charset) {
+ Reader reader;
+ if (charset == null)
+ reader = new InputStreamReader(in);
+ else
+ reader = new InputStreamReader(in, charset);
+ parse(reader);
+ }
+
+ /**
+ * Parses the CSV file (stream is closed at the end)
+ *
+ * @param reader the reader to use (it will be buffered)
+ */
+ public synchronized void parse(Reader reader) {
+ Integer lineCount = 0;
+ try (BufferedReader bufferedReader = new BufferedReader(reader)) {
+ List<String> header = null;
+ if (!noHeader) {
+ String headerStr = bufferedReader.readLine();
+ if (headerStr == null)// empty file
+ return;
+ lineCount++;
+ header = new ArrayList<String>();
+ StringBuffer currStr = new StringBuffer("");
+ Boolean wasInquote = false;
+ while (parseLine(headerStr, header, currStr, wasInquote)) {
+ headerStr = bufferedReader.readLine();
+ if (headerStr == null)
+ break;
+ wasInquote = true;
+ }
+ header = Collections.unmodifiableList(header);
+ }
+
+ String line = null;
+ lines: while ((line = bufferedReader.readLine()) != null) {
+ line = preProcessLine(line);
+ if (line == null) {
+ // skip line
+ continue lines;
+ }
+ lineCount++;
+ List<String> tokens = new ArrayList<String>();
+ StringBuffer currStr = new StringBuffer("");
+ Boolean wasInquote = false;
+ sublines: while (parseLine(line, tokens, currStr, wasInquote)) {
+ line = bufferedReader.readLine();
+ if (line == null)
+ break sublines;
+ wasInquote = true;
+ }
+ if (!noHeader && strictLineAsLongAsHeader) {
+ int headerSize = header.size();
+ int tokenSize = tokens.size();
+ if (tokenSize == 1 && line.trim().equals(""))
+ continue lines;// empty line
+ if (headerSize != tokenSize) {
+ throw new IllegalStateException("Token size " + tokenSize + " is different from header size "
+ + headerSize + " at line " + lineCount + ", line: " + line + ", header: " + header
+ + ", tokens: " + tokens);
+ }
+ }
+ processLine(lineCount, header, tokens);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot parse CSV file (line: " + lineCount + ")", e);
+ }
+ }
+
+ /**
+ * Called before each (logical) line is processed, giving a change to modify it
+ * (typically for cleaning dirty files). To be overridden, return the line
+ * unchanged by default. Skip the line if 'null' is returned.
+ */
+ protected String preProcessLine(String line) {
+ return line;
+ }
+
+ /**
+ * Parses a line character by character for performance purpose
+ *
+ * @return whether to continue parsing this line
+ */
+ protected Boolean parseLine(String str, List<String> tokens, StringBuffer currStr, Boolean wasInquote) {
+ if (wasInquote)
+ currStr.append('\n');
+
+ char[] arr = str.toCharArray();
+ boolean inQuote = wasInquote;
+ for (int i = 0; i < arr.length; i++) {
+ char c = arr[i];
+ if (c == separator) {
+ if (!inQuote) {
+ tokens.add(currStr.toString());
+// currStr.delete(0, currStr.length());
+ currStr.setLength(0);
+ currStr.trimToSize();
+ } else {
+ // we don't remove separator that are in a quoted substring
+ // System.out
+ // .println("IN QUOTE, got a separator: [" + c + "]");
+ currStr.append(c);
+ }
+ } else if (c == quote) {
+ if (inQuote && (i + 1) < arr.length && arr[i + 1] == quote) {
+ // case of double quote
+ currStr.append(quote);
+ i++;
+ } else {// standard
+ inQuote = inQuote ? false : true;
+ }
+ } else {
+ currStr.append(c);
+ }
+ }
+
+ if (!inQuote) {
+ tokens.add(currStr.toString());
+ // System.out.println("# TOKEN: " + currStr);
+ }
+ // if (inQuote)
+ // throw new ArgeoException("Missing quote at the end of the line "
+ // + str + " (parsed: " + tokens + ")");
+ if (inQuote)
+ return true;
+ else
+ return false;
+ // return tokens;
+ }
+
+ public char getSeparator() {
+ return separator;
+ }
+
+ public synchronized void setSeparator(char separator) {
+ this.separator = separator;
+ }
+
+ public char getQuote() {
+ return quote;
+ }
+
+ public synchronized void setQuote(char quote) {
+ this.quote = quote;
+ }
+
+ public Boolean getNoHeader() {
+ return noHeader;
+ }
+
+ public synchronized void setNoHeader(Boolean noHeader) {
+ this.noHeader = noHeader;
+ }
+
+ public Boolean getStrictLineAsLongAsHeader() {
+ return strictLineAsLongAsHeader;
+ }
+
+ public synchronized void setStrictLineAsLongAsHeader(Boolean strictLineAsLongAsHeader) {
+ this.strictLineAsLongAsHeader = strictLineAsLongAsHeader;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * CSV parser allowing to process lines as maps whose keys are the header
+ * fields.
+ */
+public abstract class CsvParserWithLinesAsMap extends CsvParser {
+
+ /**
+ * Actually processes a line.
+ *
+ * @param lineNumber the current line number, starts at 1 (the header, if header
+ * processing is enabled, the first lien otherwise)
+ * @param line the parsed tokens as a map whose keys are the header fields
+ */
+ protected abstract void processLine(Integer lineNumber, Map<String, String> line);
+
+ protected final void processLine(Integer lineNumber, List<String> header, List<String> tokens) {
+ if (header == null)
+ throw new IllegalArgumentException("Only CSV with header is supported");
+ Map<String, String> line = new HashMap<String, String>();
+ for (int i = 0; i < header.size(); i++) {
+ String key = header.get(i);
+ String value = null;
+ if (i < tokens.size())
+ value = tokens.get(i);
+ line.put(key, value);
+ }
+ processLine(lineNumber, line);
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Iterator;
+import java.util.List;
+
+/** Write in CSV format. */
+public class CsvWriter {
+ private final Writer out;
+
+ private char separator = ',';
+ private char quote = '\"';
+
+ /**
+ * Creates a CSV writer.
+ *
+ * @param out the stream to write to. Caller is responsible for closing it.
+ *
+ * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead.
+ *
+ */
+ @Deprecated
+ public CsvWriter(OutputStream out) {
+ this.out = new OutputStreamWriter(out);
+ }
+
+ /**
+ * Creates a CSV writer.
+ *
+ * @param out the stream to write to. Caller is responsible for closing it.
+ * @param encoding the encoding to use.
+ *
+ * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead.
+ */
+ @Deprecated
+ public CsvWriter(OutputStream out, String encoding) {
+ try {
+ this.out = new OutputStreamWriter(out, encoding);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Creates a CSV writer.
+ *
+ * @param out the stream to write to. Caller is responsible for closing it.
+ * @param charset the charset to use
+ */
+ public CsvWriter(OutputStream out, Charset charset) {
+ this.out = new OutputStreamWriter(out, charset);
+ }
+
+ /**
+ * Creates a CSV writer.
+ *
+ * @param out the stream to write to. Caller is responsible for closing it.
+ */
+ public CsvWriter(Writer writer) {
+ this.out = writer;
+ }
+
+ /**
+ * Write a CSV line. Also used to write a header if needed (this is transparent
+ * for the CSV writer): simply call it first, before writing the lines.
+ */
+ public void writeLine(List<?> tokens) {
+ try {
+ Iterator<?> it = tokens.iterator();
+ while (it.hasNext()) {
+ Object obj = it.next();
+ writeToken(obj != null ? obj.toString() : null);
+ if (it.hasNext())
+ out.write(separator);
+ }
+ out.write('\n');
+ out.flush();
+ } catch (IOException e) {
+ throw new RuntimeException("Could not write " + tokens, e);
+ }
+ }
+
+ /**
+ * Write a CSV line. Also used to write a header if needed (this is transparent
+ * for the CSV writer): simply call it first, before writing the lines.
+ */
+ public void writeLine(Object... tokens) {
+ try {
+ for (int i = 0; i < tokens.length; i++) {
+ if (tokens[i] == null) {
+ writeToken(null);
+ } else {
+ writeToken(tokens[i].toString());
+ }
+ if (i != (tokens.length - 1))
+ out.write(separator);
+ }
+ out.write('\n');
+ out.flush();
+ } catch (IOException e) {
+ throw new RuntimeException("Could not write " + tokens, e);
+ }
+ }
+
+ protected void writeToken(String token) throws IOException {
+ if (token == null) {
+ // TODO configure how to deal with null
+ out.write("");
+ return;
+ }
+ // +2 for possible quotes, another +2 assuming there would be an already
+ // quoted string where quotes needs to be duplicated
+ // another +2 for safety
+ // we don't want to increase buffer size while writing
+ StringBuffer buf = new StringBuffer(token.length() + 6);
+ char[] arr = token.toCharArray();
+ boolean shouldQuote = false;
+ for (char c : arr) {
+ if (!shouldQuote) {
+ if (c == separator)
+ shouldQuote = true;
+ if (c == '\n')
+ shouldQuote = true;
+ }
+
+ if (c == quote) {
+ shouldQuote = true;
+ // duplicate quote
+ buf.append(quote);
+ }
+
+ // generic case
+ buf.append(c);
+ }
+
+ if (shouldQuote == true)
+ out.write(quote);
+ out.write(buf.toString());
+ if (shouldQuote == true)
+ out.write(quote);
+ }
+
+ public void setSeparator(char separator) {
+ this.separator = separator;
+ }
+
+ public void setQuote(char quote) {
+ this.quote = quote;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletionException;
+
+import javax.security.auth.Subject;
+
+/**
+ * Prepare evolution of Java APIs introduced in JDK 18, as these static methods
+ * will be added to {@link Subject}.
+ */
+@SuppressWarnings("removal")
+public class CurrentSubject {
+
+ private final static boolean useThreadLocal = Boolean
+ .parseBoolean(System.getProperty("jdk.security.auth.subject.useTL"));
+
+ private final static InheritableThreadLocal<Subject> current = new InheritableThreadLocal<>();
+
+ public static Subject current() {
+ if (useThreadLocal) {
+ return current.get();
+ } else {// legacy
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ return subject;
+ }
+ }
+
+ public static <T> T callAs(Subject subject, Callable<T> action) {
+ if (useThreadLocal) {
+ Subject previous = current();
+ current.set(subject);
+ try {
+ return action.call();
+ } catch (Exception e) {
+ throw new CompletionException("Failed to execute action for " + subject, e);
+ } finally {
+ current.set(previous);
+ }
+ } else {// legacy
+ try {
+ return Subject.doAs(subject, new PrivilegedExceptionAction<T>() {
+
+ @Override
+ public T run() throws Exception {
+ return action.call();
+ }
+
+ });
+ } catch (PrivilegedActionException e) {
+ throw new CompletionException("Failed to execute action for " + subject, e.getCause());
+ } catch (Exception e) {
+ throw new CompletionException("Failed to execute action for " + subject, e);
+ }
+ }
+ }
+
+ /** Singleton. */
+ private CurrentSubject() {
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+/**
+ * Access the keys of a {@link String}-keyed {@link Dictionary} (common throughout
+ * the OSGi APIs) as an {@link Iterable} so that they are easily usable in
+ * for-each loops.
+ */
+class DictionaryKeys implements Iterable<String> {
+ private final Dictionary<String, ?> dictionary;
+
+ public DictionaryKeys(Dictionary<String, ?> dictionary) {
+ this.dictionary = dictionary;
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return new KeyIterator(dictionary.keys());
+ }
+
+ private static class KeyIterator implements Iterator<String> {
+ private final Enumeration<String> keys;
+
+ KeyIterator(Enumeration<String> keys) {
+ this.keys = keys;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return keys.hasMoreElements();
+ }
+
+ @Override
+ public String next() {
+ return keys.nextElement();
+ }
+
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/** Utilities around cryptographic digests */
+public class DigestUtils {
+ public final static String MD5 = "MD5";
+ public final static String SHA1 = "SHA1";
+ public final static String SHA256 = "SHA-256";
+ public final static String SHA512 = "SHA-512";
+
+ private static Boolean debug = false;
+ // TODO: make it configurable
+ private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB
+
+ public static byte[] sha1(byte[]... bytes) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance(SHA1);
+ for (byte[] arr : bytes)
+ digest.update(arr);
+ byte[] checksum = digest.digest();
+ return checksum;
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("SHA1 is not avalaible", e);
+ }
+ }
+
+ public static byte[] digestAsBytes(String algorithm, byte[]... bytes) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ for (byte[] arr : bytes)
+ digest.update(arr);
+ byte[] checksum = digest.digest();
+ return checksum;
+ } catch (NoSuchAlgorithmException e) {
+ throw new UnsupportedOperationException("Cannot digest with algorithm " + algorithm, e);
+ }
+ }
+
+ public static String digest(String algorithm, byte[]... bytes) {
+ return toHexString(digestAsBytes(algorithm, bytes));
+ }
+
+ public static String digest(String algorithm, InputStream in) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ // ReadableByteChannel channel = Channels.newChannel(in);
+ // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
+ // while (channel.read(bb) > 0)
+ // digest.update(bb);
+ byte[] buffer = new byte[byteBufferCapacity];
+ int read = 0;
+ while ((read = in.read(buffer)) > 0) {
+ digest.update(buffer, 0, read);
+ }
+
+ byte[] checksum = digest.digest();
+ String res = toHexString(checksum);
+ return res;
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ StreamUtils.closeQuietly(in);
+ }
+ }
+
+ public static String digest(String algorithm, File file) {
+ FileInputStream fis = null;
+ FileChannel fc = null;
+ try {
+ fis = new FileInputStream(file);
+ fc = fis.getChannel();
+
+ // Get the file's size and then map it into memory
+ int sz = (int) fc.size();
+ ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
+ return digest(algorithm, bb);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
+ } finally {
+ StreamUtils.closeQuietly(fis);
+ if (fc.isOpen())
+ try {
+ fc.close();
+ } catch (IOException e) {
+ // silent
+ }
+ }
+ }
+
+ protected static String digest(String algorithm, ByteBuffer bb) {
+ long begin = System.currentTimeMillis();
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ digest.update(bb);
+ byte[] checksum = digest.digest();
+ String res = toHexString(checksum);
+ long end = System.currentTimeMillis();
+ if (debug)
+ System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
+ return res;
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
+ }
+ }
+
+ public static String sha1hex(Path path) {
+ return digest(SHA1, path, byteBufferCapacity);
+ }
+
+ public static String digest(String algorithm, Path path, long bufferSize) {
+ byte[] digest = digestAsBytes(algorithm, path, bufferSize);
+ return toHexString(digest);
+ }
+
+ public static byte[] digestAsBytes(String algorithm, Path file, long bufferSize) {
+ long begin = System.currentTimeMillis();
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ FileChannel fc = FileChannel.open(file);
+ long fileSize = Files.size(file);
+ if (fileSize <= bufferSize) {
+ ByteBuffer bb = fc.map(MapMode.READ_ONLY, 0, fileSize);
+ md.update(bb);
+ } else {
+ long lastCycle = (fileSize / bufferSize) - 1;
+ long position = 0;
+ for (int i = 0; i <= lastCycle; i++) {
+ ByteBuffer bb;
+ if (i != lastCycle) {
+ bb = fc.map(MapMode.READ_ONLY, position, bufferSize);
+ position = position + bufferSize;
+ } else {
+ bb = fc.map(MapMode.READ_ONLY, position, fileSize - position);
+ position = fileSize;
+ }
+ md.update(bb);
+ }
+ }
+ long end = System.currentTimeMillis();
+ if (debug)
+ System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
+ return md.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot digest " + file + " with algorithm " + algorithm, e);
+ }
+ }
+
+ public static void main(String[] args) {
+ File file;
+ if (args.length > 0)
+ file = new File(args[0]);
+ else {
+ System.err.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
+ + "docs/guide/security/CryptoSpec.html#AppA)");
+ return;
+ }
+
+ if (args.length > 1) {
+ String algorithm = args[1];
+ System.out.println(digest(algorithm, file));
+ } else {
+ String algorithm = "MD5";
+ System.out.println(algorithm + ": " + digest(algorithm, file));
+ algorithm = "SHA";
+ System.out.println(algorithm + ": " + digest(algorithm, file));
+ System.out.println(algorithm + ": " + sha1hex(file.toPath()));
+ algorithm = "SHA-256";
+ System.out.println(algorithm + ": " + digest(algorithm, file));
+ algorithm = "SHA-512";
+ System.out.println(algorithm + ": " + digest(algorithm, file));
+ }
+ }
+
+ final private static char[] hexArray = "0123456789abcdef".toCharArray();
+
+ /** Converts a byte array to an hex String. */
+ public static String toHexString(byte[] bytes) {
+ char[] hexChars = new char[bytes.length * 2];
+ for (int j = 0; j < bytes.length; j++) {
+ int v = bytes[j] & 0xFF;
+ hexChars[j * 2] = hexArray[v >>> 4];
+ hexChars[j * 2 + 1] = hexArray[v & 0x0F];
+ }
+ return new String(hexChars);
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/** Hashes the hashes of the files in a directory. */
+public class DirH {
+
+ private final static Charset charset = Charset.forName("UTF-16");
+ private final static long bufferSize = 200 * 1024 * 1024;
+ private final static String algorithm = "SHA";
+
+ private final static byte EOL = (byte) '\n';
+ private final static byte SPACE = (byte) ' ';
+
+ private final int hashSize;
+
+ private final byte[][] hashes;
+ private final byte[][] fileNames;
+ private final byte[] digest;
+ private final byte[] dirName;
+
+ /**
+ * @param dirName can be null or empty
+ */
+ private DirH(byte[][] hashes, byte[][] fileNames, byte[] dirName) {
+ if (hashes.length != fileNames.length)
+ throw new IllegalArgumentException(hashes.length + " hashes and " + fileNames.length + " file names");
+ this.hashes = hashes;
+ this.fileNames = fileNames;
+ this.dirName = dirName == null ? new byte[0] : dirName;
+ if (hashes.length == 0) {// empty dir
+ hashSize = 20;
+ // FIXME what is the digest of an empty dir?
+ digest = new byte[hashSize];
+ Arrays.fill(digest, SPACE);
+ return;
+ }
+ hashSize = hashes[0].length;
+ for (int i = 0; i < hashes.length; i++) {
+ if (hashes[i].length != hashSize)
+ throw new IllegalArgumentException(
+ "Hash size for " + new String(fileNames[i], charset) + " is " + hashes[i].length);
+ }
+
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ for (int i = 0; i < hashes.length; i++) {
+ md.update(this.hashes[i]);
+ md.update(SPACE);
+ md.update(this.fileNames[i]);
+ md.update(EOL);
+ }
+ digest = md.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new IllegalArgumentException("Cannot digest", e);
+ }
+ }
+
+ public void print(PrintStream out) {
+ out.print(DigestUtils.toHexString(digest));
+ if (dirName.length > 0) {
+ out.print(' ');
+ out.print(new String(dirName, charset));
+ }
+ out.print('\n');
+ for (int i = 0; i < hashes.length; i++) {
+ out.print(DigestUtils.toHexString(hashes[i]));
+ out.print(' ');
+ out.print(new String(fileNames[i], charset));
+ out.print('\n');
+ }
+ }
+
+ public static DirH digest(Path dir) {
+ try (DirectoryStream<Path> files = Files.newDirectoryStream(dir)) {
+ List<byte[]> hs = new ArrayList<byte[]>();
+ List<String> fNames = new ArrayList<>();
+ for (Path file : files) {
+ if (!Files.isDirectory(file)) {
+ byte[] digest = DigestUtils.digestAsBytes(algorithm, file, bufferSize);
+ hs.add(digest);
+ fNames.add(file.getFileName().toString());
+ }
+ }
+
+ byte[][] fileNames = new byte[fNames.size()][];
+ for (int i = 0; i < fNames.size(); i++) {
+ fileNames[i] = fNames.get(i).getBytes(charset);
+ }
+ byte[][] hashes = hs.toArray(new byte[hs.size()][]);
+ return new DirH(hashes, fileNames, dir.toString().getBytes(charset));
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot digest " + dir, e);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ DirH dirH = DirH.digest(Paths.get("/home/mbaudier/tmp/"));
+ dirH.print(System.out);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Serialisable wrapper of a {@link Throwable}. typically to be written as XML
+ * or JSON in a server error response.
+ */
+public class ExceptionsChain {
+ private List<SystemException> exceptions = new ArrayList<>();
+
+ public ExceptionsChain() {
+ }
+
+ public ExceptionsChain(Throwable exception) {
+ writeException(exception);
+ }
+
+ /** recursive */
+ protected void writeException(Throwable exception) {
+ SystemException systemException = new SystemException(exception);
+ exceptions.add(systemException);
+ Throwable cause = exception.getCause();
+ if (cause != null)
+ writeException(cause);
+ }
+
+ public List<SystemException> getExceptions() {
+ return exceptions;
+ }
+
+ public void setExceptions(List<SystemException> exceptions) {
+ this.exceptions = exceptions;
+ }
+
+ /** An exception in the chain. */
+ public static class SystemException {
+ private String type;
+ private String message;
+ private List<String> stackTrace;
+
+ public SystemException() {
+ }
+
+ public SystemException(Throwable exception) {
+ this.type = exception.getClass().getName();
+ this.message = exception.getMessage();
+ this.stackTrace = new ArrayList<>();
+ StackTraceElement[] elems = exception.getStackTrace();
+ for (int i = 0; i < elems.length; i++)
+ stackTrace.add("at " + elems[i].toString());
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public List<String> getStackTrace() {
+ return stackTrace;
+ }
+
+ public void setStackTrace(List<String> stackTrace) {
+ this.stackTrace = stackTrace;
+ }
+
+ @Override
+ public String toString() {
+ return "System exception: " + type + ", " + message + ", " + stackTrace;
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return exceptions.toString();
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+/** Utilities around the standard Java file abstractions. */
+public class FsUtils {
+
+ /** Deletes this path, recursively if needed. */
+ public static void copyDirectory(Path source, Path target) {
+ if (!Files.exists(source) || !Files.isDirectory(source))
+ throw new IllegalArgumentException(source + " is not a directory");
+ if (Files.exists(target) && !Files.isDirectory(target))
+ throw new IllegalArgumentException(target + " is not a directory");
+ try {
+ Files.createDirectories(target);
+ Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path directory, BasicFileAttributes attrs) throws IOException {
+ Path relativePath = source.relativize(directory);
+ Path targetDirectory = target.resolve(relativePath);
+ if (!Files.exists(targetDirectory))
+ Files.createDirectory(targetDirectory);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Path relativePath = source.relativize(file);
+ Path targetFile = target.resolve(relativePath);
+ Files.copy(file, targetFile);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot copy " + source + " to " + target, e);
+ }
+
+ }
+
+ /**
+ * Deletes this path, recursively if needed. Does nothing if the path does not
+ * exist.
+ */
+ public static void delete(Path path) {
+ try {
+ if (!Files.exists(path))
+ return;
+ Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult postVisitDirectory(Path directory, IOException e) throws IOException {
+ if (e != null)
+ throw e;
+ Files.delete(directory);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot delete " + path, e);
+ }
+ }
+
+ /** Singleton. */
+ private FsUtils() {
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.time.ZonedDateTime;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.Temporal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+/** Utilities around Java basic features. */
+public class LangUtils {
+ /*
+ * NON-API OSGi
+ */
+ /**
+ * Returns an array with the names of the provided classes. Useful when
+ * registering services with multiple interfaces in OSGi.
+ */
+ public static String[] names(Class<?>... clzz) {
+ String[] res = new String[clzz.length];
+ for (int i = 0; i < clzz.length; i++)
+ res[i] = clzz[i].getName();
+ return res;
+ }
+
+// /*
+// * MAP
+// */
+// /**
+// * Creates a new {@link Map} with one key-value pair. Key should not be null,
+// * but if the value is null, it returns an empty {@link Map}.
+// *
+// * @deprecated Use {@link Collections#singletonMap(Object, Object)} instead.
+// */
+// @Deprecated
+// public static Map<String, Object> map(String key, Object value) {
+// assert key != null;
+// HashMap<String, Object> props = new HashMap<>();
+// if (value != null)
+// props.put(key, value);
+// return props;
+// }
+
+ /*
+ * DICTIONARY
+ */
+
+ /**
+ * Creates a new {@link Dictionary} with one key-value pair. Key should not be
+ * null, but if the value is null, it returns an empty {@link Dictionary}.
+ */
+ public static Dictionary<String, Object> dict(String key, Object value) {
+ assert key != null;
+ Hashtable<String, Object> props = new Hashtable<>();
+ if (value != null)
+ props.put(key, value);
+ return props;
+ }
+
+ /** @deprecated Use {@link #dict(String, Object)} instead. */
+ @Deprecated
+ public static Dictionary<String, Object> dico(String key, Object value) {
+ return dict(key, value);
+ }
+
+ /** Converts a {@link Dictionary} to a {@link Map} of strings. */
+ public static Map<String, String> dictToStringMap(Dictionary<String, ?> properties) {
+ if (properties == null) {
+ return null;
+ }
+ Map<String, String> res = new HashMap<>(properties.size());
+ Enumeration<String> keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ res.put(key, properties.get(key).toString());
+ }
+ return res;
+ }
+
+ /** Converts a {@link Dictionary} to a {@link Map}. */
+ public static Map<String, Object> dictToMap(Dictionary<String, ?> properties) {
+ if (properties == null) {
+ return null;
+ }
+ Map<String, Object> res = new HashMap<>(properties.size());
+ Enumeration<String> keys = properties.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ res.put(key, properties.get(key));
+ }
+ return res;
+ }
+
+ /**
+ * Get a string property from this map, expecting to find it, or
+ * <code>null</code> if not found.
+ */
+ public static String get(Map<String, ?> map, String key) {
+ Object res = map.get(key);
+ if (res == null)
+ return null;
+ return res.toString();
+ }
+
+ /**
+ * Get a string property from this map, expecting to find it.
+ *
+ * @throws IllegalArgumentException if the key was not found
+ */
+ public static String getNotNull(Map<String, ?> map, String key) {
+ Object res = map.get(key);
+ if (res == null)
+ throw new IllegalArgumentException("Map " + map + " should contain key " + key);
+ return res.toString();
+ }
+
+ /**
+ * Wraps the keys of the provided {@link Dictionary} as an {@link Iterable}.
+ */
+ public static Iterable<String> keys(Dictionary<String, ?> props) {
+ assert props != null;
+ return new DictionaryKeys(props);
+ }
+
+ static String toJson(Dictionary<String, ?> props) {
+ return toJson(props, false);
+ }
+
+ static String toJson(Dictionary<String, ?> props, boolean pretty) {
+ StringBuilder sb = new StringBuilder();
+ sb.append('{');
+ if (pretty)
+ sb.append('\n');
+ Enumeration<String> keys = props.keys();
+ while (keys.hasMoreElements()) {
+ String key = keys.nextElement();
+ if (pretty)
+ sb.append(' ');
+ sb.append('\"').append(key).append('\"');
+ if (pretty)
+ sb.append(" : ");
+ else
+ sb.append(':');
+ sb.append('\"').append(props.get(key)).append('\"');
+ if (keys.hasMoreElements())
+ sb.append(", ");
+ if (pretty)
+ sb.append('\n');
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ static void storeAsProperties(Dictionary<String, Object> props, Path path) throws IOException {
+ if (props == null)
+ throw new IllegalArgumentException("Props cannot be null");
+ Properties toStore = new Properties();
+ for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ toStore.setProperty(key, props.get(key).toString());
+ }
+ try (OutputStream out = Files.newOutputStream(path)) {
+ toStore.store(out, null);
+ }
+ }
+
+ static void appendAsLdif(String dnBase, String dnKey, Dictionary<String, Object> props, Path path)
+ throws IOException {
+ if (props == null)
+ throw new IllegalArgumentException("Props cannot be null");
+ Object dnValue = props.get(dnKey);
+ String dnStr = dnKey + '=' + dnValue + ',' + dnBase;
+ LdapName dn;
+ try {
+ dn = new LdapName(dnStr);
+ } catch (InvalidNameException e) {
+ throw new IllegalArgumentException("Cannot interpret DN " + dnStr, e);
+ }
+ if (dnValue == null)
+ throw new IllegalArgumentException("DN key " + dnKey + " must have a value");
+ try (Writer writer = Files.newBufferedWriter(path, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
+ writer.append("\ndn: ");
+ writer.append(dn.toString());
+ writer.append('\n');
+ for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
+ String key = keys.nextElement();
+ Object value = props.get(key);
+ writer.append(key);
+ writer.append(": ");
+ // FIXME deal with binary and multiple values
+ writer.append(value.toString());
+ writer.append('\n');
+ }
+ }
+ }
+
+ static Dictionary<String, Object> loadFromProperties(Path path) throws IOException {
+ Properties toLoad = new Properties();
+ try (InputStream in = Files.newInputStream(path)) {
+ toLoad.load(in);
+ }
+ Dictionary<String, Object> res = new Hashtable<String, Object>();
+ for (Object key : toLoad.keySet())
+ res.put(key.toString(), toLoad.get(key));
+ return res;
+ }
+
+ /*
+ * COLLECTIONS
+ */
+ /**
+ * Convert a comma-separated separated {@link String} or a {@link String} array
+ * to a {@link List} of {@link String}, trimming them. Useful to quickly
+ * interpret OSGi services properties.
+ *
+ * @return a {@link List} containing the trimmed {@link String}s, or an empty
+ * {@link List} if the argument was <code>null</code>.
+ */
+ public static List<String> toStringList(Object value) {
+ List<String> values = new ArrayList<>();
+ if (value == null)
+ return values;
+ String[] arr;
+ if (value instanceof String) {
+ arr = ((String) value).split(",");
+ } else if (value instanceof String[]) {
+ arr = (String[]) value;
+ } else {
+ throw new IllegalArgumentException("Unsupported value type " + value.getClass());
+ }
+ for (String str : arr) {
+ values.add(str.trim());
+ }
+ return values;
+ }
+
+ /** Size of an {@link Iterable}, optimised if it is a {@link Collection}. */
+ public static int size(Iterable<?> iterable) {
+ if (iterable instanceof Collection)
+ return ((Collection<?>) iterable).size();
+
+ int size = 0;
+ for (Iterator<?> it = iterable.iterator(); it.hasNext(); size++)
+ it.next();
+ return size;
+ }
+
+ public static <T> T getAt(Iterable<T> iterable, int index) {
+ if (iterable instanceof List) {
+ List<T> lst = ((List<T>) iterable);
+ if (index >= lst.size())
+ throw new IllegalArgumentException("Index " + index + " is not available (size is " + lst.size() + ")");
+ return lst.get(index);
+ }
+ int i = 0;
+ for (Iterator<T> it = iterable.iterator(); it.hasNext(); i++) {
+ if (i == index)
+ return it.next();
+ else
+ it.next();
+ }
+ throw new IllegalArgumentException("Index " + index + " is not available (size is " + i + ")");
+ }
+
+ /*
+ * EXCEPTIONS
+ */
+ /**
+ * Chain the messages of all causes (one per line, <b>starts with a line
+ * return</b>) without all the stack
+ */
+ public static String chainCausesMessages(Throwable t) {
+ StringBuffer buf = new StringBuffer();
+ chainCauseMessage(buf, t);
+ return buf.toString();
+ }
+
+ /** Recursive chaining of messages */
+ private static void chainCauseMessage(StringBuffer buf, Throwable t) {
+ buf.append('\n').append(' ').append(t.getClass().getCanonicalName()).append(": ").append(t.getMessage());
+ if (t.getCause() != null)
+ chainCauseMessage(buf, t.getCause());
+ }
+
+ /*
+ * TIME
+ */
+ /** Formats time elapsed since start. */
+ public static String since(ZonedDateTime start) {
+ ZonedDateTime now = ZonedDateTime.now();
+ return duration(start, now);
+ }
+
+ /** Formats a duration. */
+ public static String duration(Temporal start, Temporal end) {
+ long count = ChronoUnit.DAYS.between(start, end);
+ if (count != 0)
+ return count > 1 ? count + " days" : count + " day";
+ count = ChronoUnit.HOURS.between(start, end);
+ if (count != 0)
+ return count > 1 ? count + " hours" : count + " hours";
+ count = ChronoUnit.MINUTES.between(start, end);
+ if (count != 0)
+ return count > 1 ? count + " minutes" : count + " minute";
+ count = ChronoUnit.SECONDS.between(start, end);
+ return count > 1 ? count + " seconds" : count + " second";
+ }
+
+ /** Singleton constructor. */
+ private LangUtils() {
+
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/** When OS specific informations are needed. */
+public class OS {
+ public final static OS LOCAL = new OS();
+
+ private final String arch, name, version;
+
+ /** The OS of the running JVM */
+ protected OS() {
+ arch = System.getProperty("os.arch");
+ name = System.getProperty("os.name");
+ version = System.getProperty("os.version");
+ }
+
+ public String getArch() {
+ return arch;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public boolean isMSWindows() {
+ // only MS Windows would use such an horrendous separator...
+ return File.separatorChar == '\\';
+ }
+
+ public String[] getDefaultShellCommand() {
+ if (!isMSWindows())
+ return new String[] { "/bin/bash", "-l", "-i" };
+ else
+ return new String[] { "cmd.exe", "/C" };
+ }
+
+ public static long getJvmPid() {
+ return ProcessHandle.current().pid();
+// String pidAndHost = ManagementFactory.getRuntimeMXBean().getName();
+// return Integer.parseInt(pidAndHost.substring(0, pidAndHost.indexOf('@')));
+ }
+
+ /**
+ * Get the runtime directory. It will be the environment variable
+ * XDG_RUNTIME_DIR if it is set, or ~/.cache/argeo if not.
+ */
+ public static Path getRunDir() {
+ Path runDir;
+ String xdgRunDir = System.getenv("XDG_RUNTIME_DIR");
+ if (xdgRunDir != null) {
+ // TODO support multiple names
+ runDir = Paths.get(xdgRunDir);
+ } else {
+ runDir = Paths.get(System.getProperty("user.home"), ".cache/argeo");
+ }
+ return runDir;
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherInputStream;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class PasswordEncryption {
+ public final static Integer DEFAULT_ITERATION_COUNT = 1024;
+ /** Stronger with 256, but causes problem with Oracle JVM */
+ public final static Integer DEFAULT_SECRETE_KEY_LENGTH = 256;
+ public final static Integer DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED = 128;
+ public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1";
+ public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES";
+ public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding";
+// public final static String DEFAULT_CHARSET = "UTF-8";
+ public final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+
+ private Integer iterationCount = DEFAULT_ITERATION_COUNT;
+ private Integer secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH;
+ private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY;
+ private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION;
+ private String cipherName = DEFAULT_CIPHER_NAME;
+
+ private static byte[] DEFAULT_SALT_8 = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
+ (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
+ private static byte[] DEFAULT_IV_16 = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
+ (byte) 0x35, (byte) 0xE3, (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
+ (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
+
+ private Key key;
+ private Cipher ecipher;
+ private Cipher dcipher;
+
+ private String securityProviderName = null;
+
+ /**
+ * This is up to the caller to clear the passed array. Neither copy of nor
+ * reference to the passed array is kept
+ */
+ public PasswordEncryption(char[] password) {
+ this(password, DEFAULT_SALT_8, DEFAULT_IV_16);
+ }
+
+ /**
+ * This is up to the caller to clear the passed array. Neither copies of nor
+ * references to the passed arrays are kept
+ */
+ public PasswordEncryption(char[] password, byte[] passwordSalt, byte[] initializationVector) {
+ try {
+ initKeyAndCiphers(password, passwordSalt, initializationVector);
+ } catch (InvalidKeyException e) {
+ Integer previousSecreteKeyLength = secreteKeyLength;
+ secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED;
+ System.err.println("'" + e.getMessage() + "', will use " + secreteKeyLength
+ + " secrete key length instead of " + previousSecreteKeyLength);
+ try {
+ initKeyAndCiphers(password, passwordSalt, initializationVector);
+ } catch (GeneralSecurityException e1) {
+ throw new IllegalStateException("Cannot get secret key (with restricted length)", e1);
+ }
+ } catch (GeneralSecurityException e) {
+ throw new IllegalStateException("Cannot get secret key", e);
+ }
+ }
+
+ protected void initKeyAndCiphers(char[] password, byte[] passwordSalt, byte[] initializationVector)
+ throws GeneralSecurityException {
+ byte[] salt = new byte[8];
+ System.arraycopy(passwordSalt, 0, salt, 0, salt.length);
+ // for (int i = 0; i < password.length && i < salt.length; i++)
+ // salt[i] = (byte) password[i];
+ byte[] iv = new byte[16];
+ System.arraycopy(initializationVector, 0, iv, 0, iv.length);
+
+ SecretKeyFactory keyFac = SecretKeyFactory.getInstance(getSecretKeyFactoryName());
+ PBEKeySpec keySpec = new PBEKeySpec(password, salt, getIterationCount(), getKeyLength());
+ String secKeyEncryption = getSecretKeyEncryption();
+ if (secKeyEncryption != null) {
+ SecretKey tmp = keyFac.generateSecret(keySpec);
+ key = new SecretKeySpec(tmp.getEncoded(), getSecretKeyEncryption());
+ } else {
+ key = keyFac.generateSecret(keySpec);
+ }
+ if (securityProviderName != null)
+ ecipher = Cipher.getInstance(getCipherName(), securityProviderName);
+ else
+ ecipher = Cipher.getInstance(getCipherName());
+ ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
+ dcipher = Cipher.getInstance(getCipherName());
+ dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+ }
+
+ public void encrypt(InputStream decryptedIn, OutputStream encryptedOut) throws IOException {
+ try {
+ CipherOutputStream out = new CipherOutputStream(encryptedOut, ecipher);
+ StreamUtils.copy(decryptedIn, out);
+ StreamUtils.closeQuietly(out);
+ } catch (IOException e) {
+ throw e;
+ } finally {
+ StreamUtils.closeQuietly(decryptedIn);
+ }
+ }
+
+ public void decrypt(InputStream encryptedIn, OutputStream decryptedOut) throws IOException {
+ try {
+ CipherInputStream decryptedIn = new CipherInputStream(encryptedIn, dcipher);
+ StreamUtils.copy(decryptedIn, decryptedOut);
+ } catch (IOException e) {
+ throw e;
+ } finally {
+ StreamUtils.closeQuietly(encryptedIn);
+ }
+ }
+
+ public byte[] encryptString(String str) {
+ ByteArrayOutputStream out = null;
+ ByteArrayInputStream in = null;
+ try {
+ out = new ByteArrayOutputStream();
+ in = new ByteArrayInputStream(str.getBytes(DEFAULT_CHARSET));
+ encrypt(in, out);
+ return out.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ StreamUtils.closeQuietly(out);
+ }
+ }
+
+ /** Closes the input stream */
+ public String decryptAsString(InputStream in) {
+ ByteArrayOutputStream out = null;
+ try {
+ out = new ByteArrayOutputStream();
+ decrypt(in, out);
+ return new String(out.toByteArray(), DEFAULT_CHARSET);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ StreamUtils.closeQuietly(out);
+ }
+ }
+
+ protected Key getKey() {
+ return key;
+ }
+
+ protected Cipher getEcipher() {
+ return ecipher;
+ }
+
+ protected Cipher getDcipher() {
+ return dcipher;
+ }
+
+ protected Integer getIterationCount() {
+ return iterationCount;
+ }
+
+ protected Integer getKeyLength() {
+ return secreteKeyLength;
+ }
+
+ protected String getSecretKeyFactoryName() {
+ return secreteKeyFactoryName;
+ }
+
+ protected String getSecretKeyEncryption() {
+ return secreteKeyEncryption;
+ }
+
+ protected String getCipherName() {
+ return cipherName;
+ }
+
+ public void setIterationCount(Integer iterationCount) {
+ this.iterationCount = iterationCount;
+ }
+
+ public void setSecreteKeyLength(Integer keyLength) {
+ this.secreteKeyLength = keyLength;
+ }
+
+ public void setSecreteKeyFactoryName(String secreteKeyFactoryName) {
+ this.secreteKeyFactoryName = secreteKeyFactoryName;
+ }
+
+ public void setSecreteKeyEncryption(String secreteKeyEncryption) {
+ this.secreteKeyEncryption = secreteKeyEncryption;
+ }
+
+ public void setCipherName(String cipherName) {
+ this.cipherName = cipherName;
+ }
+
+ public void setSecurityProviderName(String securityProviderName) {
+ this.securityProviderName = securityProviderName;
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousByteChannel;
+import java.nio.channels.CompletionHandler;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+
+/** An {@link AsynchronousByteChannel} based on an {@link ExecutorService}. */
+public class ServiceChannel implements AsynchronousByteChannel {
+ private final ReadableByteChannel in;
+ private final WritableByteChannel out;
+
+ private boolean open = true;
+
+ private ExecutorService executor;
+
+ public ServiceChannel(ReadableByteChannel in, WritableByteChannel out, ExecutorService executor) {
+ this.in = in;
+ this.out = out;
+ this.executor = executor;
+ }
+
+ @Override
+ public Future<Integer> read(ByteBuffer dst) {
+ return executor.submit(() -> in.read(dst));
+ }
+
+ @Override
+ public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
+ try {
+ Future<Integer> res = read(dst);
+ handler.completed(res.get(), attachment);
+ } catch (Exception e) {
+ handler.failed(e, attachment);
+ }
+ }
+
+ @Override
+ public Future<Integer> write(ByteBuffer src) {
+ return executor.submit(() -> out.write(src));
+ }
+
+ @Override
+ public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
+ try {
+ Future<Integer> res = write(src);
+ handler.completed(res.get(), attachment);
+ } catch (Exception e) {
+ handler.failed(e, attachment);
+ }
+ }
+
+ @Override
+ public synchronized void close() throws IOException {
+ try {
+ in.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ try {
+ out.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ open = false;
+ notifyAll();
+ }
+
+ @Override
+ public synchronized boolean isOpen() {
+ return open;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.StringJoiner;
+
+/** Stream utilities to be used when Apache Commons IO is not available. */
+public class StreamUtils {
+ private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
+
+ /*
+ * APACHE COMMONS IO (inspired)
+ */
+
+ /** @return the number of bytes */
+ public static Long copy(InputStream in, OutputStream out) throws IOException {
+ Long count = 0l;
+ byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
+ while (true) {
+ int length = in.read(buf);
+ if (length < 0)
+ break;
+ out.write(buf, 0, length);
+ count = count + length;
+ }
+ return count;
+ }
+
+ /** @return the number of chars */
+ public static Long copy(Reader in, Writer out) throws IOException {
+ Long count = 0l;
+ char[] buf = new char[DEFAULT_BUFFER_SIZE];
+ while (true) {
+ int length = in.read(buf);
+ if (length < 0)
+ break;
+ out.write(buf, 0, length);
+ count = count + length;
+ }
+ return count;
+ }
+
+ public static byte[] toByteArray(InputStream in) throws IOException {
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ copy(in, out);
+ return out.toByteArray();
+ }
+ }
+
+ public static void closeQuietly(InputStream in) {
+ if (in != null)
+ try {
+ in.close();
+ } catch (Exception e) {
+ //
+ }
+ }
+
+ public static void closeQuietly(OutputStream out) {
+ if (out != null)
+ try {
+ out.close();
+ } catch (Exception e) {
+ //
+ }
+ }
+
+ public static void closeQuietly(Reader in) {
+ if (in != null)
+ try {
+ in.close();
+ } catch (Exception e) {
+ //
+ }
+ }
+
+ public static void closeQuietly(Writer out) {
+ if (out != null)
+ try {
+ out.close();
+ } catch (Exception e) {
+ //
+ }
+ }
+
+ public static String toString(BufferedReader reader) throws IOException {
+ StringJoiner sn = new StringJoiner("\n");
+ String line = null;
+ while ((line = reader.readLine()) != null)
+ sn.add(line);
+ return sn.toString();
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/** A generic tester based on Java assertions and functional programming. */
+public class Tester {
+ private Map<String, TesterStatus> results = Collections.synchronizedSortedMap(new TreeMap<>());
+
+ private ClassLoader classLoader;
+
+ /** Use {@link Thread#getContextClassLoader()} by default. */
+ public Tester() {
+ this(Thread.currentThread().getContextClassLoader());
+ }
+
+ public Tester(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public void execute(String className) {
+ Class<?> clss;
+ try {
+ clss = classLoader.loadClass(className);
+ boolean assertionsEnabled = clss.desiredAssertionStatus();
+ if (!assertionsEnabled)
+ throw new IllegalStateException("Test runner " + getClass().getName()
+ + " requires Java assertions to be enabled. Call the JVM with the -ea argument.");
+ } catch (Exception e1) {
+ throw new IllegalArgumentException("Cannot initalise test for " + className, e1);
+
+ }
+ List<Method> methods = findMethods(clss);
+ if (methods.size() == 0)
+ throw new IllegalArgumentException("No test method found in " + clss);
+ // TODO make order more predictable?
+ for (Method method : methods) {
+ String uid = method.getDeclaringClass().getName() + "#" + method.getName();
+ TesterStatus testStatus = new TesterStatus(uid);
+ Object obj = null;
+ try {
+ beforeTest(uid, method);
+ obj = clss.getDeclaredConstructor().newInstance();
+ method.invoke(obj);
+ testStatus.setPassed();
+ afterTestPassed(uid, method, obj);
+ } catch (Exception e) {
+ testStatus.setFailed(e);
+ afterTestFailed(uid, method, obj, e);
+ } finally {
+ results.put(uid, testStatus);
+ }
+ }
+ }
+
+ protected void beforeTest(String uid, Method method) {
+ // System.out.println(uid + ": STARTING");
+ }
+
+ protected void afterTestPassed(String uid, Method method, Object obj) {
+ System.out.println(uid + ": PASSED");
+ }
+
+ protected void afterTestFailed(String uid, Method method, Object obj, Throwable e) {
+ System.out.println(uid + ": FAILED");
+ e.printStackTrace();
+ }
+
+ protected List<Method> findMethods(Class<?> clss) {
+ List<Method> methods = new ArrayList<Method>();
+// Method call = getMethod(clss, "call");
+// if (call != null)
+// methods.add(call);
+//
+ for (Method method : clss.getMethods()) {
+ if (method.getName().startsWith("test")) {
+ methods.add(method);
+ }
+ }
+ return methods;
+ }
+
+ protected Method getMethod(Class<?> clss, String name, Class<?>... parameterTypes) {
+ try {
+ return clss.getMethod(name, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ return null;
+ } catch (SecurityException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public static void main(String[] args) {
+ // deal with arguments
+ String className;
+ if (args.length < 1) {
+ System.err.println(usage());
+ System.exit(1);
+ throw new IllegalArgumentException();
+ } else {
+ className = args[0];
+ }
+
+ Tester test = new Tester();
+ try {
+ test.execute(className);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+
+ Map<String, TesterStatus> r = test.results;
+ for (String uid : r.keySet()) {
+ TesterStatus testStatus = r.get(uid);
+ System.out.println(testStatus);
+ }
+ }
+
+ public static String usage() {
+ return "java " + Tester.class.getName() + " [test class name]";
+
+ }
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.io.Serializable;
+
+/** The status of a test. */
+public class TesterStatus implements Serializable {
+ private static final long serialVersionUID = 6272975746885487000L;
+
+ private Boolean passed = null;
+ private final String uid;
+ private Throwable throwable = null;
+
+ public TesterStatus(String uid) {
+ this.uid = uid;
+ }
+
+ /** For cloning. */
+ public TesterStatus(String uid, Boolean passed, Throwable throwable) {
+ this(uid);
+ this.passed = passed;
+ this.throwable = throwable;
+ }
+
+ public synchronized Boolean isRunning() {
+ return passed == null;
+ }
+
+ public synchronized Boolean isPassed() {
+ assert passed != null;
+ return passed;
+ }
+
+ public synchronized Boolean isFailed() {
+ assert passed != null;
+ return !passed;
+ }
+
+ public synchronized void setPassed() {
+ setStatus(true);
+ }
+
+ public synchronized void setFailed() {
+ setStatus(false);
+ }
+
+ public synchronized void setFailed(Throwable throwable) {
+ setStatus(false);
+ setThrowable(throwable);
+ }
+
+ protected void setStatus(Boolean passed) {
+ if (this.passed != null)
+ throw new IllegalStateException("Passed status of test " + uid + " is already set (to " + passed + ")");
+ this.passed = passed;
+ }
+
+ protected void setThrowable(Throwable throwable) {
+ if (this.throwable != null)
+ throw new IllegalStateException("Throwable of test " + uid + " is already set (to " + passed + ")");
+ this.throwable = throwable;
+ }
+
+ public String getUid() {
+ return uid;
+ }
+
+ public Throwable getThrowable() {
+ return throwable;
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ // TODO Auto-generated method stub
+ return super.clone();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof TesterStatus) {
+ TesterStatus other = (TesterStatus) o;
+ // we don't check consistency for performance purposes
+ // this equals() is supposed to be used in collections or for transfer
+ return other.uid.equals(uid);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return uid.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return uid + "\t" + (passed ? "passed" : "failed");
+ }
+
+}
--- /dev/null
+package org.argeo.cms.util;
+
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Locale;
+
+/** A throughput, that is, a value per unit of time. */
+public class Throughput {
+ private final static NumberFormat usNumberFormat = NumberFormat.getInstance(Locale.US);
+
+ public enum Unit {
+ s, m, h, d
+ }
+
+ private final Double value;
+ private final Unit unit;
+
+ public Throughput(Double value, Unit unit) {
+ this.value = value;
+ this.unit = unit;
+ }
+
+ public Throughput(Long periodMs, Long count, Unit unit) {
+ if (unit.equals(Unit.s))
+ value = ((double) count * 1000d) / periodMs;
+ else if (unit.equals(Unit.m))
+ value = ((double) count * 60d * 1000d) / periodMs;
+ else if (unit.equals(Unit.h))
+ value = ((double) count * 60d * 60d * 1000d) / periodMs;
+ else if (unit.equals(Unit.d))
+ value = ((double) count * 24d * 60d * 60d * 1000d) / periodMs;
+ else
+ throw new IllegalArgumentException("Unsupported unit " + unit);
+ this.unit = unit;
+ }
+
+ public Throughput(Double value, String unitStr) {
+ this(value, Unit.valueOf(unitStr));
+ }
+
+ public Throughput(String def) {
+ int index = def.indexOf('/');
+ if (def.length() < 3 || index <= 0 || index != def.length() - 2)
+ throw new IllegalArgumentException(
+ def + " no a proper throughput definition" + " (should be <value>/<unit>, e.g. 3.54/s or 1500/h");
+ String valueStr = def.substring(0, index);
+ String unitStr = def.substring(index + 1);
+ try {
+ this.value = usNumberFormat.parse(valueStr).doubleValue();
+ } catch (ParseException e) {
+ throw new IllegalArgumentException("Cannot parse " + valueStr + " as a number.", e);
+ }
+ this.unit = Unit.valueOf(unitStr);
+ }
+
+ public Long asMsPeriod() {
+ if (unit.equals(Unit.s))
+ return Math.round(1000d / value);
+ else if (unit.equals(Unit.m))
+ return Math.round((60d * 1000d) / value);
+ else if (unit.equals(Unit.h))
+ return Math.round((60d * 60d * 1000d) / value);
+ else if (unit.equals(Unit.d))
+ return Math.round((24d * 60d * 60d * 1000d) / value);
+ else
+ throw new IllegalArgumentException("Unsupported unit " + unit);
+ }
+
+ @Override
+ public String toString() {
+ return usNumberFormat.format(value) + '/' + unit;
+ }
+
+ public Double getValue() {
+ return value;
+ }
+
+ public Unit getUnit() {
+ return unit;
+ }
+
+}
--- /dev/null
+/** Generic Java utilities. */
+package org.argeo.cms.util;
\ No newline at end of file
}
} catch (Exception e) {
e.printStackTrace();
- System.exit(1);
+ Runtime.getRuntime().halt(1);
}
}, "Runtime shutdown"));
/** A provisioning source in A2 format. */
public interface A2Source extends ProvisioningSource {
+ /** Use standard a2 protocol, installing from source URL. */
final static String SCHEME_A2 = "a2";
+ /**
+ * Use equinox-specific reference: installation, which does not copy the bundle
+ * content.
+ */
+ final static String SCHEME_A2_REFERENCE = "a2+reference";
final static String DEFAULT_A2_URI = SCHEME_A2 + ":///";
+ final static String DEFAULT_A2_REFERENCE_URI = SCHEME_A2_REFERENCE + ":///";
URI getUri();
}
public abstract class AbstractProvisioningSource implements ProvisioningSource {
protected final Map<String, A2Contribution> contributions = Collections.synchronizedSortedMap(new TreeMap<>());
+ private final boolean usingReference;
+
+ public AbstractProvisioningSource(boolean usingReference) {
+ this.usingReference = usingReference;
+ }
+
public Iterable<A2Contribution> listContributions(Object filter) {
return contributions.values();
}
@Override
public Bundle install(BundleContext bc, A2Module module) {
try {
- Path tempJar = null;
- if (module.getLocator() instanceof Path && Files.isDirectory((Path) module.getLocator()))
- tempJar = toTempJar((Path) module.getLocator());
- Bundle bundle;
- try (InputStream in = newInputStream(tempJar != null ? tempJar : module.getLocator())) {
- bundle = bc.installBundle(module.getBranch().getCoordinates(), in);
+ Object locator = module.getLocator();
+ if (usingReference && locator instanceof Path locatorPath) {
+ String referenceUrl = "reference:file:" + locatorPath.toString();
+ Bundle bundle = bc.installBundle(referenceUrl);
+ return bundle;
+ } else {
+
+ Path tempJar = null;
+ if (locator instanceof Path && Files.isDirectory((Path) locator))
+ tempJar = toTempJar((Path) locator);
+ Bundle bundle;
+ try (InputStream in = newInputStream(tempJar != null ? tempJar : locator)) {
+ bundle = bc.installBundle(module.getBranch().getCoordinates(), in);
+ }
+
+ if (tempJar != null)
+ Files.deleteIfExists(tempJar);
+ return bundle;
}
- if (tempJar != null)
- Files.deleteIfExists(tempJar);
- return bundle;
} catch (BundleException | IOException e) {
throw new A2Exception("Cannot install module " + module, e);
}
@Override
public void update(Bundle bundle, A2Module module) {
try {
- Path tempJar = null;
- if (module.getLocator() instanceof Path && Files.isDirectory((Path) module.getLocator()))
- tempJar = toTempJar((Path) module.getLocator());
- try (InputStream in = newInputStream(tempJar != null ? tempJar : module.getLocator())) {
- bundle.update(in);
+ Object locator = module.getLocator();
+ if (usingReference && locator instanceof Path) {
+ try (InputStream in = newInputStream(locator)) {
+ bundle.update(in);
+ }
+ } else {
+ Path tempJar = null;
+ if (locator instanceof Path && Files.isDirectory((Path) locator))
+ tempJar = toTempJar((Path) locator);
+ try (InputStream in = newInputStream(tempJar != null ? tempJar : locator)) {
+ bundle.update(in);
+ }
+ if (tempJar != null)
+ Files.deleteIfExists(tempJar);
}
- if (tempJar != null)
- Files.deleteIfExists(tempJar);
} catch (BundleException | IOException e) {
throw new A2Exception("Cannot update module " + module, e);
}
return symbolicName;
}
+ protected boolean isUsingReference() {
+ return usingReference;
+ }
+
+ private InputStream newInputStream(Object locator) throws IOException {
+ if (locator instanceof Path) {
+ return Files.newInputStream((Path) locator);
+ } else if (locator instanceof URL) {
+ return ((URL) locator).openStream();
+ } else {
+ throw new IllegalArgumentException("Unsupported module locator type " + locator.getClass());
+ }
+ }
+
private static Manifest findManifest(Path currentPath) {
Path metaInfPath = currentPath.resolve("META-INF");
if (Files.exists(metaInfPath) && Files.isDirectory(metaInfPath)) {
}
- private InputStream newInputStream(Object locator) throws IOException {
- if (locator instanceof Path) {
- return Files.newInputStream((Path) locator);
- } else if (locator instanceof URL) {
- return ((URL) locator).openStream();
- } else {
- throw new IllegalArgumentException("Unsupported module locator type " + locator.getClass());
- }
- }
}
import org.osgi.framework.Version;
/**
- * A provisioning source based on the linear classpath with which the JCM has
+ * A provisioning source based on the linear classpath with which the JVM has
* been started.
*/
public class ClasspathSource extends AbstractProvisioningSource {
+
+ public ClasspathSource() {
+ super(true);
+ }
+
void load() throws IOException {
A2Contribution classpathContribution = getOrAddContribution( A2Contribution.CLASSPATH);
List<String> classpath = Arrays.asList(System.getProperty("java.class.path").split(File.pathSeparator));
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
+import java.util.StringJoiner;
import java.util.TreeMap;
import org.argeo.init.osgi.OsgiBootUtils;
/** A file system {@link AbstractProvisioningSource} in A2 format. */
public class FsA2Source extends AbstractProvisioningSource implements A2Source {
private final Path base;
- private Map<String, String> xOr;
+ private final Map<String, String> variantsXOr;
- public FsA2Source(Path base) {
- this(base, new HashMap<>());
- }
+// public FsA2Source(Path base) {
+// this(base, new HashMap<>());
+// }
- public FsA2Source(Path base, Map<String, String> xOr) {
+ public FsA2Source(Path base, Map<String, String> variantsXOr, boolean usingReference) {
+ super(usingReference);
this.base = base;
- this.xOr = xOr;
+ this.variantsXOr = new HashMap<>(variantsXOr);
}
void load() throws IOException {
} else {// variants
Path variantPath = null;
// is it an explicit variant?
- String variant = xOr.get(contributionPath.getFileName().toString());
+ String variant = variantsXOr.get(contributionPath.getFileName().toString());
if (variant != null) {
variantPath = contributionPath.resolve(variant);
}
String ext = moduleFileName.substring(lastDot + 1);
if (!"jar".equals(ext))
continue modules;
-// String moduleName = moduleFileName.substring(0, lastDot);
-// if (moduleName.endsWith("-SNAPSHOT"))
-// moduleName = moduleName.substring(0, moduleName.length() - "-SNAPSHOT".length());
-// int lastDash = moduleName.lastIndexOf('-');
-// String versionStr = moduleName.substring(lastDash + 1);
-// String componentName = moduleName.substring(0, lastDash);
- // if(versionStr.endsWith("-SNAPSHOT")) {
- // versionStr = readVersionFromModule(modulePath);
- // }
Version version;
-// try {
-// version = new Version(versionStr);
-// } catch (Exception e) {
+ // TODO optimise? check attributes?
String[] nameVersion = readNameVersionFromModule(modulePath);
String componentName = nameVersion[0];
String versionStr = nameVersion[1];
URI baseUri = base.toUri();
try {
if (baseUri.getScheme().equals("file")) {
- return new URI(SCHEME_A2, null, base.toString(), null);
+ String queryPart = "";
+ if (!getVariantsXOr().isEmpty()) {
+ StringJoiner sj = new StringJoiner("&");
+ for (String key : getVariantsXOr().keySet()) {
+ sj.add(key + "=" + getVariantsXOr().get(key));
+ }
+ queryPart = sj.toString();
+ }
+ return new URI(isUsingReference() ? SCHEME_A2_REFERENCE : SCHEME_A2, null, base.toString(), queryPart,
+ null);
} else {
throw new UnsupportedOperationException("Unsupported scheme " + baseUri.getScheme());
}
}
}
- public static void main(String[] args) {
- if (args.length == 0)
- throw new IllegalArgumentException("Usage: <path to A2 base>");
- try {
- Map<String, String> xOr = new HashMap<>();
- xOr.put("osgi", "equinox");
- xOr.put("swt", "rap");
- FsA2Source context = new FsA2Source(Paths.get(args[0]), xOr);
- context.load();
- context.asTree();
- } catch (Exception e) {
- e.printStackTrace();
- }
+ protected Map<String, String> getVariantsXOr() {
+ return variantsXOr;
}
+// public static void main(String[] args) {
+// if (args.length == 0)
+// throw new IllegalArgumentException("Usage: <path to A2 base>");
+// try {
+// Map<String, String> xOr = new HashMap<>();
+// xOr.put("osgi", "equinox");
+// xOr.put("swt", "rap");
+// FsA2Source context = new FsA2Source(Paths.get(args[0]), xOr);
+// context.load();
+// context.asTree();
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+
}
private final Path base;
public FsM2Source(Path base) {
- super();
+ super(false);
this.base = base;
}
private final BundleContext bc;
public OsgiContext(BundleContext bc) {
- super();
+ super(false);
this.bc = bc;
}
public OsgiContext() {
+ super(false);
Bundle bundle = FrameworkUtil.getBundle(OsgiContext.class);
if (bundle == null)
throw new IllegalArgumentException(
package org.argeo.init.a2;
+import static org.argeo.init.a2.A2Source.SCHEME_A2;
+import static org.argeo.init.a2.A2Source.SCHEME_A2_REFERENCE;
+
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;
-import org.osgi.framework.launch.Framework;
import org.osgi.framework.wiring.FrameworkWiring;
/** Loads provisioning sources into an OSGi context. */
updatedBundles.add(bundle);
}
}
- FrameworkWiring frameworkWiring = bc.getBundle(0).adapt(FrameworkWiring.class);
- frameworkWiring.refreshBundles(updatedBundles);
+// FrameworkWiring frameworkWiring = bc.getBundle(0).adapt(FrameworkWiring.class);
+// frameworkWiring.refreshBundles(updatedBundles);
}
public void registerSource(String uri) {
xOr.put(key, lst.get(0));
}
- if (A2Source.SCHEME_A2.equals(u.getScheme())) {
+ if (SCHEME_A2.equals(u.getScheme()) || SCHEME_A2_REFERENCE.equals(u.getScheme())) {
if (u.getHost() == null || "".equals(u.getHost())) {
String baseStr = u.getPath();
if (File.separatorChar == '\\') {// MS Windows
}
Path base = Paths.get(baseStr);
if (Files.exists(base)) {
- FsA2Source source = new FsA2Source(base, xOr);
+ FsA2Source source = new FsA2Source(base, xOr, SCHEME_A2_REFERENCE.equals(u.getScheme()));
source.load();
addSource(source);
OsgiBootUtils.info("Registered " + uri + " as source");
+ } else {
+ OsgiBootUtils.debug("Source " + base + " does not exist, ignoring.");
}
+ } else {
+ throw new UnsupportedOperationException(
+ "Remote installation is not yet supported, cannot add source " + u);
}
+ } else {
+ throw new IllegalArgumentException("Unkown scheme: for source " + u);
}
} catch (Exception e) {
throw new A2Exception("Cannot add source " + uri, e);
}
}
- public static void main(String[] args) {
- if (args.length == 0)
- throw new IllegalArgumentException("Usage: <path to A2 base>");
- Map<String, String> configuration = new HashMap<>();
- configuration.put("osgi.console", "2323");
- configuration.put("org.osgi.framework.bootdelegation",
- "com.sun.jndi.ldap,com.sun.jndi.ldap.sasl,com.sun.security.jgss,com.sun.jndi.dns,com.sun.nio.file,com.sun.nio.sctp,sun.nio.cs");
- Framework framework = OsgiBootUtils.launch(configuration);
- try {
- ProvisioningManager pm = new ProvisioningManager(framework.getBundleContext());
- Map<String, String> xOr = new HashMap<>();
- xOr.put("osgi", "equinox");
- xOr.put("swt", "rap");
- FsA2Source context = new FsA2Source(Paths.get(args[0]), xOr);
- context.load();
- pm.addSource(context);
- if (framework.getBundleContext().getBundles().length == 1) {// initial
- pm.install(null);
- } else {
- pm.update();
- }
-
- Thread.sleep(2000);
-
- Bundle[] bundles = framework.getBundleContext().getBundles();
- Arrays.sort(bundles, (b1, b2) -> b1.getSymbolicName().compareTo(b2.getSymbolicName()));
- for (Bundle b : bundles)
- if (b.getState() == Bundle.RESOLVED || b.getState() == Bundle.STARTING || b.getState() == Bundle.ACTIVE)
- System.out.println(b.getSymbolicName() + " " + b.getVersion());
- else
- System.err.println(b.getSymbolicName() + " " + b.getVersion() + " (" + b.getState() + ")");
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- try {
- framework.stop();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
+// public static void main(String[] args) {
+// if (args.length == 0)
+// throw new IllegalArgumentException("Usage: <path to A2 base>");
+// Map<String, String> configuration = new HashMap<>();
+// configuration.put("osgi.console", "2323");
+// configuration.put("org.osgi.framework.bootdelegation",
+// "com.sun.jndi.ldap,com.sun.jndi.ldap.sasl,com.sun.security.jgss,com.sun.jndi.dns,com.sun.nio.file,com.sun.nio.sctp,sun.nio.cs");
+// Framework framework = OsgiBootUtils.launch(configuration);
+// try {
+// ProvisioningManager pm = new ProvisioningManager(framework.getBundleContext());
+// Map<String, String> xOr = new HashMap<>();
+// xOr.put("osgi", "equinox");
+// xOr.put("swt", "rap");
+// FsA2Source context = new FsA2Source(Paths.get(args[0]), xOr);
+// context.load();
+// pm.addSource(context);
+// if (framework.getBundleContext().getBundles().length == 1) {// initial
+// pm.install(null);
+// } else {
+// pm.update();
+// }
+//
+// Thread.sleep(2000);
+//
+// Bundle[] bundles = framework.getBundleContext().getBundles();
+// Arrays.sort(bundles, (b1, b2) -> b1.getSymbolicName().compareTo(b2.getSymbolicName()));
+// for (Bundle b : bundles)
+// if (b.getState() == Bundle.RESOLVED || b.getState() == Bundle.STARTING || b.getState() == Bundle.ACTIVE)
+// System.out.println(b.getSymbolicName() + " " + b.getVersion());
+// else
+// System.err.println(b.getSymbolicName() + " " + b.getVersion() + " (" + b.getState() + ")");
+// } catch (Exception e) {
+// e.printStackTrace();
+// } finally {
+// try {
+// framework.stop();
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+// }
}
A2Source.SCHEME_A2 + "://" + homePath.toString() + "/.local/share/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/local/share/a2" + queryPart);
provisioningManager.registerSource(A2Source.SCHEME_A2 + ":///usr/share/a2" + queryPart);
+ } else if (source.trim().equals(A2Source.DEFAULT_A2_REFERENCE_URI)) {
+ if (Files.exists(homePath))
+ provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + "://" + homePath.toString()
+ + "/.local/share/a2" + queryPart);
+ provisioningManager
+ .registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/local/share/a2" + queryPart);
+ provisioningManager.registerSource(A2Source.SCHEME_A2_REFERENCE + ":///usr/share/a2" + queryPart);
} else {
provisioningManager.registerSource(source + queryPart);
}
public void bootstrap(Map<String, String> properties) {
try {
long begin = System.currentTimeMillis();
- // check properties
-// if (properties != null) {
-// for (String property : properties.keySet()) {
-// String value = properties.get(property);
-// String bcValue = bundleContext.getProperty(property);
-// if (PROP_OSGI_CONFIGURATION_AREA.equals(property) || PROP_OSGI_INSTANCE_AREA.equals(property)) {
-// try {
-// if (value.startsWith("/"))
-// value = "file://" + value;
-// URL uri = new URL(value);
-// URL bcUri = new URL(bcValue);
-// if (!uri.equals(bcUri))
-// throw new IllegalArgumentException("Property " + property + "=" + uri
-// + " is inconsistent with bundle context : " + bcUri);
-// } catch (MalformedURLException e) {
-// throw new IllegalArgumentException("Malformed property " + property, e);
-// }
-//
-// } else {
-// if (!value.equals(bcValue))
-// throw new IllegalArgumentException("Property " + property + "=" + value
-// + " is inconsistent with bundle context : " + bcValue);
-// }
-// }
-// } else {
-// String useSystemProperties = bundleContext.getProperty(PROP_OSGI_USE_SYSTEM_PROPERTIES);
-// if (useSystemProperties == null || !useSystemProperties.equals("true")) {
-// OsgiBootUtils.warn("No properties passed but " + PROP_OSGI_USE_SYSTEM_PROPERTIES + " is not set.");
-// }
-// }
// notify start
String osgiInstancePath = getProperty(PROP_OSGI_INSTANCE_AREA);
// A2 install bundles
provisioningManager.install(null);
+ // Make sure fragments are properly considered by refreshing
+ refreshFramework();
+
// start bundles
// if (properties != null && !Boolean.parseBoolean(properties.get(PROP_OSGI_USE_SYSTEM_PROPERTIES)))
startBundles(properties);
String url = (String) urls.get(i);
installUrl(url, installedBundles);
}
- refreshFramework();
+// refreshFramework();
}
/** Actually install the provided URL */
/*
* START
*/
-// /**
-// * Start bundles based on system properties.
-// *
-// * @see OsgiBoot#doStartBundles(Map)
-// */
-// public void startBundles() {
-// Properties properties = System.getProperties();
-// startBundles(properties);
-// }
/**
* Start bundles based on these properties.
FrameworkStartLevel frameworkStartLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
// default and active start levels from System properties
- Integer defaultStartLevel = Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"));
- Integer activeStartLevel = Integer.parseInt(getProperty(PROP_OSGI_STARTLEVEL, "6"));
+ int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
+ int defaultStartLevel = Integer.parseInt(getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "4"));
+ int activeStartLevel = Integer.parseInt(getProperty(PROP_OSGI_STARTLEVEL, "6"));
+ if (OsgiBootUtils.isDebug()) {
+ OsgiBootUtils.debug("OSGi default start level: "
+ + getProperty(PROP_OSGI_BUNDLES_DEFAULTSTARTLEVEL, "<not set>") + ", using " + defaultStartLevel);
+ OsgiBootUtils.debug("OSGi active start level: " + getProperty(PROP_OSGI_STARTLEVEL, "<not set>")
+ + ", using " + activeStartLevel);
+ OsgiBootUtils.debug("Framework start level: " + frameworkStartLevel.getStartLevel() + " (initial: "
+ + initialStartLevel + ")");
+ }
SortedMap<Integer, List<String>> startLevels = new TreeMap<Integer, List<String>>();
computeStartLevels(startLevels, properties, defaultStartLevel);
}
}
}
+
+ if (OsgiBootUtils.isDebug())
+ OsgiBootUtils.debug("About to set framework start level to " + activeStartLevel + " ...");
+
frameworkStartLevel.setStartLevel(activeStartLevel, (FrameworkEvent event) -> {
- if (OsgiBootUtils.isDebug())
- OsgiBootUtils.debug("Framework event: " + event);
- int initialStartLevel = frameworkStartLevel.getInitialBundleStartLevel();
- int startLevel = frameworkStartLevel.getStartLevel();
- OsgiBootUtils.debug("Framework start level: " + startLevel + " (initial: " + initialStartLevel + ")");
+ if (event.getType() == FrameworkEvent.ERROR) {
+ OsgiBootUtils.error("Start sequence failed", event.getThrowable());
+ } else {
+ if (OsgiBootUtils.isDebug())
+ OsgiBootUtils.debug("Framework started at level " + frameworkStartLevel.getStartLevel());
+ }
});
+
+// // Start the framework level after level
+// int currentStartLevel = frameworkStartLevel.getStartLevel();
+// stages: for (int stage = currentStartLevel + 1; stage <= activeStartLevel; stage++) {
+// if (OsgiBootUtils.isDebug())
+// OsgiBootUtils.debug("Starting stage " + stage + "...");
+// final int nextStage = stage;
+// final CompletableFuture<FrameworkEvent> stageCompleted = new CompletableFuture<>();
+// frameworkStartLevel.setStartLevel(nextStage, (FrameworkEvent event) -> {
+// stageCompleted.complete(event);
+// });
+// FrameworkEvent event;
+// try {
+// event = stageCompleted.get();
+// } catch (InterruptedException | ExecutionException e) {
+// throw new IllegalStateException("Cannot continue start", e);
+// }
+// if (event.getThrowable() != null) {
+// OsgiBootUtils.error("Stage " + nextStage + " failed, aborting start.", event.getThrowable());
+// break stages;
+// }
+// }
}
private static void computeStartLevels(SortedMap<Integer, List<String>> startLevels, Map<String, String> properties,
}
}
-// /**
-// * Start the provided list of bundles
-// *
-// * @return whether all bundles are now in active state
-// * @deprecated
-// */
-// @Deprecated
-// public boolean startBundles(List<String> bundlesToStart) {
-// if (bundlesToStart.size() == 0)
-// return true;
-//
-// // used to monitor ACTIVE states
-// List<Bundle> startedBundles = new ArrayList<Bundle>();
-// // used to log the bundles not found
-// List<String> notFoundBundles = new ArrayList<String>(bundlesToStart);
-//
-// Bundle[] bundles = bundleContext.getBundles();
-// long startBegin = System.currentTimeMillis();
-// for (int i = 0; i < bundles.length; i++) {
-// Bundle bundle = bundles[i];
-// String symbolicName = bundle.getSymbolicName();
-// if (bundlesToStart.contains(symbolicName))
-// try {
-// try {
-// bundle.start();
-// if (OsgiBootUtils.isDebug())
-// debug("Bundle " + symbolicName + " started");
-// } catch (Exception e) {
-// OsgiBootUtils.warn("Start of bundle " + symbolicName + " failed because of " + e
-// + ", maybe bundle is not yet resolved," + " waiting and trying again.");
-// waitForBundleResolvedOrActive(startBegin, bundle);
-// bundle.start();
-// startedBundles.add(bundle);
-// }
-// notFoundBundles.remove(symbolicName);
-// } catch (Exception e) {
-// OsgiBootUtils.warn("Bundle " + symbolicName + " cannot be started: " + e.getMessage());
-// if (OsgiBootUtils.isDebug())
-// e.printStackTrace();
-// // was found even if start failed
-// notFoundBundles.remove(symbolicName);
-// }
-// }
-//
-// for (int i = 0; i < notFoundBundles.size(); i++)
-// OsgiBootUtils.warn("Bundle '" + notFoundBundles.get(i) + "' not started because it was not found.");
-//
-// // monitors that all bundles are started
-// long beginMonitor = System.currentTimeMillis();
-// boolean allStarted = !(startedBundles.size() > 0);
-// List<String> notStarted = new ArrayList<String>();
-// while (!allStarted && (System.currentTimeMillis() - beginMonitor) < defaultTimeout) {
-// notStarted = new ArrayList<String>();
-// allStarted = true;
-// for (int i = 0; i < startedBundles.size(); i++) {
-// Bundle bundle = (Bundle) startedBundles.get(i);
-// // TODO check behaviour of lazs bundles
-// if (bundle.getState() != Bundle.ACTIVE) {
-// allStarted = false;
-// notStarted.add(bundle.getSymbolicName());
-// }
-// }
-// try {
-// Thread.sleep(100);
-// } catch (InterruptedException e) {
-// // silent
-// }
-// }
-// long duration = System.currentTimeMillis() - beginMonitor;
-//
-// if (!allStarted)
-// for (int i = 0; i < notStarted.size(); i++)
-// OsgiBootUtils.warn("Bundle '" + notStarted.get(i) + "' not ACTIVE after " + (duration / 1000) + "s");
-//
-// return allStarted;
-// }
-
-// /** Waits for a bundle to become active or resolved */
-// @Deprecated
-// private void waitForBundleResolvedOrActive(long startBegin, Bundle bundle) throws Exception {
-// int originalState = bundle.getState();
-// if ((originalState == Bundle.RESOLVED) || (originalState == Bundle.ACTIVE))
-// return;
-//
-// String originalStateStr = OsgiBootUtils.stateAsString(originalState);
-//
-// int currentState = bundle.getState();
-// while (!(currentState == Bundle.RESOLVED || currentState == Bundle.ACTIVE)) {
-// long now = System.currentTimeMillis();
-// if ((now - startBegin) > defaultTimeout * 10)
-// throw new Exception("Bundle " + bundle.getSymbolicName() + " was not RESOLVED or ACTIVE after "
-// + (now - startBegin) + "ms (originalState=" + originalStateStr + ", currentState="
-// + OsgiBootUtils.stateAsString(currentState) + ")");
-//
-// try {
-// Thread.sleep(100l);
-// } catch (InterruptedException e) {
-// // silent
-// }
-// currentState = bundle.getState();
-// }
-// }
-
/*
* BUNDLE PATTERNS INSTALLATION
*/
distributionBundle = new DistributionBundle(baseUrl, distributionUrl, localCache);
}
- // if (baseUrl != null && !(distributionUrl.startsWith("http") ||
- // distributionUrl.startsWith("file"))) {
- // // relative url
- // distributionBundle = new DistributionBundle(baseUrl, distributionUrl,
- // localCache);
- // } else {
- // distributionBundle = new DistributionBundle(distributionUrl);
- // if (baseUrl != null)
- // distributionBundle.setBaseUrl(baseUrl);
- // }
distributionBundle.processUrl();
return distributionBundle.listUrls();
}
private void refreshFramework() {
Bundle systemBundle = bundleContext.getBundle(0);
FrameworkWiring frameworkWiring = systemBundle.adapt(FrameworkWiring.class);
+ // TODO deal with refresh breaking native loading (e.g SWT)
frameworkWiring.refreshBundles(null);
}
* BEAN METHODS
*/
-// public boolean getDebug() {
-// return OsgiBootUtils.debug;
-// }
-
- // public void setDebug(boolean debug) {
- // this.debug = debug;
- // }
-
public BundleContext getBundleContext() {
return bundleContext;
}
-// public String getLocalCache() {
-// return localCache;
-// }
-
- // public void setDefaultTimeout(long defaultTimeout) {
- // this.defaultTimeout = defaultTimeout;
- // }
-
- // public boolean isExcludeSvn() {
- // return excludeSvn;
- // }
- //
- // public void setExcludeSvn(boolean excludeSvn) {
- // this.excludeSvn = excludeSvn;
- // }
-
- /*
- * INTERNAL CLASSES
- */
-
}
+++ /dev/null
-log4j.rootLogger=WARN, console
-
-log4j.logger.org.argeo=INFO
-
-## Appenders
-log4j.appender.console=org.apache.log4j.ConsoleAppender
-log4j.appender.console.layout=org.apache.log4j.PatternLayout
-log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c - [%t]%n
-
-log4j.appender.development=org.apache.log4j.ConsoleAppender
-log4j.appender.development.layout=org.apache.log4j.PatternLayout
-log4j.appender.development.layout.ConversionPattern=%d{ABSOLUTE} %m (%F:%L) [%t] %p %n
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
- <attributes>
- <attribute name="module" value="true"/>
- </attributes>
- </classpathentry>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.util</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- <nature>org.eclipse.pde.PluginNature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-/MANIFEST.MF
+++ /dev/null
-Bundle-Activator: org.argeo.osgi.internal.EnterpriseActivator
-Bundle-ActivationPolicy: lazy
-
-Import-Package: org.osgi.*;version=0.0.0,\
-!org.apache.commons.logging,\
-*
+++ /dev/null
-source.. = src/
\ No newline at end of file
+++ /dev/null
-package org.argeo.osgi.internal;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-/**
- * Called to gather information about the OSGi runtime. Should not activate
- * anything else that canonical monitoring services (not creating implicit
- * APIs), which is the responsibility of higher levels.
- */
-public class EnterpriseActivator implements BundleActivator {
-
- @Override
- public void start(BundleContext context) throws Exception {
- }
-
- @Override
- public void stop(BundleContext context) throws Exception {
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.provisioning;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.zip.ZipInputStream;
-
-import org.osgi.service.provisioning.ProvisioningService;
-
-public class SimpleProvisioningService implements ProvisioningService {
- private Map<String, Object> map = Collections.synchronizedSortedMap(new TreeMap<>());
-
- public SimpleProvisioningService() {
- // update count
- map.put(PROVISIONING_UPDATE_COUNT, 0);
- }
-
- @Override
- public Dictionary<String, Object> getInformation() {
- return new Information();
- }
-
- @Override
- public synchronized void setInformation(Dictionary<String, ?> info) {
- map.clear();
- addInformation(info);
- }
-
- @Override
- public synchronized void addInformation(Dictionary<String, ?> info) {
- Enumeration<String> e = info.keys();
- while (e.hasMoreElements()) {
- String key = e.nextElement();
- map.put(key, info.get(key));
- }
- incrementProvisioningUpdateCount();
- }
-
- protected synchronized void incrementProvisioningUpdateCount() {
- Integer current = (Integer) map.get(PROVISIONING_UPDATE_COUNT);
- Integer newValue = current + 1;
- map.put(PROVISIONING_UPDATE_COUNT, newValue);
- }
-
- @Override
- public synchronized void addInformation(ZipInputStream zis) throws IOException {
- throw new UnsupportedOperationException();
- }
-
- class Information extends Dictionary<String, Object> {
-
- @Override
- public int size() {
- return map.size();
- }
-
- @Override
- public boolean isEmpty() {
- return map.isEmpty();
- }
-
- @Override
- public Enumeration<String> keys() {
- Iterator<String> it = map.keySet().iterator();
- return new Enumeration<String>() {
-
- @Override
- public boolean hasMoreElements() {
- return it.hasNext();
- }
-
- @Override
- public String nextElement() {
- return it.next();
- }
-
- };
- }
-
- @Override
- public Enumeration<Object> elements() {
- Iterator<Object> it = map.values().iterator();
- return new Enumeration<Object>() {
-
- @Override
- public boolean hasMoreElements() {
- return it.hasNext();
- }
-
- @Override
- public Object nextElement() {
- return it.next();
- }
-
- };
- }
-
- @Override
- public Object get(Object key) {
- return map.get(key);
- }
-
- @Override
- public Object put(String key, Object value) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Object remove(Object key) {
- throw new UnsupportedOperationException();
- }
-
- }
-}
+++ /dev/null
-/** OSGi provisioning support. */
-package org.argeo.osgi.provisioning;
\ No newline at end of file
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.security.auth.x500.X500Principal;
-
-import org.osgi.service.useradmin.Authorization;
-
-/** An {@link Authorization} which combines roles form various auth sources. */
-class AggregatingAuthorization implements Authorization {
- private final String name;
- private final String displayName;
- private final Set<String> systemRoles;
- private final Set<String> roles;
-
- public AggregatingAuthorization(String name, String displayName, Set<String> systemRoles, String[] roles) {
- this.name = new X500Principal(name).getName();
- this.displayName = displayName;
- this.systemRoles = Collections.unmodifiableSet(new HashSet<>(systemRoles));
- Set<String> temp = new HashSet<>();
- for (String role : roles) {
- if (!temp.contains(role))
- temp.add(role);
- }
- this.roles = Collections.unmodifiableSet(temp);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public boolean hasRole(String name) {
- if (systemRoles.contains(name))
- return true;
- if (roles.contains(name))
- return true;
- return false;
- }
-
- @Override
- public String[] getRoles() {
- int size = systemRoles.size() + roles.size();
- List<String> res = new ArrayList<String>(size);
- res.addAll(systemRoles);
- res.addAll(roles);
- return res.toArray(new String[size]);
- }
-
- @Override
- public int hashCode() {
- if (name == null)
- return super.hashCode();
- return name.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Authorization))
- return false;
- Authorization that = (Authorization) obj;
- if (name == null)
- return that.getName() == null;
- return name.equals(that.getName());
- }
-
- @Override
- public String toString() {
- return displayName;
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import static org.argeo.osgi.useradmin.DirectoryUserAdmin.toLdapName;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.DirectoryConf;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/**
- * Aggregates multiple {@link UserDirectory} and integrates them with system
- * roles.
- */
-public class AggregatingUserAdmin implements UserAdmin {
- private final LdapName systemRolesBaseDn;
- private final LdapName tokensBaseDn;
-
- // DAOs
- private DirectoryUserAdmin systemRoles = null;
- private DirectoryUserAdmin tokens = null;
- private Map<LdapName, DirectoryUserAdmin> businessRoles = new HashMap<LdapName, DirectoryUserAdmin>();
-
- // TODO rather use an empty constructor and an init method
- public AggregatingUserAdmin(String systemRolesBaseDn, String tokensBaseDn) {
- try {
- this.systemRolesBaseDn = new LdapName(systemRolesBaseDn);
- if (tokensBaseDn != null)
- this.tokensBaseDn = new LdapName(tokensBaseDn);
- else
- this.tokensBaseDn = null;
- } catch (InvalidNameException e) {
- throw new IllegalStateException("Cannot initialize " + AggregatingUserAdmin.class, e);
- }
- }
-
- @Override
- public Role createRole(String name, int type) {
- return findUserAdmin(name).createRole(name, type);
- }
-
- @Override
- public boolean removeRole(String name) {
- boolean actuallyDeleted = findUserAdmin(name).removeRole(name);
- systemRoles.removeRole(name);
- return actuallyDeleted;
- }
-
- @Override
- public Role getRole(String name) {
- return findUserAdmin(name).getRole(name);
- }
-
- @Override
- public Role[] getRoles(String filter) throws InvalidSyntaxException {
- List<Role> res = new ArrayList<Role>();
- for (UserAdmin userAdmin : businessRoles.values()) {
- res.addAll(Arrays.asList(userAdmin.getRoles(filter)));
- }
- res.addAll(Arrays.asList(systemRoles.getRoles(filter)));
- return res.toArray(new Role[res.size()]);
- }
-
- @Override
- public User getUser(String key, String value) {
- List<User> res = new ArrayList<User>();
- for (UserAdmin userAdmin : businessRoles.values()) {
- User u = userAdmin.getUser(key, value);
- if (u != null)
- res.add(u);
- }
- // Note: node roles cannot contain users, so it is not searched
- return res.size() == 1 ? res.get(0) : null;
- }
-
- /** Builds an authorisation by scanning all referentials. */
- @Override
- public Authorization getAuthorization(User user) {
- if (user == null) {// anonymous
- return systemRoles.getAuthorization(null);
- }
- DirectoryUserAdmin userReferentialOfThisUser = findUserAdmin(user.getName());
- Authorization rawAuthorization = userReferentialOfThisUser.getAuthorization(user);
- User retrievedUser = (User) userReferentialOfThisUser.getRole(user.getName());
- String usernameToUse;
- String displayNameToUse;
- if (user instanceof Group) {
- // TODO check whether this is still working
- String ownerDn = TokenUtils.userDn((Group) user);
- if (ownerDn != null) {// tokens
- UserAdmin ownerUserAdmin = findUserAdmin(ownerDn);
- User ownerUser = (User) ownerUserAdmin.getRole(ownerDn);
- usernameToUse = ownerDn;
- displayNameToUse = LdifAuthorization.extractDisplayName(ownerUser);
- } else {
- usernameToUse = rawAuthorization.getName();
- displayNameToUse = rawAuthorization.toString();
- }
- } else {// regular users
- usernameToUse = rawAuthorization.getName();
- displayNameToUse = rawAuthorization.toString();
- }
-
- // gather roles from other referentials
- List<String> allRoles = new ArrayList<>(Arrays.asList(rawAuthorization.getRoles()));
- for (LdapName otherBaseDn : businessRoles.keySet()) {
- if (otherBaseDn.equals(userReferentialOfThisUser.getBaseDn()))
- continue;
- DirectoryUserAdmin otherUserAdmin = userAdminToUse(user, businessRoles.get(otherBaseDn));
- if (otherUserAdmin == null)
- continue;
- Authorization auth = otherUserAdmin.getAuthorization(retrievedUser);
- allRoles.addAll(Arrays.asList(auth.getRoles()));
-
- }
-
- // integrate system roles
- final DirectoryUserAdmin userAdminToUse = userAdminToUse(retrievedUser, userReferentialOfThisUser);
- Objects.requireNonNull(userAdminToUse);
-
- try {
- Set<String> sysRoles = new HashSet<String>();
- for (String role : rawAuthorization.getRoles()) {
- User userOrGroup = (User) userAdminToUse.getRole(role);
- Authorization auth = systemRoles.getAuthorization(userOrGroup);
- systemRoles: for (String systemRole : auth.getRoles()) {
- if (role.equals(systemRole))
- continue systemRoles;
- sysRoles.add(systemRole);
- }
-// sysRoles.addAll(Arrays.asList(auth.getRoles()));
- }
- addAbstractSystemRoles(rawAuthorization, sysRoles);
- Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
- allRoles.toArray(new String[allRoles.size()]));
- return authorization;
- } finally {
- if (userAdminToUse != null && userAdminToUse.isScoped()) {
- userAdminToUse.destroy();
- }
- }
- }
-
- /** Decide whether to scope or not */
- private DirectoryUserAdmin userAdminToUse(User user, DirectoryUserAdmin userAdmin) {
- if (user instanceof DirectoryUser) {
- return userAdmin;
- } else if (user instanceof AuthenticatingUser) {
- return userAdmin.scope(user).orElse(null);
- } else {
- throw new IllegalArgumentException("Unsupported user type " + user.getClass());
- }
-
- }
-
- /**
- * Enrich with application-specific roles which are strictly programmatic, such
- * as anonymous/user semantics.
- */
- protected void addAbstractSystemRoles(Authorization rawAuthorization, Set<String> sysRoles) {
-
- }
-
- //
- // USER ADMIN AGGREGATOR
- //
- protected void addUserDirectory(UserDirectory ud) {
- if (!(ud instanceof DirectoryUserAdmin))
- throw new IllegalArgumentException("Only " + DirectoryUserAdmin.class.getName() + " is supported");
- DirectoryUserAdmin userDirectory = (DirectoryUserAdmin) ud;
- String basePath = userDirectory.getBase();
- if (isSystemRolesBaseDn(basePath)) {
- this.systemRoles = userDirectory;
- systemRoles.setExternalRoles(this);
- } else if (isTokensBaseDn(basePath)) {
- this.tokens = userDirectory;
- tokens.setExternalRoles(this);
- } else {
- LdapName baseDn = toLdapName(basePath);
- if (businessRoles.containsKey(baseDn))
- throw new IllegalStateException("There is already a user admin for " + baseDn);
- businessRoles.put(baseDn, userDirectory);
- }
- userDirectory.init();
- postAdd(userDirectory);
- }
-
- /** Called after a new user directory has been added */
- protected void postAdd(UserDirectory userDirectory) {
- }
-
- private DirectoryUserAdmin findUserAdmin(String name) {
- try {
- return findUserAdmin(new LdapName(name));
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Badly formatted name " + name, e);
- }
- }
-
- private DirectoryUserAdmin findUserAdmin(LdapName name) {
- if (name.startsWith(systemRolesBaseDn))
- return systemRoles;
- if (tokensBaseDn != null && name.startsWith(tokensBaseDn))
- return tokens;
- List<DirectoryUserAdmin> res = new ArrayList<>(1);
- userDirectories: for (LdapName baseDn : businessRoles.keySet()) {
- DirectoryUserAdmin userDirectory = businessRoles.get(baseDn);
- if (name.startsWith(baseDn)) {
- if (userDirectory.isDisabled())
- continue userDirectories;
-// if (res.isEmpty()) {
- res.add(userDirectory);
-// } else {
-// for (AbstractUserDirectory ud : res) {
-// LdapName bd = ud.getBaseDn();
-// if (userDirectory.getBaseDn().startsWith(bd)) {
-// // child user directory
-// }
-// }
-// }
- }
- }
- if (res.size() == 0)
- throw new IllegalStateException("Cannot find user admin for " + name);
- if (res.size() > 1)
- throw new IllegalStateException("Multiple user admin found for " + name);
- return res.get(0);
- }
-
- protected boolean isSystemRolesBaseDn(String basePath) {
- return toLdapName(basePath).equals(systemRolesBaseDn);
- }
-
- protected boolean isTokensBaseDn(String basePath) {
- return tokensBaseDn != null && toLdapName(basePath).equals(tokensBaseDn);
- }
-
-// protected Dictionary<String, Object> currentState() {
-// Dictionary<String, Object> res = new Hashtable<String, Object>();
-// // res.put(NodeConstants.CN, NodeConstants.DEFAULT);
-// for (LdapName name : businessRoles.keySet()) {
-// AbstractUserDirectory userDirectory = businessRoles.get(name);
-// String uri = UserAdminConf.propertiesAsUri(userDirectory.getProperties()).toString();
-// res.put(uri, "");
-// }
-// return res;
-// }
-
- public void start() {
- if (systemRoles == null) {
- // TODO do we really need separate system roles?
- Hashtable<String, Object> properties = new Hashtable<>();
- properties.put(DirectoryConf.baseDn.name(), "ou=roles,ou=system");
- systemRoles = new DirectoryUserAdmin(properties);
- }
- }
-
- public void stop() {
- for (LdapName name : businessRoles.keySet()) {
- DirectoryUserAdmin userDirectory = businessRoles.get(name);
- destroy(userDirectory);
- }
- businessRoles.clear();
- businessRoles = null;
- destroy(systemRoles);
- systemRoles = null;
- }
-
- private void destroy(DirectoryUserAdmin userDirectory) {
- preDestroy(userDirectory);
- userDirectory.destroy();
- }
-
-// protected void removeUserDirectory(UserDirectory userDirectory) {
-// LdapName baseDn = toLdapName(userDirectory.getContext());
-// businessRoles.remove(baseDn);
-// if (userDirectory instanceof DirectoryUserAdmin)
-// destroy((DirectoryUserAdmin) userDirectory);
-// }
-
- @Deprecated
- protected void removeUserDirectory(String basePath) {
- if (isSystemRolesBaseDn(basePath))
- throw new IllegalArgumentException("System roles cannot be removed ");
- LdapName baseDn = toLdapName(basePath);
- if (!businessRoles.containsKey(baseDn))
- throw new IllegalStateException("No user directory registered for " + baseDn);
- DirectoryUserAdmin userDirectory = businessRoles.remove(baseDn);
- destroy(userDirectory);
- }
-
- /**
- * Called before each user directory is destroyed, so that additional actions
- * can be performed.
- */
- protected void preDestroy(UserDirectory userDirectory) {
- }
-
- public Set<UserDirectory> getUserDirectories() {
- TreeSet<UserDirectory> res = new TreeSet<>((o1, o2) -> o1.getBase().compareTo(o2.getBase()));
- res.addAll(businessRoles.values());
- res.add(systemRoles);
- return res;
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.DirectoryDigestUtils;
-import org.osgi.service.useradmin.User;
-
-/**
- * A special user type used during authentication in order to provide the
- * credentials required for scoping the user admin.
- */
-public class AuthenticatingUser implements User {
- /** From com.sun.security.auth.module.*LoginModule */
- public final static String SHARED_STATE_NAME = "javax.security.auth.login.name";
- /** From com.sun.security.auth.module.*LoginModule */
- public final static String SHARED_STATE_PWD = "javax.security.auth.login.password";
-
- private final String name;
- private final Dictionary<String, Object> credentials;
-
- public AuthenticatingUser(LdapName name) {
- if (name == null)
- throw new NullPointerException("Provided name cannot be null.");
- this.name = name.toString();
- this.credentials = new Hashtable<>();
- }
-
- public AuthenticatingUser(String name, Dictionary<String, Object> credentials) {
- this.name = name;
- this.credentials = credentials;
- }
-
- public AuthenticatingUser(String name, char[] password) {
- if (name == null)
- throw new NullPointerException("Provided name cannot be null.");
- this.name = name;
- credentials = new Hashtable<>();
- credentials.put(SHARED_STATE_NAME, name);
- byte[] pwd = DirectoryDigestUtils.charsToBytes(password);
- credentials.put(SHARED_STATE_PWD, pwd);
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public int getType() {
- return User.USER;
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Dictionary getProperties() {
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings({ "rawtypes", "unchecked" })
- @Override
- public Dictionary getCredentials() {
- return credentials;
- }
-
- @Override
- public boolean hasCredential(String key, Object value) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- @Override
- public String toString() {
- return "Authenticating user " + name;
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import org.osgi.service.useradmin.Group;
-
-/** A group in a user directroy. */
-interface DirectoryGroup extends Group, DirectoryUser {
-// List<LdapName> getMemberNames();
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import org.osgi.service.useradmin.User;
-
-/** A user in a user directory. */
-interface DirectoryUser extends User {
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import static org.argeo.util.naming.LdapAttrs.objectClass;
-import static org.argeo.util.naming.LdapObjs.extensibleObject;
-import static org.argeo.util.naming.LdapObjs.inetOrgPerson;
-import static org.argeo.util.naming.LdapObjs.organizationalPerson;
-import static org.argeo.util.naming.LdapObjs.person;
-import static org.argeo.util.naming.LdapObjs.top;
-
-import java.net.URI;
-import java.security.PrivilegedAction;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
-
-import javax.naming.Context;
-import javax.naming.InvalidNameException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-import javax.security.auth.Subject;
-import javax.security.auth.kerberos.KerberosTicket;
-
-import org.argeo.util.CurrentSubject;
-import org.argeo.util.directory.DirectoryConf;
-import org.argeo.util.directory.DirectoryDigestUtils;
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.directory.ldap.AbstractLdapDirectory;
-import org.argeo.util.directory.ldap.LdapDao;
-import org.argeo.util.directory.ldap.LdapEntry;
-import org.argeo.util.directory.ldap.LdapEntryWorkingCopy;
-import org.argeo.util.directory.ldap.LdapNameUtils;
-import org.argeo.util.directory.ldap.LdifDao;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/** Base class for a {@link UserDirectory}. */
-public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdmin, UserDirectory {
-
- private UserAdmin externalRoles;
-
- // Transaction
- public DirectoryUserAdmin(URI uriArg, Dictionary<String, ?> props) {
- this(uriArg, props, false);
- }
-
- public DirectoryUserAdmin(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
- super(uriArg, props, scoped);
- }
-
- public DirectoryUserAdmin(Dictionary<String, ?> props) {
- this(null, props);
- }
-
- /*
- * ABSTRACT METHODS
- */
-
- protected Optional<DirectoryUserAdmin> scope(User user) {
- if (getDirectoryDao() instanceof LdapDao) {
- return scopeLdap(user);
- } else if (getDirectoryDao() instanceof LdifDao) {
- return scopeLdif(user);
- } else {
- throw new IllegalStateException("Unsupported DAO " + getDirectoryDao().getClass());
- }
- }
-
- protected Optional<DirectoryUserAdmin> scopeLdap(User user) {
- Dictionary<String, Object> credentials = user.getCredentials();
- String username = (String) credentials.get(SHARED_STATE_USERNAME);
- if (username == null)
- username = user.getName();
- Dictionary<String, Object> properties = cloneConfigProperties();
- properties.put(Context.SECURITY_PRINCIPAL, username.toString());
- Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
- byte[] pwd = (byte[]) pwdCred;
- if (pwd != null) {
- char[] password = DirectoryDigestUtils.bytesToChars(pwd);
- properties.put(Context.SECURITY_CREDENTIALS, new String(password));
- } else {
- properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
- }
- DirectoryUserAdmin scopedDirectory = new DirectoryUserAdmin(null, properties, true);
- scopedDirectory.init();
- // check connection
- if (!scopedDirectory.getDirectoryDao().checkConnection())
- return Optional.empty();
- return Optional.of(scopedDirectory);
- }
-
- protected Optional<DirectoryUserAdmin> scopeLdif(User user) {
- Dictionary<String, Object> credentials = user.getCredentials();
- String username = (String) credentials.get(SHARED_STATE_USERNAME);
- if (username == null)
- username = user.getName();
- Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
- byte[] pwd = (byte[]) pwdCred;
- if (pwd != null) {
- char[] password = DirectoryDigestUtils.bytesToChars(pwd);
- User directoryUser = (User) getRole(username);
- if (!directoryUser.hasCredential(null, password))
- throw new IllegalStateException("Invalid credentials");
- } else {
- throw new IllegalStateException("Password is required");
- }
- Dictionary<String, Object> properties = cloneConfigProperties();
- properties.put(DirectoryConf.readOnly.name(), "true");
- DirectoryUserAdmin scopedUserAdmin = new DirectoryUserAdmin(null, properties, true);
- // FIXME do it better
- ((LdifDao) getDirectoryDao()).scope((LdifDao) scopedUserAdmin.getDirectoryDao());
- // no need to check authentication
- scopedUserAdmin.init();
- return Optional.of(scopedUserAdmin);
- }
-
- @Override
- public String getRolePath(Role role) {
- return nameToRelativePath(LdapNameUtils.toLdapName(role.getName()));
- }
-
- @Override
- public String getRoleSimpleName(Role role) {
- LdapName dn = LdapNameUtils.toLdapName(role.getName());
- String name = LdapNameUtils.getLastRdnValue(dn);
- return name;
- }
-
- @Override
- public Role getRoleByPath(String path) {
- LdapEntry entry = doGetRole(pathToName(path));
- if (!(entry instanceof Role)) {
- return null;
-// throw new IllegalStateException("Path must be a UserAdmin Role.");
- } else {
- return (Role) entry;
- }
- }
-
- protected List<Role> getAllRoles(DirectoryUser user) {
- List<Role> allRoles = new ArrayList<Role>();
- if (user != null) {
- collectRoles((LdapEntry) user, allRoles);
- allRoles.add(user);
- } else
- collectAnonymousRoles(allRoles);
- return allRoles;
- }
-
- private void collectRoles(LdapEntry user, List<Role> allRoles) {
- List<LdapEntry> allEntries = new ArrayList<>();
- LdapEntry entry = user;
- collectGroups(entry, allEntries);
- for (LdapEntry e : allEntries) {
- if (e instanceof Role)
- allRoles.add((Role) e);
- }
- }
-
- private void collectAnonymousRoles(List<Role> allRoles) {
- // TODO gather anonymous roles
- }
-
- // USER ADMIN
- @Override
- public Role getRole(String name) {
- return (Role) doGetRole(toLdapName(name));
- }
-
- @Override
- public Role[] getRoles(String filter) throws InvalidSyntaxException {
- List<? extends Role> res = getRoles(getBaseDn(), filter, true);
- return res.toArray(new Role[res.size()]);
- }
-
- List<DirectoryUser> getRoles(LdapName searchBase, String filter, boolean deep) throws InvalidSyntaxException {
- LdapEntryWorkingCopy wc = getWorkingCopy();
-// Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
- List<LdapEntry> searchRes = getDirectoryDao().doGetEntries(searchBase, filter, deep);
- List<DirectoryUser> res = new ArrayList<>();
- for (LdapEntry entry : searchRes)
- res.add((DirectoryUser) entry);
- if (wc != null) {
- for (Iterator<DirectoryUser> it = res.iterator(); it.hasNext();) {
- DirectoryUser user = (DirectoryUser) it.next();
- LdapName dn = LdapNameUtils.toLdapName(user.getName());
- if (wc.getDeletedData().containsKey(dn))
- it.remove();
- }
- Filter f = filter != null ? FrameworkUtil.createFilter(filter) : null;
- for (LdapEntry ldapEntry : wc.getNewData().values()) {
- DirectoryUser user = (DirectoryUser) ldapEntry;
- if (f == null || f.match(user.getProperties()))
- res.add(user);
- }
- // no need to check modified users,
- // since doGetRoles was already based on the modified attributes
- }
- return res;
- }
-
- @Override
- public User getUser(String key, String value) {
- // TODO check value null or empty
- List<DirectoryUser> collectedUsers = new ArrayList<DirectoryUser>();
- if (key != null) {
- doGetUser(key, value, collectedUsers);
- } else {
- throw new IllegalArgumentException("Key cannot be null");
- }
-
- if (collectedUsers.size() == 1) {
- return collectedUsers.get(0);
- } else if (collectedUsers.size() > 1) {
- // log.warn(collectedUsers.size() + " users for " + (key != null ? key + "=" :
- // "") + value);
- }
- return null;
- }
-
- protected void doGetUser(String key, String value, List<DirectoryUser> collectedUsers) {
- String f = "(" + key + "=" + value + ")";
- List<LdapEntry> users = getDirectoryDao().doGetEntries(getBaseDn(), f, true);
- for (LdapEntry entry : users)
- collectedUsers.add((DirectoryUser) entry);
- }
-
- @Override
- public Authorization getAuthorization(User user) {
- if (user == null) {// anonymous
- return new LdifAuthorization(user, getAllRoles(null));
- }
- LdapName userName = toLdapName(user.getName());
- if (isExternal(userName) && user instanceof LdapEntry) {
- List<Role> allRoles = new ArrayList<Role>();
- collectRoles((LdapEntry) user, allRoles);
- return new LdifAuthorization(user, allRoles);
- } else {
-
- Subject currentSubject = CurrentSubject.current();
- if (currentSubject != null //
- && getRealm().isPresent() //
- && !currentSubject.getPrivateCredentials(Authorization.class).isEmpty() //
- && !currentSubject.getPrivateCredentials(KerberosTicket.class).isEmpty()) //
- {
- // TODO not only Kerberos but also bind scope with kept password ?
- Authorization auth = currentSubject.getPrivateCredentials(Authorization.class).iterator().next();
- // bind with authenticating user
- DirectoryUserAdmin scopedUserAdmin = CurrentSubject.callAs(currentSubject, () -> {
- return scope(new AuthenticatingUser(auth.getName(), new Hashtable<>())).orElseThrow();
- });
- return getAuthorizationFromScoped(scopedUserAdmin, user);
- }
-
- if (user instanceof DirectoryUser) {
- return new LdifAuthorization(user, getAllRoles((DirectoryUser) user));
- } else {
- // bind with authenticating user
- DirectoryUserAdmin scopedUserAdmin = scope(user).orElseThrow();
- return getAuthorizationFromScoped(scopedUserAdmin, user);
- }
- }
- }
-
- private Authorization getAuthorizationFromScoped(DirectoryUserAdmin scopedUserAdmin, User user) {
- try {
- DirectoryUser directoryUser = (DirectoryUser) scopedUserAdmin.getRole(user.getName());
- if (directoryUser == null)
- throw new IllegalStateException("No scoped user found for " + user);
- LdifAuthorization authorization = new LdifAuthorization(directoryUser,
- scopedUserAdmin.getAllRoles(directoryUser));
- return authorization;
- } finally {
- scopedUserAdmin.destroy();
- }
- }
-
- @Override
- public Role createRole(String name, int type) {
- checkEdit();
- LdapEntryWorkingCopy wc = getWorkingCopy();
- LdapName dn = toLdapName(name);
- if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
- || wc.getNewData().containsKey(dn))
- throw new IllegalArgumentException("Already a role " + name);
- BasicAttributes attrs = new BasicAttributes(true);
- // attrs.put(LdifName.dn.name(), dn.toString());
- Rdn nameRdn = dn.getRdn(dn.size() - 1);
- // TODO deal with multiple attr RDN
- attrs.put(nameRdn.getType(), nameRdn.getValue());
- if (wc.getDeletedData().containsKey(dn)) {
- wc.getDeletedData().remove(dn);
- wc.getModifiedData().put(dn, attrs);
- return getRole(name);
- } else {
- wc.getModifiedData().put(dn, attrs);
- LdapEntry newRole = doCreateRole(dn, type, attrs);
- wc.getNewData().put(dn, newRole);
- return (Role) newRole;
- }
- }
-
- private LdapEntry doCreateRole(LdapName dn, int type, Attributes attrs) {
- LdapEntry newRole;
- BasicAttribute objClass = new BasicAttribute(objectClass.name());
- if (type == Role.USER) {
- String userObjClass = getUserObjectClass();
- objClass.add(userObjClass);
- if (inetOrgPerson.name().equals(userObjClass)) {
- objClass.add(organizationalPerson.name());
- objClass.add(person.name());
- } else if (organizationalPerson.name().equals(userObjClass)) {
- objClass.add(person.name());
- }
- objClass.add(top.name());
- objClass.add(extensibleObject.name());
- attrs.put(objClass);
- newRole = newUser(dn);
- } else if (type == Role.GROUP) {
- String groupObjClass = getGroupObjectClass();
- objClass.add(groupObjClass);
- // objClass.add(LdifName.extensibleObject.name());
- objClass.add(top.name());
- attrs.put(objClass);
- newRole = newGroup(dn);
- } else
- throw new IllegalArgumentException("Unsupported type " + type);
- return newRole;
- }
-
- @Override
- public boolean removeRole(String name) {
- return removeEntry(LdapNameUtils.toLdapName(name));
- }
-
- /*
- * HIERARCHY
- */
- @Override
- public HierarchyUnit getHierarchyUnit(Role role) {
- LdapName dn = LdapNameUtils.toLdapName(role.getName());
- LdapName huDn = LdapNameUtils.getParent(dn);
- HierarchyUnit hierarchyUnit = getDirectoryDao().doGetHierarchyUnit(huDn);
- if (hierarchyUnit == null)
- throw new IllegalStateException("No hierarchy unit found for " + role);
- return hierarchyUnit;
- }
-
- @Override
- public Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) {
- LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getBase());
- try {
- return getRoles(dn, filter, deep);
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Cannot filter " + filter + " " + dn, e);
- }
- }
-
- /*
- * ROLES CREATION
- */
- protected LdapEntry newUser(LdapName name) {
- // TODO support devices, applications, etc.
- return new LdifUser(this, name);
- }
-
- protected LdapEntry newGroup(LdapName name) {
- return new LdifGroup(this, name);
-
- }
-
- // GETTERS
- protected UserAdmin getExternalRoles() {
- return externalRoles;
- }
-
- public void setExternalRoles(UserAdmin externalRoles) {
- this.externalRoles = externalRoles;
- }
-
- /*
- * STATIC UTILITIES
- */
- static LdapName toLdapName(String name) {
- try {
- return new LdapName(name);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException(name + " is not an LDAP name", e);
- }
- }
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.List;
-
-import org.argeo.util.naming.LdapAttrs;
-import org.osgi.service.useradmin.Authorization;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/** Basic authorization. */
-class LdifAuthorization implements Authorization {
- private final String name;
- private final String displayName;
- private final List<String> allRoles;
-
- public LdifAuthorization(User user, List<Role> allRoles) {
- if (user == null) {
- this.name = null;
- this.displayName = "anonymous";
- } else {
- this.name = user.getName();
- this.displayName = extractDisplayName(user);
- }
- // roles
- String[] roles = new String[allRoles.size()];
- for (int i = 0; i < allRoles.size(); i++) {
- roles[i] = allRoles.get(i).getName();
- }
- this.allRoles = Collections.unmodifiableList(Arrays.asList(roles));
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public boolean hasRole(String name) {
- return allRoles.contains(name);
- }
-
- @Override
- public String[] getRoles() {
- return allRoles.toArray(new String[allRoles.size()]);
- }
-
- @Override
- public int hashCode() {
- if (name == null)
- return super.hashCode();
- return name.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Authorization))
- return false;
- Authorization that = (Authorization) obj;
- if (name == null)
- return that.getName() == null;
- return name.equals(that.getName());
- }
-
- @Override
- public String toString() {
- return displayName;
- }
-
- final static String extractDisplayName(User user) {
- Dictionary<String, Object> props = user.getProperties();
- Object displayName = props.get(LdapAttrs.displayName.name());
- if (displayName == null)
- displayName = props.get(LdapAttrs.cn.name());
- if (displayName == null)
- displayName = props.get(LdapAttrs.uid.name());
- if (displayName == null)
- displayName = user.getName();
- if (displayName == null)
- throw new IllegalStateException("Cannot set display name for " + user);
- return displayName.toString();
- }
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.InvalidNameException;
-import javax.naming.directory.Attribute;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.ldap.AbstractLdapDirectory;
-import org.osgi.service.useradmin.Role;
-
-/** Directory group implementation */
-class LdifGroup extends LdifUser implements DirectoryGroup {
- private final String memberAttributeId;
-
- LdifGroup(AbstractLdapDirectory userAdmin, LdapName dn) {
- super(userAdmin, dn);
- memberAttributeId = userAdmin.getMemberAttributeId();
- }
-
- @Override
- public boolean addMember(Role role) {
- try {
- Role foundRole = findRole(new LdapName(role.getName()));
- if (foundRole == null)
- throw new UnsupportedOperationException(
- "Adding role " + role.getName() + " is unsupported within this context.");
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Role name" + role.getName() + " is badly formatted");
- }
-
- getUserAdmin().checkEdit();
- if (!isEditing())
- startEditing();
-
- Attribute member = getAttributes().get(memberAttributeId);
- if (member != null) {
- if (member.contains(role.getName()))
- return false;
- else
- member.add(role.getName());
- } else
- getAttributes().put(memberAttributeId, role.getName());
- return true;
- }
-
- @Override
- public boolean addRequiredMember(Role role) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean removeMember(Role role) {
- getUserAdmin().checkEdit();
- if (!isEditing())
- startEditing();
-
- Attribute member = getAttributes().get(memberAttributeId);
- if (member != null) {
- if (!member.contains(role.getName()))
- return false;
- member.remove(role.getName());
- return true;
- } else
- return false;
- }
-
- @Override
- public Role[] getMembers() {
- List<Role> directMembers = new ArrayList<Role>();
- for (LdapName ldapName : getReferences(memberAttributeId)) {
- Role role = findRole(ldapName);
- if (role == null) {
- throw new IllegalStateException("Role " + ldapName + " not found.");
- }
- directMembers.add(role);
- }
- return directMembers.toArray(new Role[directMembers.size()]);
- }
-
- /**
- * Whether a role with this name can be found from this context.
- *
- * @return The related {@link Role} or <code>null</code>.
- */
- protected Role findRole(LdapName ldapName) {
- Role role = getUserAdmin().getRole(ldapName.toString());
- if (role == null) {
- if (getUserAdmin().getExternalRoles() != null)
- role = getUserAdmin().getExternalRoles().getRole(ldapName.toString());
- }
- return role;
- }
-
-// @Override
-// public List<LdapName> getMemberNames() {
-// Attribute memberAttribute = getAttributes().get(memberAttributeId);
-// if (memberAttribute == null)
-// return new ArrayList<LdapName>();
-// try {
-// List<LdapName> roles = new ArrayList<LdapName>();
-// NamingEnumeration<?> values = memberAttribute.getAll();
-// while (values.hasMore()) {
-// LdapName dn = new LdapName(values.next().toString());
-// roles.add(dn);
-// }
-// return roles;
-// } catch (NamingException e) {
-// throw new IllegalStateException("Cannot get members", e);
-// }
-// }
-
- @Override
- public Role[] getRequiredMembers() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int getType() {
- return GROUP;
- }
-
- protected DirectoryUserAdmin getUserAdmin() {
- return (DirectoryUserAdmin) getDirectory();
- }
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.ldap.AbstractLdapDirectory;
-import org.argeo.util.directory.ldap.DefaultLdapEntry;
-
-/** Directory user implementation */
-class LdifUser extends DefaultLdapEntry implements DirectoryUser {
- LdifUser(AbstractLdapDirectory userAdmin, LdapName dn) {
- super(userAdmin, dn);
- }
-
- @Override
- public String getName() {
- return getDn().toString();
- }
-
- @Override
- public int getType() {
- return USER;
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.directory.ldap.AbstractLdapDirectory;
-import org.argeo.util.directory.ldap.AbstractLdapDirectoryDao;
-import org.argeo.util.directory.ldap.LdapEntry;
-import org.argeo.util.directory.ldap.LdapEntryWorkingCopy;
-import org.argeo.util.naming.LdapAttrs;
-
-/** Pseudo user directory to be used when logging in as OS user. */
-public class OsUserDirectory extends AbstractLdapDirectoryDao {
- private final String osUsername = System.getProperty("user.name");
- private final LdapName osUserDn;
- private final LdapEntry osUser;
-
- public OsUserDirectory(AbstractLdapDirectory directory) {
- super(directory);
- try {
- osUserDn = new LdapName(LdapAttrs.uid.name() + "=" + osUsername + "," + directory.getUserBaseRdn() + ","
- + directory.getBaseDn());
-// Attributes attributes = new BasicAttributes();
-// attributes.put(LdapAttrs.uid.name(), osUsername);
- osUser = newUser(osUserDn);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot create system user", e);
- }
- }
-
- @Override
- public List<LdapName> getDirectGroups(LdapName dn) {
- return new ArrayList<>();
- }
-
- @Override
- public boolean entryExists(LdapName dn) {
- return osUserDn.equals(dn);
- }
-
- @Override
- public boolean checkConnection() {
- return true;
- }
-
- @Override
- public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
- if (osUserDn.equals(key))
- return osUser;
- else
- throw new NameNotFoundException("Not an OS role");
- }
-
- @Override
- public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
- List<LdapEntry> res = new ArrayList<>();
-// if (f == null || f.match(osUser.getProperties()))
- res.add(osUser);
- return res;
- }
-
- @Override
- public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
- return null;
- }
-
- @Override
- public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
- return new ArrayList<>();
- }
-
- public void prepare(LdapEntryWorkingCopy wc) {
-
- }
-
- public void commit(LdapEntryWorkingCopy wc) {
-
- }
-
- public void rollback(LdapEntryWorkingCopy wc) {
-
- }
-
- @Override
- public void init() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public void destroy() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public Attributes doGetAttributes(LdapName name) {
- try {
- return doGetEntry(name).getAttributes();
- } catch (NameNotFoundException e) {
- throw new IllegalStateException(name + " doe not exist in " + getDirectory().getBaseDn(), e);
- }
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.NoSuchAlgorithmException;
-import java.security.URIParameter;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-/** Log in based on JDK-provided OS integration. */
-public class OsUserUtils {
- private final static String LOGIN_CONTEXT_USER_NIX = "USER_NIX";
- private final static String LOGIN_CONTEXT_USER_NT = "USER_NT";
-
- public static String getOsUsername() {
- return System.getProperty("user.name");
- }
-
- public static LoginContext loginAsSystemUser(Subject subject) {
- try {
- URL jaasConfigurationUrl = OsUserUtils.class.getClassLoader()
- .getResource("org/argeo/osgi/useradmin/jaas-os.cfg");
- URIParameter uriParameter = new URIParameter(jaasConfigurationUrl.toURI());
- Configuration jaasConfiguration = Configuration.getInstance("JavaLoginConfig", uriParameter);
- LoginContext lc = new LoginContext(isWindows() ? LOGIN_CONTEXT_USER_NT : LOGIN_CONTEXT_USER_NIX, subject,
- null, jaasConfiguration);
- lc.login();
- return lc;
- } catch (URISyntaxException | NoSuchAlgorithmException | LoginException e) {
- throw new RuntimeException("Cannot login as system user", e);
- }
- }
-
- public static void main(String args[]) {
- Subject subject = new Subject();
- LoginContext loginContext = loginAsSystemUser(subject);
- System.out.println(subject);
- try {
- loginContext.logout();
- } catch (LoginException e) {
- // silent
- }
- }
-
- private static boolean isWindows() {
- return System.getProperty("os.name").startsWith("Windows");
- }
-
- private OsUserUtils() {
- }
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import static org.argeo.util.naming.LdapAttrs.description;
-import static org.argeo.util.naming.LdapAttrs.owner;
-
-import java.security.Principal;
-import java.time.Instant;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.security.auth.Subject;
-
-import org.argeo.util.naming.NamingUtils;
-import org.osgi.service.useradmin.Group;
-
-/**
- * Canonically implements the Argeo token conventions.
- */
-public class TokenUtils {
- public static Set<String> tokensUsed(Subject subject, String tokensBaseDn) {
- Set<String> res = new HashSet<>();
- for (Principal principal : subject.getPrincipals()) {
- String name = principal.getName();
- if (name.endsWith(tokensBaseDn)) {
- try {
- LdapName ldapName = new LdapName(name);
- String token = ldapName.getRdn(ldapName.size()).getValue().toString();
- res.add(token);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Invalid principal " + principal, e);
- }
- }
- }
- return res;
- }
-
- /** The user related to this token group */
- public static String userDn(Group tokenGroup) {
- return (String) tokenGroup.getProperties().get(owner.name());
- }
-
- public static boolean isExpired(Group tokenGroup) {
- return isExpired(tokenGroup, Instant.now());
-
- }
-
- public static boolean isExpired(Group tokenGroup, Instant instant) {
- String expiryDateStr = (String) tokenGroup.getProperties().get(description.name());
- if (expiryDateStr != null) {
- Instant expiryDate = NamingUtils.ldapDateToInstant(expiryDateStr);
- if (expiryDate.isBefore(instant)) {
- return true;
- }
- }
- return false;
- }
-
-// private final String token;
-//
-// public TokenUtils(String token) {
-// this.token = token;
-// }
-//
-// public String getToken() {
-// return token;
-// }
-//
-// @Override
-// public int hashCode() {
-// return token.hashCode();
-// }
-//
-// @Override
-// public boolean equals(Object obj) {
-// if ((obj instanceof TokenUtils) && ((TokenUtils) obj).token.equals(token))
-// return true;
-// return false;
-// }
-//
-// @Override
-// public String toString() {
-// return "Token #" + hashCode();
-// }
-
-}
+++ /dev/null
-package org.argeo.osgi.useradmin;
-
-import org.argeo.util.directory.Directory;
-import org.argeo.util.directory.HierarchyUnit;
-import org.osgi.service.useradmin.Role;
-
-/** Information about a user directory. */
-public interface UserDirectory extends Directory {
-
- HierarchyUnit getHierarchyUnit(Role role);
-
- Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep);
-
- String getRolePath(Role role);
-
- String getRoleSimpleName(Role role);
-
- Role getRoleByPath(String path);
-}
+++ /dev/null
-USER_NIX {
- com.sun.security.auth.module.UnixLoginModule requisite;
-};
-
-USER_NT {
- com.sun.security.auth.module.NTLoginModule requisite;
-};
-
+++ /dev/null
-/** LDAP and LDIF based OSGi useradmin implementation. */
-package org.argeo.osgi.useradmin;
\ No newline at end of file
+++ /dev/null
-package org.argeo.osgi.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.resource.Namespace;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-/** Simplify filtering resources. */
-public class FilterRequirement implements Requirement {
- private String namespace;
- private String filter;
-
- public FilterRequirement(String namespace, String filter) {
- this.namespace = namespace;
- this.filter = filter;
- }
-
- @Override
- public Resource getResource() {
- return null;
- }
-
- @Override
- public String getNamespace() {
- return namespace;
- }
-
- @Override
- public Map<String, String> getDirectives() {
- Map<String, String> directives = new HashMap<>();
- directives.put(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
- return directives;
- }
-
- @Override
- public Map<String, Object> getAttributes() {
- return new HashMap<>();
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.util;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Function;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-
-public class OnServiceRegistration<R> implements Future<R> {
- private BundleContext ownBundleContext = FrameworkUtil.getBundle(OnServiceRegistration.class).getBundleContext();
-
- private ServiceTracker<?, ?> st;
-
- private R result;
- private boolean cancelled = false;
- private Throwable exception;
-
- public <T> OnServiceRegistration(Class<T> clss, Function<T, R> function) {
- this(null, clss, function);
- }
-
- public <T> OnServiceRegistration(BundleContext bundleContext, Class<T> clss, Function<T, R> function) {
- st = new ServiceTracker<T, T>(bundleContext != null ? bundleContext : ownBundleContext, clss, null) {
-
- @Override
- public T addingService(ServiceReference<T> reference) {
- T service = super.addingService(reference);
- try {
- if (result != null)// we only want the first one
- return service;
- result = function.apply(service);
- return service;
- } catch (Exception e) {
- exception = e;
- return service;
- } finally {
- close();
- }
- }
- };
- st.open(bundleContext == null);
- }
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- if (result != null || exception != null || cancelled)
- return false;
- st.close();
- cancelled = true;
- return true;
- }
-
- @Override
- public boolean isCancelled() {
- return cancelled;
- }
-
- @Override
- public boolean isDone() {
- return result != null || cancelled;
- }
-
- @Override
- public R get() throws InterruptedException, ExecutionException {
- st.waitForService(0);
- return tryGetResult();
- }
-
- @Override
- public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
- st.waitForService(TimeUnit.MILLISECONDS.convert(timeout, unit));
- if (result == null)
- throw new TimeoutException("No result after " + timeout + " " + unit);
- return tryGetResult();
- }
-
- protected R tryGetResult() throws ExecutionException, CancellationException {
- if (cancelled)
- throw new CancellationException();
- if (exception != null)
- throw new ExecutionException(exception);
- if (result == null)// this should not happen
- try {
- throw new IllegalStateException("No result available");
- } catch (Exception e) {
- exception = e;
- throw new ExecutionException(e);
- }
- return result;
- }
-
-}
+++ /dev/null
-package org.argeo.osgi.util;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ForkJoinPool;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-public class OsgiRegister {
- private final BundleContext bundleContext;
- private Executor executor;
-
- private CompletableFuture<Void> shutdownStarting = new CompletableFuture<Void>();
-
- public OsgiRegister(BundleContext bundleContext) {
- this.bundleContext = bundleContext;
- // TODO experiment with dedicated executors
- this.executor = ForkJoinPool.commonPool();
- }
-
- public <T> void set(T obj, Class<T> clss, Map<String, Object> attributes, Class<?>... classes) {
- CompletableFuture<ServiceRegistration<?>> srf = new CompletableFuture<ServiceRegistration<?>>();
- CompletableFuture<T> postRegistration = CompletableFuture.supplyAsync(() -> {
- List<String> lst = new ArrayList<>();
- lst.add(clss.getName());
- for (Class<?> c : classes) {
- lst.add(c.getName());
- }
- ServiceRegistration<?> sr = bundleContext.registerService(lst.toArray(new String[lst.size()]), obj,
- new Hashtable<String, Object>(attributes));
- srf.complete(sr);
- return obj;
- }, executor);
-// Singleton<T> singleton = new Singleton<T>(clss, postRegistration);
-
-// shutdownStarting. //
-// thenCompose(singleton::prepareUnregistration). //
-// thenRunAsync(() -> {
-// try {
-// srf.get().unregister();
-// } catch (InterruptedException | ExecutionException e) {
-// e.printStackTrace();
-// }
-// }, executor);
-// return singleton;
- }
-
- public void shutdown() {
- shutdownStarting.complete(null);
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.StringTokenizer;
-
-/** A name that can be expressed with various conventions. */
-public class CompositeString {
- public final static Character UNDERSCORE = Character.valueOf('_');
- public final static Character SPACE = Character.valueOf(' ');
- public final static Character DASH = Character.valueOf('-');
-
- private final String[] parts;
-
- // optimisation
- private final int hashCode;
-
- public CompositeString(String str) {
- Objects.requireNonNull(str, "String cannot be null");
- if ("".equals(str.trim()))
- throw new IllegalArgumentException("String cannot be empty");
- if (!str.equals(str.trim()))
- throw new IllegalArgumentException("String must be trimmed");
- this.parts = toParts(str);
- hashCode = hashCode(this.parts);
- }
-
- public String toString(char separator, boolean upperCase) {
- StringBuilder sb = null;
- for (String part : parts) {
- if (sb == null) {
- sb = new StringBuilder();
- } else {
- sb.append(separator);
- }
- sb.append(upperCase ? part.toUpperCase() : part);
- }
- return sb.toString();
- }
-
- public String toStringCaml(boolean firstCharUpperCase) {
- StringBuilder sb = null;
- for (String part : parts) {
- if (sb == null) {// first
- sb = new StringBuilder();
- sb.append(firstCharUpperCase ? Character.toUpperCase(part.charAt(0)) : part.charAt(0));
- } else {
- sb.append(Character.toUpperCase(part.charAt(0)));
- }
-
- if (part.length() > 1)
- sb.append(part.substring(1));
- }
- return sb.toString();
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof CompositeString))
- return false;
-
- CompositeString other = (CompositeString) obj;
- return Arrays.equals(parts, other.parts);
- }
-
- @Override
- public String toString() {
- return toString(DASH, false);
- }
-
- public static String[] toParts(String str) {
- Character separator = null;
- if (str.indexOf(UNDERSCORE) >= 0) {
- checkNo(str, SPACE);
- checkNo(str, DASH);
- separator = UNDERSCORE;
- } else if (str.indexOf(DASH) >= 0) {
- checkNo(str, SPACE);
- checkNo(str, UNDERSCORE);
- separator = DASH;
- } else if (str.indexOf(SPACE) >= 0) {
- checkNo(str, DASH);
- checkNo(str, UNDERSCORE);
- separator = SPACE;
- }
-
- List<String> res = new ArrayList<>();
- if (separator != null) {
- StringTokenizer st = new StringTokenizer(str, separator.toString());
- while (st.hasMoreTokens()) {
- res.add(st.nextToken().toLowerCase());
- }
- } else {
- // single
- String strLowerCase = str.toLowerCase();
- if (str.toUpperCase().equals(str) || strLowerCase.equals(str))
- return new String[] { strLowerCase };
-
- // CAML
- StringBuilder current = null;
- for (char c : str.toCharArray()) {
- if (Character.isUpperCase(c)) {
- if (current != null)
- res.add(current.toString());
- current = new StringBuilder();
- }
- if (current == null)// first char is lower case
- current = new StringBuilder();
- current.append(Character.toLowerCase(c));
- }
- res.add(current.toString());
- }
- return res.toArray(new String[res.size()]);
- }
-
- private static void checkNo(String str, Character c) {
- if (str.indexOf(c) >= 0) {
- throw new IllegalArgumentException("Only one kind of sperator is allowed");
- }
- }
-
- private static int hashCode(String[] parts) {
- int hashCode = 0;
- for (String part : parts) {
- hashCode = hashCode + part.hashCode();
- }
- return hashCode;
- }
-
- static boolean smokeTests() {
- CompositeString plainName = new CompositeString("NAME");
- assert "name".equals(plainName.toString());
- assert "NAME".equals(plainName.toString(UNDERSCORE, true));
- assert "name".equals(plainName.toString(UNDERSCORE, false));
- assert "name".equals(plainName.toStringCaml(false));
- assert "Name".equals(plainName.toStringCaml(true));
-
- CompositeString camlName = new CompositeString("myComplexName");
-
- assert new CompositeString("my-complex-name").equals(camlName);
- assert new CompositeString("MY_COMPLEX_NAME").equals(camlName);
- assert new CompositeString("My complex Name").equals(camlName);
- assert new CompositeString("MyComplexName").equals(camlName);
-
- assert "my-complex-name".equals(camlName.toString());
- assert "MY_COMPLEX_NAME".equals(camlName.toString(UNDERSCORE, true));
- assert "my_complex_name".equals(camlName.toString(UNDERSCORE, false));
- assert "myComplexName".equals(camlName.toStringCaml(false));
- assert "MyComplexName".equals(camlName.toStringCaml(true));
-
- return CompositeString.class.desiredAssertionStatus();
- }
-
- public static void main(String[] args) {
- System.out.println(smokeTests());
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Parses a CSV file interpreting the first line as a header. The
- * {@link #parse(InputStream)} method and the setters are synchronized so that
- * the object cannot be modified when parsing.
- */
-public abstract class CsvParser {
- private char separator = ',';
- private char quote = '\"';
-
- private Boolean noHeader = false;
- private Boolean strictLineAsLongAsHeader = true;
-
- /**
- * Actually process a parsed line. If
- * {@link #setStrictLineAsLongAsHeader(Boolean)} is true (default) the header
- * and the tokens are guaranteed to have the same size.
- *
- * @param lineNumber the current line number, starts at 1 (the header, if header
- * processing is enabled, the first line otherwise)
- * @param header the read-only header or null if
- * {@link #setNoHeader(Boolean)} is true (default is false)
- * @param tokens the parsed tokens
- */
- protected abstract void processLine(Integer lineNumber, List<String> header, List<String> tokens);
-
- /**
- * Parses the CSV file (stream is closed at the end)
- *
- * @param in the stream to parse
- *
- * @deprecated Use {@link #parse(InputStream, Charset)} instead.
- */
- @Deprecated
- public synchronized void parse(InputStream in) {
- parse(in, (Charset) null);
- }
-
- /**
- * Parses the CSV file (stream is closed at the end)
- *
- * @param in the stream to parse
- * @param encoding the encoding to use.
- *
- * @deprecated Use {@link #parse(InputStream, Charset)} instead.
- */
- @Deprecated
- public synchronized void parse(InputStream in, String encoding) {
- Reader reader;
- if (encoding == null)
- reader = new InputStreamReader(in);
- else
- try {
- reader = new InputStreamReader(in, encoding);
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- parse(reader);
- }
-
- /**
- * Parses the CSV file (stream is closed at the end)
- *
- * @param in the stream to parse
- * @param charset the charset to use
- */
- public synchronized void parse(InputStream in, Charset charset) {
- Reader reader;
- if (charset == null)
- reader = new InputStreamReader(in);
- else
- reader = new InputStreamReader(in, charset);
- parse(reader);
- }
-
- /**
- * Parses the CSV file (stream is closed at the end)
- *
- * @param reader the reader to use (it will be buffered)
- */
- public synchronized void parse(Reader reader) {
- Integer lineCount = 0;
- try (BufferedReader bufferedReader = new BufferedReader(reader)) {
- List<String> header = null;
- if (!noHeader) {
- String headerStr = bufferedReader.readLine();
- if (headerStr == null)// empty file
- return;
- lineCount++;
- header = new ArrayList<String>();
- StringBuffer currStr = new StringBuffer("");
- Boolean wasInquote = false;
- while (parseLine(headerStr, header, currStr, wasInquote)) {
- headerStr = bufferedReader.readLine();
- if (headerStr == null)
- break;
- wasInquote = true;
- }
- header = Collections.unmodifiableList(header);
- }
-
- String line = null;
- lines: while ((line = bufferedReader.readLine()) != null) {
- line = preProcessLine(line);
- if (line == null) {
- // skip line
- continue lines;
- }
- lineCount++;
- List<String> tokens = new ArrayList<String>();
- StringBuffer currStr = new StringBuffer("");
- Boolean wasInquote = false;
- sublines: while (parseLine(line, tokens, currStr, wasInquote)) {
- line = bufferedReader.readLine();
- if (line == null)
- break sublines;
- wasInquote = true;
- }
- if (!noHeader && strictLineAsLongAsHeader) {
- int headerSize = header.size();
- int tokenSize = tokens.size();
- if (tokenSize == 1 && line.trim().equals(""))
- continue lines;// empty line
- if (headerSize != tokenSize) {
- throw new IllegalStateException("Token size " + tokenSize + " is different from header size "
- + headerSize + " at line " + lineCount + ", line: " + line + ", header: " + header
- + ", tokens: " + tokens);
- }
- }
- processLine(lineCount, header, tokens);
- }
- } catch (IOException e) {
- throw new RuntimeException("Cannot parse CSV file (line: " + lineCount + ")", e);
- }
- }
-
- /**
- * Called before each (logical) line is processed, giving a change to modify it
- * (typically for cleaning dirty files). To be overridden, return the line
- * unchanged by default. Skip the line if 'null' is returned.
- */
- protected String preProcessLine(String line) {
- return line;
- }
-
- /**
- * Parses a line character by character for performance purpose
- *
- * @return whether to continue parsing this line
- */
- protected Boolean parseLine(String str, List<String> tokens, StringBuffer currStr, Boolean wasInquote) {
- if (wasInquote)
- currStr.append('\n');
-
- char[] arr = str.toCharArray();
- boolean inQuote = wasInquote;
- for (int i = 0; i < arr.length; i++) {
- char c = arr[i];
- if (c == separator) {
- if (!inQuote) {
- tokens.add(currStr.toString());
-// currStr.delete(0, currStr.length());
- currStr.setLength(0);
- currStr.trimToSize();
- } else {
- // we don't remove separator that are in a quoted substring
- // System.out
- // .println("IN QUOTE, got a separator: [" + c + "]");
- currStr.append(c);
- }
- } else if (c == quote) {
- if (inQuote && (i + 1) < arr.length && arr[i + 1] == quote) {
- // case of double quote
- currStr.append(quote);
- i++;
- } else {// standard
- inQuote = inQuote ? false : true;
- }
- } else {
- currStr.append(c);
- }
- }
-
- if (!inQuote) {
- tokens.add(currStr.toString());
- // System.out.println("# TOKEN: " + currStr);
- }
- // if (inQuote)
- // throw new ArgeoException("Missing quote at the end of the line "
- // + str + " (parsed: " + tokens + ")");
- if (inQuote)
- return true;
- else
- return false;
- // return tokens;
- }
-
- public char getSeparator() {
- return separator;
- }
-
- public synchronized void setSeparator(char separator) {
- this.separator = separator;
- }
-
- public char getQuote() {
- return quote;
- }
-
- public synchronized void setQuote(char quote) {
- this.quote = quote;
- }
-
- public Boolean getNoHeader() {
- return noHeader;
- }
-
- public synchronized void setNoHeader(Boolean noHeader) {
- this.noHeader = noHeader;
- }
-
- public Boolean getStrictLineAsLongAsHeader() {
- return strictLineAsLongAsHeader;
- }
-
- public synchronized void setStrictLineAsLongAsHeader(Boolean strictLineAsLongAsHeader) {
- this.strictLineAsLongAsHeader = strictLineAsLongAsHeader;
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * CSV parser allowing to process lines as maps whose keys are the header
- * fields.
- */
-public abstract class CsvParserWithLinesAsMap extends CsvParser {
-
- /**
- * Actually processes a line.
- *
- * @param lineNumber the current line number, starts at 1 (the header, if header
- * processing is enabled, the first lien otherwise)
- * @param line the parsed tokens as a map whose keys are the header fields
- */
- protected abstract void processLine(Integer lineNumber, Map<String, String> line);
-
- protected final void processLine(Integer lineNumber, List<String> header, List<String> tokens) {
- if (header == null)
- throw new IllegalArgumentException("Only CSV with header is supported");
- Map<String, String> line = new HashMap<String, String>();
- for (int i = 0; i < header.size(); i++) {
- String key = header.get(i);
- String value = null;
- if (i < tokens.size())
- value = tokens.get(i);
- line.put(key, value);
- }
- processLine(lineNumber, line);
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.util.Iterator;
-import java.util.List;
-
-/** Write in CSV format. */
-public class CsvWriter {
- private final Writer out;
-
- private char separator = ',';
- private char quote = '\"';
-
- /**
- * Creates a CSV writer.
- *
- * @param out the stream to write to. Caller is responsible for closing it.
- *
- * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead.
- *
- */
- @Deprecated
- public CsvWriter(OutputStream out) {
- this.out = new OutputStreamWriter(out);
- }
-
- /**
- * Creates a CSV writer.
- *
- * @param out the stream to write to. Caller is responsible for closing it.
- * @param encoding the encoding to use.
- *
- * @deprecated Use {@link #CsvWriter(OutputStream, Charset)} instead.
- */
- @Deprecated
- public CsvWriter(OutputStream out, String encoding) {
- try {
- this.out = new OutputStreamWriter(out, encoding);
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- /**
- * Creates a CSV writer.
- *
- * @param out the stream to write to. Caller is responsible for closing it.
- * @param charset the charset to use
- */
- public CsvWriter(OutputStream out, Charset charset) {
- this.out = new OutputStreamWriter(out, charset);
- }
-
- /**
- * Creates a CSV writer.
- *
- * @param out the stream to write to. Caller is responsible for closing it.
- */
- public CsvWriter(Writer writer) {
- this.out = writer;
- }
-
- /**
- * Write a CSV line. Also used to write a header if needed (this is transparent
- * for the CSV writer): simply call it first, before writing the lines.
- */
- public void writeLine(List<?> tokens) {
- try {
- Iterator<?> it = tokens.iterator();
- while (it.hasNext()) {
- Object obj = it.next();
- writeToken(obj != null ? obj.toString() : null);
- if (it.hasNext())
- out.write(separator);
- }
- out.write('\n');
- out.flush();
- } catch (IOException e) {
- throw new RuntimeException("Could not write " + tokens, e);
- }
- }
-
- /**
- * Write a CSV line. Also used to write a header if needed (this is transparent
- * for the CSV writer): simply call it first, before writing the lines.
- */
- public void writeLine(Object[] tokens) {
- try {
- for (int i = 0; i < tokens.length; i++) {
- if (tokens[i] == null) {
- writeToken(null);
- } else {
- writeToken(tokens[i].toString());
- }
- if (i != (tokens.length - 1))
- out.write(separator);
- }
- out.write('\n');
- out.flush();
- } catch (IOException e) {
- throw new RuntimeException("Could not write " + tokens, e);
- }
- }
-
- protected void writeToken(String token) throws IOException {
- if (token == null) {
- // TODO configure how to deal with null
- out.write("");
- return;
- }
- // +2 for possible quotes, another +2 assuming there would be an already
- // quoted string where quotes needs to be duplicated
- // another +2 for safety
- // we don't want to increase buffer size while writing
- StringBuffer buf = new StringBuffer(token.length() + 6);
- char[] arr = token.toCharArray();
- boolean shouldQuote = false;
- for (char c : arr) {
- if (!shouldQuote) {
- if (c == separator)
- shouldQuote = true;
- if (c == '\n')
- shouldQuote = true;
- }
-
- if (c == quote) {
- shouldQuote = true;
- // duplicate quote
- buf.append(quote);
- }
-
- // generic case
- buf.append(c);
- }
-
- if (shouldQuote == true)
- out.write(quote);
- out.write(buf.toString());
- if (shouldQuote == true)
- out.write(quote);
- }
-
- public void setSeparator(char separator) {
- this.separator = separator;
- }
-
- public void setQuote(char quote) {
- this.quote = quote;
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CompletionException;
-
-import javax.security.auth.Subject;
-
-/**
- * Prepare evolution of Java APIs introduced in JDK 18, as these static methods
- * will be added to {@link Subject}.
- */
-@SuppressWarnings("removal")
-public class CurrentSubject {
-
- private final static boolean useThreadLocal = Boolean
- .parseBoolean(System.getProperty("jdk.security.auth.subject.useTL"));
-
- private final static InheritableThreadLocal<Subject> current = new InheritableThreadLocal<>();
-
- public static Subject current() {
- if (useThreadLocal) {
- return current.get();
- } else {// legacy
- Subject subject = Subject.getSubject(AccessController.getContext());
- return subject;
- }
- }
-
- public static <T> T callAs(Subject subject, Callable<T> action) {
- if (useThreadLocal) {
- Subject previous = current();
- current.set(subject);
- try {
- return action.call();
- } catch (Exception e) {
- throw new CompletionException("Failed to execute action for " + subject, e);
- } finally {
- current.set(previous);
- }
- } else {// legacy
- try {
- return Subject.doAs(subject, new PrivilegedExceptionAction<T>() {
-
- @Override
- public T run() throws Exception {
- return action.call();
- }
-
- });
- } catch (PrivilegedActionException e) {
- throw new CompletionException("Failed to execute action for " + subject, e.getCause());
- } catch (Exception e) {
- throw new CompletionException("Failed to execute action for " + subject, e);
- }
- }
- }
-
- /** Singleton. */
- private CurrentSubject() {
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-
-/**
- * Access the keys of a {@link String}-keyed {@link Dictionary} (common throughout
- * the OSGi APIs) as an {@link Iterable} so that they are easily usable in
- * for-each loops.
- */
-class DictionaryKeys implements Iterable<String> {
- private final Dictionary<String, ?> dictionary;
-
- public DictionaryKeys(Dictionary<String, ?> dictionary) {
- this.dictionary = dictionary;
- }
-
- @Override
- public Iterator<String> iterator() {
- return new KeyIterator(dictionary.keys());
- }
-
- private static class KeyIterator implements Iterator<String> {
- private final Enumeration<String> keys;
-
- KeyIterator(Enumeration<String> keys) {
- this.keys = keys;
- }
-
- @Override
- public boolean hasNext() {
- return keys.hasMoreElements();
- }
-
- @Override
- public String next() {
- return keys.nextElement();
- }
-
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileChannel.MapMode;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-/** Utilities around cryptographic digests */
-public class DigestUtils {
- public final static String MD5 = "MD5";
- public final static String SHA1 = "SHA1";
- public final static String SHA256 = "SHA-256";
- public final static String SHA512 = "SHA-512";
-
- private static Boolean debug = false;
- // TODO: make it configurable
- private final static Integer byteBufferCapacity = 100 * 1024;// 100 KB
-
- public static byte[] sha1(byte[]... bytes) {
- try {
- MessageDigest digest = MessageDigest.getInstance(SHA1);
- for (byte[] arr : bytes)
- digest.update(arr);
- byte[] checksum = digest.digest();
- return checksum;
- } catch (NoSuchAlgorithmException e) {
- throw new UnsupportedOperationException("SHA1 is not avalaible", e);
- }
- }
-
- public static byte[] digestAsBytes(String algorithm, byte[]... bytes) {
- try {
- MessageDigest digest = MessageDigest.getInstance(algorithm);
- for (byte[] arr : bytes)
- digest.update(arr);
- byte[] checksum = digest.digest();
- return checksum;
- } catch (NoSuchAlgorithmException e) {
- throw new UnsupportedOperationException("Cannot digest with algorithm " + algorithm, e);
- }
- }
-
- public static String digest(String algorithm, byte[]... bytes) {
- return toHexString(digestAsBytes(algorithm, bytes));
- }
-
- public static String digest(String algorithm, InputStream in) {
- try {
- MessageDigest digest = MessageDigest.getInstance(algorithm);
- // ReadableByteChannel channel = Channels.newChannel(in);
- // ByteBuffer bb = ByteBuffer.allocateDirect(byteBufferCapacity);
- // while (channel.read(bb) > 0)
- // digest.update(bb);
- byte[] buffer = new byte[byteBufferCapacity];
- int read = 0;
- while ((read = in.read(buffer)) > 0) {
- digest.update(buffer, 0, read);
- }
-
- byte[] checksum = digest.digest();
- String res = toHexString(checksum);
- return res;
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- StreamUtils.closeQuietly(in);
- }
- }
-
- public static String digest(String algorithm, File file) {
- FileInputStream fis = null;
- FileChannel fc = null;
- try {
- fis = new FileInputStream(file);
- fc = fis.getChannel();
-
- // Get the file's size and then map it into memory
- int sz = (int) fc.size();
- ByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, sz);
- return digest(algorithm, bb);
- } catch (IOException e) {
- throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
- } finally {
- StreamUtils.closeQuietly(fis);
- if (fc.isOpen())
- try {
- fc.close();
- } catch (IOException e) {
- // silent
- }
- }
- }
-
- protected static String digest(String algorithm, ByteBuffer bb) {
- long begin = System.currentTimeMillis();
- try {
- MessageDigest digest = MessageDigest.getInstance(algorithm);
- digest.update(bb);
- byte[] checksum = digest.digest();
- String res = toHexString(checksum);
- long end = System.currentTimeMillis();
- if (debug)
- System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
- return res;
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalArgumentException("Cannot digest with algorithm " + algorithm, e);
- }
- }
-
- public static String sha1hex(Path path) {
- return digest(SHA1, path, byteBufferCapacity);
- }
-
- public static String digest(String algorithm, Path path, long bufferSize) {
- byte[] digest = digestAsBytes(algorithm, path, bufferSize);
- return toHexString(digest);
- }
-
- public static byte[] digestAsBytes(String algorithm, Path file, long bufferSize) {
- long begin = System.currentTimeMillis();
- try {
- MessageDigest md = MessageDigest.getInstance(algorithm);
- FileChannel fc = FileChannel.open(file);
- long fileSize = Files.size(file);
- if (fileSize <= bufferSize) {
- ByteBuffer bb = fc.map(MapMode.READ_ONLY, 0, fileSize);
- md.update(bb);
- } else {
- long lastCycle = (fileSize / bufferSize) - 1;
- long position = 0;
- for (int i = 0; i <= lastCycle; i++) {
- ByteBuffer bb;
- if (i != lastCycle) {
- bb = fc.map(MapMode.READ_ONLY, position, bufferSize);
- position = position + bufferSize;
- } else {
- bb = fc.map(MapMode.READ_ONLY, position, fileSize - position);
- position = fileSize;
- }
- md.update(bb);
- }
- }
- long end = System.currentTimeMillis();
- if (debug)
- System.out.println((end - begin) + " ms / " + ((end - begin) / 1000) + " s");
- return md.digest();
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalArgumentException("Cannot digest " + file + " with algorithm " + algorithm, e);
- } catch (IOException e) {
- throw new RuntimeException("Cannot digest " + file + " with algorithm " + algorithm, e);
- }
- }
-
- public static void main(String[] args) {
- File file;
- if (args.length > 0)
- file = new File(args[0]);
- else {
- System.err.println("Usage: <file> [<algorithm>]" + " (see http://java.sun.com/j2se/1.5.0/"
- + "docs/guide/security/CryptoSpec.html#AppA)");
- return;
- }
-
- if (args.length > 1) {
- String algorithm = args[1];
- System.out.println(digest(algorithm, file));
- } else {
- String algorithm = "MD5";
- System.out.println(algorithm + ": " + digest(algorithm, file));
- algorithm = "SHA";
- System.out.println(algorithm + ": " + digest(algorithm, file));
- System.out.println(algorithm + ": " + sha1hex(file.toPath()));
- algorithm = "SHA-256";
- System.out.println(algorithm + ": " + digest(algorithm, file));
- algorithm = "SHA-512";
- System.out.println(algorithm + ": " + digest(algorithm, file));
- }
- }
-
- final private static char[] hexArray = "0123456789abcdef".toCharArray();
-
- /** Converts a byte array to an hex String. */
- public static String toHexString(byte[] bytes) {
- char[] hexChars = new char[bytes.length * 2];
- for (int j = 0; j < bytes.length; j++) {
- int v = bytes[j] & 0xFF;
- hexChars[j * 2] = hexArray[v >>> 4];
- hexChars[j * 2 + 1] = hexArray[v & 0x0F];
- }
- return new String(hexChars);
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.nio.charset.Charset;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/** Hashes the hashes of the files in a directory. */
-public class DirH {
-
- private final static Charset charset = Charset.forName("UTF-16");
- private final static long bufferSize = 200 * 1024 * 1024;
- private final static String algorithm = "SHA";
-
- private final static byte EOL = (byte) '\n';
- private final static byte SPACE = (byte) ' ';
-
- private final int hashSize;
-
- private final byte[][] hashes;
- private final byte[][] fileNames;
- private final byte[] digest;
- private final byte[] dirName;
-
- /**
- * @param dirName can be null or empty
- */
- private DirH(byte[][] hashes, byte[][] fileNames, byte[] dirName) {
- if (hashes.length != fileNames.length)
- throw new IllegalArgumentException(hashes.length + " hashes and " + fileNames.length + " file names");
- this.hashes = hashes;
- this.fileNames = fileNames;
- this.dirName = dirName == null ? new byte[0] : dirName;
- if (hashes.length == 0) {// empty dir
- hashSize = 20;
- // FIXME what is the digest of an empty dir?
- digest = new byte[hashSize];
- Arrays.fill(digest, SPACE);
- return;
- }
- hashSize = hashes[0].length;
- for (int i = 0; i < hashes.length; i++) {
- if (hashes[i].length != hashSize)
- throw new IllegalArgumentException(
- "Hash size for " + new String(fileNames[i], charset) + " is " + hashes[i].length);
- }
-
- try {
- MessageDigest md = MessageDigest.getInstance(algorithm);
- for (int i = 0; i < hashes.length; i++) {
- md.update(this.hashes[i]);
- md.update(SPACE);
- md.update(this.fileNames[i]);
- md.update(EOL);
- }
- digest = md.digest();
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalArgumentException("Cannot digest", e);
- }
- }
-
- public void print(PrintStream out) {
- out.print(DigestUtils.toHexString(digest));
- if (dirName.length > 0) {
- out.print(' ');
- out.print(new String(dirName, charset));
- }
- out.print('\n');
- for (int i = 0; i < hashes.length; i++) {
- out.print(DigestUtils.toHexString(hashes[i]));
- out.print(' ');
- out.print(new String(fileNames[i], charset));
- out.print('\n');
- }
- }
-
- public static DirH digest(Path dir) {
- try (DirectoryStream<Path> files = Files.newDirectoryStream(dir)) {
- List<byte[]> hs = new ArrayList<byte[]>();
- List<String> fNames = new ArrayList<>();
- for (Path file : files) {
- if (!Files.isDirectory(file)) {
- byte[] digest = DigestUtils.digestAsBytes(algorithm, file, bufferSize);
- hs.add(digest);
- fNames.add(file.getFileName().toString());
- }
- }
-
- byte[][] fileNames = new byte[fNames.size()][];
- for (int i = 0; i < fNames.size(); i++) {
- fileNames[i] = fNames.get(i).getBytes(charset);
- }
- byte[][] hashes = hs.toArray(new byte[hs.size()][]);
- return new DirH(hashes, fileNames, dir.toString().getBytes(charset));
- } catch (IOException e) {
- throw new RuntimeException("Cannot digest " + dir, e);
- }
- }
-
- public static void main(String[] args) {
- try {
- DirH dirH = DirH.digest(Paths.get("/home/mbaudier/tmp/"));
- dirH.print(System.out);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Serialisable wrapper of a {@link Throwable}. typically to be written as XML
- * or JSON in a server error response.
- */
-public class ExceptionsChain {
- private List<SystemException> exceptions = new ArrayList<>();
-
- public ExceptionsChain() {
- }
-
- public ExceptionsChain(Throwable exception) {
- writeException(exception);
- }
-
- /** recursive */
- protected void writeException(Throwable exception) {
- SystemException systemException = new SystemException(exception);
- exceptions.add(systemException);
- Throwable cause = exception.getCause();
- if (cause != null)
- writeException(cause);
- }
-
- public List<SystemException> getExceptions() {
- return exceptions;
- }
-
- public void setExceptions(List<SystemException> exceptions) {
- this.exceptions = exceptions;
- }
-
- /** An exception in the chain. */
- public static class SystemException {
- private String type;
- private String message;
- private List<String> stackTrace;
-
- public SystemException() {
- }
-
- public SystemException(Throwable exception) {
- this.type = exception.getClass().getName();
- this.message = exception.getMessage();
- this.stackTrace = new ArrayList<>();
- StackTraceElement[] elems = exception.getStackTrace();
- for (int i = 0; i < elems.length; i++)
- stackTrace.add("at " + elems[i].toString());
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public List<String> getStackTrace() {
- return stackTrace;
- }
-
- public void setStackTrace(List<String> stackTrace) {
- this.stackTrace = stackTrace;
- }
-
- @Override
- public String toString() {
- return "System exception: " + type + ", " + message + ", " + stackTrace;
- }
-
- }
-
- @Override
- public String toString() {
- return exceptions.toString();
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.IOException;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-
-/** Utilities around the standard Java file abstractions. */
-public class FsUtils {
-
- /** Deletes this path, recursively if needed. */
- public static void copyDirectory(Path source, Path target) {
- if (!Files.exists(source) || !Files.isDirectory(source))
- throw new IllegalArgumentException(source + " is not a directory");
- if (Files.exists(target) && !Files.isDirectory(target))
- throw new IllegalArgumentException(target + " is not a directory");
- try {
- Files.createDirectories(target);
- Files.walkFileTree(source, new SimpleFileVisitor<Path>() {
-
- @Override
- public FileVisitResult preVisitDirectory(Path directory, BasicFileAttributes attrs) throws IOException {
- Path relativePath = source.relativize(directory);
- Path targetDirectory = target.resolve(relativePath);
- if (!Files.exists(targetDirectory))
- Files.createDirectory(targetDirectory);
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Path relativePath = source.relativize(file);
- Path targetFile = target.resolve(relativePath);
- Files.copy(file, targetFile);
- return FileVisitResult.CONTINUE;
- }
- });
- } catch (IOException e) {
- throw new RuntimeException("Cannot copy " + source + " to " + target, e);
- }
-
- }
-
- /**
- * Deletes this path, recursively if needed. Does nothing if the path does not
- * exist.
- */
- public static void delete(Path path) {
- try {
- if (!Files.exists(path))
- return;
- Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
- @Override
- public FileVisitResult postVisitDirectory(Path directory, IOException e) throws IOException {
- if (e != null)
- throw e;
- Files.delete(directory);
- return FileVisitResult.CONTINUE;
- }
-
- @Override
- public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
- Files.delete(file);
- return FileVisitResult.CONTINUE;
- }
- });
- } catch (IOException e) {
- throw new RuntimeException("Cannot delete " + path, e);
- }
- }
-
- /** Singleton. */
- private FsUtils() {
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
-import java.time.ZonedDateTime;
-import java.time.temporal.ChronoUnit;
-import java.time.temporal.Temporal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-
-/** Utilities around Java basic features. */
-public class LangUtils {
- /*
- * NON-API OSGi
- */
- /**
- * Returns an array with the names of the provided classes. Useful when
- * registering services with multiple interfaces in OSGi.
- */
- public static String[] names(Class<?>... clzz) {
- String[] res = new String[clzz.length];
- for (int i = 0; i < clzz.length; i++)
- res[i] = clzz[i].getName();
- return res;
- }
-
-// /*
-// * MAP
-// */
-// /**
-// * Creates a new {@link Map} with one key-value pair. Key should not be null,
-// * but if the value is null, it returns an empty {@link Map}.
-// *
-// * @deprecated Use {@link Collections#singletonMap(Object, Object)} instead.
-// */
-// @Deprecated
-// public static Map<String, Object> map(String key, Object value) {
-// assert key != null;
-// HashMap<String, Object> props = new HashMap<>();
-// if (value != null)
-// props.put(key, value);
-// return props;
-// }
-
- /*
- * DICTIONARY
- */
-
- /**
- * Creates a new {@link Dictionary} with one key-value pair. Key should not be
- * null, but if the value is null, it returns an empty {@link Dictionary}.
- */
- public static Dictionary<String, Object> dict(String key, Object value) {
- assert key != null;
- Hashtable<String, Object> props = new Hashtable<>();
- if (value != null)
- props.put(key, value);
- return props;
- }
-
- /** @deprecated Use {@link #dict(String, Object)} instead. */
- @Deprecated
- public static Dictionary<String, Object> dico(String key, Object value) {
- return dict(key, value);
- }
-
- /** Converts a {@link Dictionary} to a {@link Map} of strings. */
- public static Map<String, String> dictToStringMap(Dictionary<String, ?> properties) {
- if (properties == null) {
- return null;
- }
- Map<String, String> res = new HashMap<>(properties.size());
- Enumeration<String> keys = properties.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- res.put(key, properties.get(key).toString());
- }
- return res;
- }
-
- /** Converts a {@link Dictionary} to a {@link Map}. */
- public static Map<String, Object> dictToMap(Dictionary<String, ?> properties) {
- if (properties == null) {
- return null;
- }
- Map<String, Object> res = new HashMap<>(properties.size());
- Enumeration<String> keys = properties.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- res.put(key, properties.get(key));
- }
- return res;
- }
-
- /**
- * Get a string property from this map, expecting to find it, or
- * <code>null</code> if not found.
- */
- public static String get(Map<String, ?> map, String key) {
- Object res = map.get(key);
- if (res == null)
- return null;
- return res.toString();
- }
-
- /**
- * Get a string property from this map, expecting to find it.
- *
- * @throws IllegalArgumentException if the key was not found
- */
- public static String getNotNull(Map<String, ?> map, String key) {
- Object res = map.get(key);
- if (res == null)
- throw new IllegalArgumentException("Map " + map + " should contain key " + key);
- return res.toString();
- }
-
- /**
- * Wraps the keys of the provided {@link Dictionary} as an {@link Iterable}.
- */
- public static Iterable<String> keys(Dictionary<String, ?> props) {
- assert props != null;
- return new DictionaryKeys(props);
- }
-
- static String toJson(Dictionary<String, ?> props) {
- return toJson(props, false);
- }
-
- static String toJson(Dictionary<String, ?> props, boolean pretty) {
- StringBuilder sb = new StringBuilder();
- sb.append('{');
- if (pretty)
- sb.append('\n');
- Enumeration<String> keys = props.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- if (pretty)
- sb.append(' ');
- sb.append('\"').append(key).append('\"');
- if (pretty)
- sb.append(" : ");
- else
- sb.append(':');
- sb.append('\"').append(props.get(key)).append('\"');
- if (keys.hasMoreElements())
- sb.append(", ");
- if (pretty)
- sb.append('\n');
- }
- sb.append('}');
- return sb.toString();
- }
-
- static void storeAsProperties(Dictionary<String, Object> props, Path path) throws IOException {
- if (props == null)
- throw new IllegalArgumentException("Props cannot be null");
- Properties toStore = new Properties();
- for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
- String key = keys.nextElement();
- toStore.setProperty(key, props.get(key).toString());
- }
- try (OutputStream out = Files.newOutputStream(path)) {
- toStore.store(out, null);
- }
- }
-
- static void appendAsLdif(String dnBase, String dnKey, Dictionary<String, Object> props, Path path)
- throws IOException {
- if (props == null)
- throw new IllegalArgumentException("Props cannot be null");
- Object dnValue = props.get(dnKey);
- String dnStr = dnKey + '=' + dnValue + ',' + dnBase;
- LdapName dn;
- try {
- dn = new LdapName(dnStr);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Cannot interpret DN " + dnStr, e);
- }
- if (dnValue == null)
- throw new IllegalArgumentException("DN key " + dnKey + " must have a value");
- try (Writer writer = Files.newBufferedWriter(path, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
- writer.append("\ndn: ");
- writer.append(dn.toString());
- writer.append('\n');
- for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
- String key = keys.nextElement();
- Object value = props.get(key);
- writer.append(key);
- writer.append(": ");
- // FIXME deal with binary and multiple values
- writer.append(value.toString());
- writer.append('\n');
- }
- }
- }
-
- static Dictionary<String, Object> loadFromProperties(Path path) throws IOException {
- Properties toLoad = new Properties();
- try (InputStream in = Files.newInputStream(path)) {
- toLoad.load(in);
- }
- Dictionary<String, Object> res = new Hashtable<String, Object>();
- for (Object key : toLoad.keySet())
- res.put(key.toString(), toLoad.get(key));
- return res;
- }
-
- /*
- * COLLECTIONS
- */
- /**
- * Convert a comma-separated separated {@link String} or a {@link String} array
- * to a {@link List} of {@link String}, trimming them. Useful to quickly
- * interpret OSGi services properties.
- *
- * @return a {@link List} containing the trimmed {@link String}s, or an empty
- * {@link List} if the argument was <code>null</code>.
- */
- public static List<String> toStringList(Object value) {
- List<String> values = new ArrayList<>();
- if (value == null)
- return values;
- String[] arr;
- if (value instanceof String) {
- arr = ((String) value).split(",");
- } else if (value instanceof String[]) {
- arr = (String[]) value;
- } else {
- throw new IllegalArgumentException("Unsupported value type " + value.getClass());
- }
- for (String str : arr) {
- values.add(str.trim());
- }
- return values;
- }
-
- /** Size of an {@link Iterable}, optimised if it is a {@link Collection}. */
- public static int size(Iterable<?> iterable) {
- if (iterable instanceof Collection)
- return ((Collection<?>) iterable).size();
-
- int size = 0;
- for (Iterator<?> it = iterable.iterator(); it.hasNext(); size++)
- it.next();
- return size;
- }
-
- public static <T> T getAt(Iterable<T> iterable, int index) {
- if (iterable instanceof List) {
- List<T> lst = ((List<T>) iterable);
- if (index >= lst.size())
- throw new IllegalArgumentException("Index " + index + " is not available (size is " + lst.size() + ")");
- return lst.get(index);
- }
- int i = 0;
- for (Iterator<T> it = iterable.iterator(); it.hasNext(); i++) {
- if (i == index)
- return it.next();
- else
- it.next();
- }
- throw new IllegalArgumentException("Index " + index + " is not available (size is " + i + ")");
- }
-
- /*
- * EXCEPTIONS
- */
- /**
- * Chain the messages of all causes (one per line, <b>starts with a line
- * return</b>) without all the stack
- */
- public static String chainCausesMessages(Throwable t) {
- StringBuffer buf = new StringBuffer();
- chainCauseMessage(buf, t);
- return buf.toString();
- }
-
- /** Recursive chaining of messages */
- private static void chainCauseMessage(StringBuffer buf, Throwable t) {
- buf.append('\n').append(' ').append(t.getClass().getCanonicalName()).append(": ").append(t.getMessage());
- if (t.getCause() != null)
- chainCauseMessage(buf, t.getCause());
- }
-
- /*
- * TIME
- */
- /** Formats time elapsed since start. */
- public static String since(ZonedDateTime start) {
- ZonedDateTime now = ZonedDateTime.now();
- return duration(start, now);
- }
-
- /** Formats a duration. */
- public static String duration(Temporal start, Temporal end) {
- long count = ChronoUnit.DAYS.between(start, end);
- if (count != 0)
- return count > 1 ? count + " days" : count + " day";
- count = ChronoUnit.HOURS.between(start, end);
- if (count != 0)
- return count > 1 ? count + " hours" : count + " hours";
- count = ChronoUnit.MINUTES.between(start, end);
- if (count != 0)
- return count > 1 ? count + " minutes" : count + " minute";
- count = ChronoUnit.SECONDS.between(start, end);
- return count > 1 ? count + " seconds" : count + " second";
- }
-
- /** Singleton constructor. */
- private LangUtils() {
-
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.File;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/** When OS specific informations are needed. */
-public class OS {
- public final static OS LOCAL = new OS();
-
- private final String arch, name, version;
-
- /** The OS of the running JVM */
- protected OS() {
- arch = System.getProperty("os.arch");
- name = System.getProperty("os.name");
- version = System.getProperty("os.version");
- }
-
- public String getArch() {
- return arch;
- }
-
- public String getName() {
- return name;
- }
-
- public String getVersion() {
- return version;
- }
-
- public boolean isMSWindows() {
- // only MS Windows would use such an horrendous separator...
- return File.separatorChar == '\\';
- }
-
- public String[] getDefaultShellCommand() {
- if (!isMSWindows())
- return new String[] { "/bin/bash", "-l", "-i" };
- else
- return new String[] { "cmd.exe", "/C" };
- }
-
- public static long getJvmPid() {
- return ProcessHandle.current().pid();
-// String pidAndHost = ManagementFactory.getRuntimeMXBean().getName();
-// return Integer.parseInt(pidAndHost.substring(0, pidAndHost.indexOf('@')));
- }
-
- /**
- * Get the runtime directory. It will be the environment variable
- * XDG_RUNTIME_DIR if it is set, or ~/.cache/argeo if not.
- */
- public static Path getRunDir() {
- Path runDir;
- String xdgRunDir = System.getenv("XDG_RUNTIME_DIR");
- if (xdgRunDir != null) {
- // TODO support multiple names
- runDir = Paths.get(xdgRunDir);
- } else {
- runDir = Paths.get(System.getProperty("user.home"), ".cache/argeo");
- }
- return runDir;
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.security.GeneralSecurityException;
-import java.security.InvalidKeyException;
-import java.security.Key;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.CipherOutputStream;
-import javax.crypto.SecretKey;
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.PBEKeySpec;
-import javax.crypto.spec.SecretKeySpec;
-
-public class PasswordEncryption {
- public final static Integer DEFAULT_ITERATION_COUNT = 1024;
- /** Stronger with 256, but causes problem with Oracle JVM */
- public final static Integer DEFAULT_SECRETE_KEY_LENGTH = 256;
- public final static Integer DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED = 128;
- public final static String DEFAULT_SECRETE_KEY_FACTORY = "PBKDF2WithHmacSHA1";
- public final static String DEFAULT_SECRETE_KEY_ENCRYPTION = "AES";
- public final static String DEFAULT_CIPHER_NAME = "AES/CBC/PKCS5Padding";
-// public final static String DEFAULT_CHARSET = "UTF-8";
- public final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
-
- private Integer iterationCount = DEFAULT_ITERATION_COUNT;
- private Integer secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH;
- private String secreteKeyFactoryName = DEFAULT_SECRETE_KEY_FACTORY;
- private String secreteKeyEncryption = DEFAULT_SECRETE_KEY_ENCRYPTION;
- private String cipherName = DEFAULT_CIPHER_NAME;
-
- private static byte[] DEFAULT_SALT_8 = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
- (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
- private static byte[] DEFAULT_IV_16 = { (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
- (byte) 0x35, (byte) 0xE3, (byte) 0x03, (byte) 0xA9, (byte) 0x9B, (byte) 0xC8, (byte) 0x32, (byte) 0x56,
- (byte) 0x35, (byte) 0xE3, (byte) 0x03 };
-
- private Key key;
- private Cipher ecipher;
- private Cipher dcipher;
-
- private String securityProviderName = null;
-
- /**
- * This is up to the caller to clear the passed array. Neither copy of nor
- * reference to the passed array is kept
- */
- public PasswordEncryption(char[] password) {
- this(password, DEFAULT_SALT_8, DEFAULT_IV_16);
- }
-
- /**
- * This is up to the caller to clear the passed array. Neither copies of nor
- * references to the passed arrays are kept
- */
- public PasswordEncryption(char[] password, byte[] passwordSalt, byte[] initializationVector) {
- try {
- initKeyAndCiphers(password, passwordSalt, initializationVector);
- } catch (InvalidKeyException e) {
- Integer previousSecreteKeyLength = secreteKeyLength;
- secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED;
- System.err.println("'" + e.getMessage() + "', will use " + secreteKeyLength
- + " secrete key length instead of " + previousSecreteKeyLength);
- try {
- initKeyAndCiphers(password, passwordSalt, initializationVector);
- } catch (GeneralSecurityException e1) {
- throw new IllegalStateException("Cannot get secret key (with restricted length)", e1);
- }
- } catch (GeneralSecurityException e) {
- throw new IllegalStateException("Cannot get secret key", e);
- }
- }
-
- protected void initKeyAndCiphers(char[] password, byte[] passwordSalt, byte[] initializationVector)
- throws GeneralSecurityException {
- byte[] salt = new byte[8];
- System.arraycopy(passwordSalt, 0, salt, 0, salt.length);
- // for (int i = 0; i < password.length && i < salt.length; i++)
- // salt[i] = (byte) password[i];
- byte[] iv = new byte[16];
- System.arraycopy(initializationVector, 0, iv, 0, iv.length);
-
- SecretKeyFactory keyFac = SecretKeyFactory.getInstance(getSecretKeyFactoryName());
- PBEKeySpec keySpec = new PBEKeySpec(password, salt, getIterationCount(), getKeyLength());
- String secKeyEncryption = getSecretKeyEncryption();
- if (secKeyEncryption != null) {
- SecretKey tmp = keyFac.generateSecret(keySpec);
- key = new SecretKeySpec(tmp.getEncoded(), getSecretKeyEncryption());
- } else {
- key = keyFac.generateSecret(keySpec);
- }
- if (securityProviderName != null)
- ecipher = Cipher.getInstance(getCipherName(), securityProviderName);
- else
- ecipher = Cipher.getInstance(getCipherName());
- ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
- dcipher = Cipher.getInstance(getCipherName());
- dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
- }
-
- public void encrypt(InputStream decryptedIn, OutputStream encryptedOut) throws IOException {
- try {
- CipherOutputStream out = new CipherOutputStream(encryptedOut, ecipher);
- StreamUtils.copy(decryptedIn, out);
- StreamUtils.closeQuietly(out);
- } catch (IOException e) {
- throw e;
- } finally {
- StreamUtils.closeQuietly(decryptedIn);
- }
- }
-
- public void decrypt(InputStream encryptedIn, OutputStream decryptedOut) throws IOException {
- try {
- CipherInputStream decryptedIn = new CipherInputStream(encryptedIn, dcipher);
- StreamUtils.copy(decryptedIn, decryptedOut);
- } catch (IOException e) {
- throw e;
- } finally {
- StreamUtils.closeQuietly(encryptedIn);
- }
- }
-
- public byte[] encryptString(String str) {
- ByteArrayOutputStream out = null;
- ByteArrayInputStream in = null;
- try {
- out = new ByteArrayOutputStream();
- in = new ByteArrayInputStream(str.getBytes(DEFAULT_CHARSET));
- encrypt(in, out);
- return out.toByteArray();
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- StreamUtils.closeQuietly(out);
- }
- }
-
- /** Closes the input stream */
- public String decryptAsString(InputStream in) {
- ByteArrayOutputStream out = null;
- try {
- out = new ByteArrayOutputStream();
- decrypt(in, out);
- return new String(out.toByteArray(), DEFAULT_CHARSET);
- } catch (IOException e) {
- throw new RuntimeException(e);
- } finally {
- StreamUtils.closeQuietly(out);
- }
- }
-
- protected Key getKey() {
- return key;
- }
-
- protected Cipher getEcipher() {
- return ecipher;
- }
-
- protected Cipher getDcipher() {
- return dcipher;
- }
-
- protected Integer getIterationCount() {
- return iterationCount;
- }
-
- protected Integer getKeyLength() {
- return secreteKeyLength;
- }
-
- protected String getSecretKeyFactoryName() {
- return secreteKeyFactoryName;
- }
-
- protected String getSecretKeyEncryption() {
- return secreteKeyEncryption;
- }
-
- protected String getCipherName() {
- return cipherName;
- }
-
- public void setIterationCount(Integer iterationCount) {
- this.iterationCount = iterationCount;
- }
-
- public void setSecreteKeyLength(Integer keyLength) {
- this.secreteKeyLength = keyLength;
- }
-
- public void setSecreteKeyFactoryName(String secreteKeyFactoryName) {
- this.secreteKeyFactoryName = secreteKeyFactoryName;
- }
-
- public void setSecreteKeyEncryption(String secreteKeyEncryption) {
- this.secreteKeyEncryption = secreteKeyEncryption;
- }
-
- public void setCipherName(String cipherName) {
- this.cipherName = cipherName;
- }
-
- public void setSecurityProviderName(String securityProviderName) {
- this.securityProviderName = securityProviderName;
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.AsynchronousByteChannel;
-import java.nio.channels.CompletionHandler;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.WritableByteChannel;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-/** An {@link AsynchronousByteChannel} based on an {@link ExecutorService}. */
-public class ServiceChannel implements AsynchronousByteChannel {
- private final ReadableByteChannel in;
- private final WritableByteChannel out;
-
- private boolean open = true;
-
- private ExecutorService executor;
-
- public ServiceChannel(ReadableByteChannel in, WritableByteChannel out, ExecutorService executor) {
- this.in = in;
- this.out = out;
- this.executor = executor;
- }
-
- @Override
- public Future<Integer> read(ByteBuffer dst) {
- return executor.submit(() -> in.read(dst));
- }
-
- @Override
- public <A> void read(ByteBuffer dst, A attachment, CompletionHandler<Integer, ? super A> handler) {
- try {
- Future<Integer> res = read(dst);
- handler.completed(res.get(), attachment);
- } catch (Exception e) {
- handler.failed(e, attachment);
- }
- }
-
- @Override
- public Future<Integer> write(ByteBuffer src) {
- return executor.submit(() -> out.write(src));
- }
-
- @Override
- public <A> void write(ByteBuffer src, A attachment, CompletionHandler<Integer, ? super A> handler) {
- try {
- Future<Integer> res = write(src);
- handler.completed(res.get(), attachment);
- } catch (Exception e) {
- handler.failed(e, attachment);
- }
- }
-
- @Override
- public synchronized void close() throws IOException {
- try {
- in.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- out.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- open = false;
- notifyAll();
- }
-
- @Override
- public synchronized boolean isOpen() {
- return open;
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.StringJoiner;
-
-/** Stream utilities to be used when Apache Commons IO is not available. */
-public class StreamUtils {
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
-
- /*
- * APACHE COMMONS IO (inspired)
- */
-
- /** @return the number of bytes */
- public static Long copy(InputStream in, OutputStream out) throws IOException {
- Long count = 0l;
- byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
- while (true) {
- int length = in.read(buf);
- if (length < 0)
- break;
- out.write(buf, 0, length);
- count = count + length;
- }
- return count;
- }
-
- /** @return the number of chars */
- public static Long copy(Reader in, Writer out) throws IOException {
- Long count = 0l;
- char[] buf = new char[DEFAULT_BUFFER_SIZE];
- while (true) {
- int length = in.read(buf);
- if (length < 0)
- break;
- out.write(buf, 0, length);
- count = count + length;
- }
- return count;
- }
-
- public static void closeQuietly(InputStream in) {
- if (in != null)
- try {
- in.close();
- } catch (Exception e) {
- //
- }
- }
-
- public static void closeQuietly(OutputStream out) {
- if (out != null)
- try {
- out.close();
- } catch (Exception e) {
- //
- }
- }
-
- public static void closeQuietly(Reader in) {
- if (in != null)
- try {
- in.close();
- } catch (Exception e) {
- //
- }
- }
-
- public static void closeQuietly(Writer out) {
- if (out != null)
- try {
- out.close();
- } catch (Exception e) {
- //
- }
- }
-
- public static String toString(BufferedReader reader) throws IOException {
- StringJoiner sn = new StringJoiner("\n");
- String line = null;
- while ((line = reader.readLine()) != null)
- sn.add(line);
- return sn.toString();
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-/** A generic tester based on Java assertions and functional programming. */
-public class Tester {
- private Map<String, TesterStatus> results = Collections.synchronizedSortedMap(new TreeMap<>());
-
- private ClassLoader classLoader;
-
- /** Use {@link Thread#getContextClassLoader()} by default. */
- public Tester() {
- this(Thread.currentThread().getContextClassLoader());
- }
-
- public Tester(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-
- public void execute(String className) {
- Class<?> clss;
- try {
- clss = classLoader.loadClass(className);
- boolean assertionsEnabled = clss.desiredAssertionStatus();
- if (!assertionsEnabled)
- throw new IllegalStateException("Test runner " + getClass().getName()
- + " requires Java assertions to be enabled. Call the JVM with the -ea argument.");
- } catch (Exception e1) {
- throw new IllegalArgumentException("Cannot initalise test for " + className, e1);
-
- }
- List<Method> methods = findMethods(clss);
- if (methods.size() == 0)
- throw new IllegalArgumentException("No test method found in " + clss);
- // TODO make order more predictable?
- for (Method method : methods) {
- String uid = method.getDeclaringClass().getName() + "#" + method.getName();
- TesterStatus testStatus = new TesterStatus(uid);
- Object obj = null;
- try {
- beforeTest(uid, method);
- obj = clss.getDeclaredConstructor().newInstance();
- method.invoke(obj);
- testStatus.setPassed();
- afterTestPassed(uid, method, obj);
- } catch (Exception e) {
- testStatus.setFailed(e);
- afterTestFailed(uid, method, obj, e);
- } finally {
- results.put(uid, testStatus);
- }
- }
- }
-
- protected void beforeTest(String uid, Method method) {
- // System.out.println(uid + ": STARTING");
- }
-
- protected void afterTestPassed(String uid, Method method, Object obj) {
- System.out.println(uid + ": PASSED");
- }
-
- protected void afterTestFailed(String uid, Method method, Object obj, Throwable e) {
- System.out.println(uid + ": FAILED");
- e.printStackTrace();
- }
-
- protected List<Method> findMethods(Class<?> clss) {
- List<Method> methods = new ArrayList<Method>();
-// Method call = getMethod(clss, "call");
-// if (call != null)
-// methods.add(call);
-//
- for (Method method : clss.getMethods()) {
- if (method.getName().startsWith("test")) {
- methods.add(method);
- }
- }
- return methods;
- }
-
- protected Method getMethod(Class<?> clss, String name, Class<?>... parameterTypes) {
- try {
- return clss.getMethod(name, parameterTypes);
- } catch (NoSuchMethodException e) {
- return null;
- } catch (SecurityException e) {
- throw new IllegalStateException(e);
- }
- }
-
- public static void main(String[] args) {
- // deal with arguments
- String className;
- if (args.length < 1) {
- System.err.println(usage());
- System.exit(1);
- throw new IllegalArgumentException();
- } else {
- className = args[0];
- }
-
- Tester test = new Tester();
- try {
- test.execute(className);
- } catch (Throwable e) {
- e.printStackTrace();
- }
-
- Map<String, TesterStatus> r = test.results;
- for (String uid : r.keySet()) {
- TesterStatus testStatus = r.get(uid);
- System.out.println(testStatus);
- }
- }
-
- public static String usage() {
- return "java " + Tester.class.getName() + " [test class name]";
-
- }
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.io.Serializable;
-
-/** The status of a test. */
-public class TesterStatus implements Serializable {
- private static final long serialVersionUID = 6272975746885487000L;
-
- private Boolean passed = null;
- private final String uid;
- private Throwable throwable = null;
-
- public TesterStatus(String uid) {
- this.uid = uid;
- }
-
- /** For cloning. */
- public TesterStatus(String uid, Boolean passed, Throwable throwable) {
- this(uid);
- this.passed = passed;
- this.throwable = throwable;
- }
-
- public synchronized Boolean isRunning() {
- return passed == null;
- }
-
- public synchronized Boolean isPassed() {
- assert passed != null;
- return passed;
- }
-
- public synchronized Boolean isFailed() {
- assert passed != null;
- return !passed;
- }
-
- public synchronized void setPassed() {
- setStatus(true);
- }
-
- public synchronized void setFailed() {
- setStatus(false);
- }
-
- public synchronized void setFailed(Throwable throwable) {
- setStatus(false);
- setThrowable(throwable);
- }
-
- protected void setStatus(Boolean passed) {
- if (this.passed != null)
- throw new IllegalStateException("Passed status of test " + uid + " is already set (to " + passed + ")");
- this.passed = passed;
- }
-
- protected void setThrowable(Throwable throwable) {
- if (this.throwable != null)
- throw new IllegalStateException("Throwable of test " + uid + " is already set (to " + passed + ")");
- this.throwable = throwable;
- }
-
- public String getUid() {
- return uid;
- }
-
- public Throwable getThrowable() {
- return throwable;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- // TODO Auto-generated method stub
- return super.clone();
- }
-
- @Override
- public boolean equals(Object o) {
- if (o instanceof TesterStatus) {
- TesterStatus other = (TesterStatus) o;
- // we don't check consistency for performance purposes
- // this equals() is supposed to be used in collections or for transfer
- return other.uid.equals(uid);
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return uid.hashCode();
- }
-
- @Override
- public String toString() {
- return uid + "\t" + (passed ? "passed" : "failed");
- }
-
-}
+++ /dev/null
-package org.argeo.util;
-
-import java.text.NumberFormat;
-import java.text.ParseException;
-import java.util.Locale;
-
-/** A throughput, that is, a value per unit of time. */
-public class Throughput {
- private final static NumberFormat usNumberFormat = NumberFormat.getInstance(Locale.US);
-
- public enum Unit {
- s, m, h, d
- }
-
- private final Double value;
- private final Unit unit;
-
- public Throughput(Double value, Unit unit) {
- this.value = value;
- this.unit = unit;
- }
-
- public Throughput(Long periodMs, Long count, Unit unit) {
- if (unit.equals(Unit.s))
- value = ((double) count * 1000d) / periodMs;
- else if (unit.equals(Unit.m))
- value = ((double) count * 60d * 1000d) / periodMs;
- else if (unit.equals(Unit.h))
- value = ((double) count * 60d * 60d * 1000d) / periodMs;
- else if (unit.equals(Unit.d))
- value = ((double) count * 24d * 60d * 60d * 1000d) / periodMs;
- else
- throw new IllegalArgumentException("Unsupported unit " + unit);
- this.unit = unit;
- }
-
- public Throughput(Double value, String unitStr) {
- this(value, Unit.valueOf(unitStr));
- }
-
- public Throughput(String def) {
- int index = def.indexOf('/');
- if (def.length() < 3 || index <= 0 || index != def.length() - 2)
- throw new IllegalArgumentException(
- def + " no a proper throughput definition" + " (should be <value>/<unit>, e.g. 3.54/s or 1500/h");
- String valueStr = def.substring(0, index);
- String unitStr = def.substring(index + 1);
- try {
- this.value = usNumberFormat.parse(valueStr).doubleValue();
- } catch (ParseException e) {
- throw new IllegalArgumentException("Cannot parse " + valueStr + " as a number.", e);
- }
- this.unit = Unit.valueOf(unitStr);
- }
-
- public Long asMsPeriod() {
- if (unit.equals(Unit.s))
- return Math.round(1000d / value);
- else if (unit.equals(Unit.m))
- return Math.round((60d * 1000d) / value);
- else if (unit.equals(Unit.h))
- return Math.round((60d * 60d * 1000d) / value);
- else if (unit.equals(Unit.d))
- return Math.round((24d * 60d * 60d * 1000d) / value);
- else
- throw new IllegalArgumentException("Unsupported unit " + unit);
- }
-
- @Override
- public String toString() {
- return usNumberFormat.format(value) + '/' + unit;
- }
-
- public Double getValue() {
- return value;
- }
-
- public Unit getUnit() {
- return unit;
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory;
-
-import java.util.Optional;
-
-import org.argeo.util.transaction.WorkControl;
-
-/** An information directory (typicylly LDAP). */
-public interface Directory extends HierarchyUnit {
- String getName();
-
- /** Whether this directory is read only. */
- boolean isReadOnly();
-
- /** Whether this directory is disabled. */
- boolean isDisabled();
-
- /** The realm (typically Kerberos) of this directory. */
- Optional<String> getRealm();
-
- /** Sets the transaction control used by this directory when editing. */
- void setTransactionControl(WorkControl transactionControl);
-
- /*
- * HIERARCHY
- */
-
- /** The hierarchy unit at this path. */
- HierarchyUnit getHierarchyUnit(String path);
-
- /** Create a new hierarchy unit. */
- HierarchyUnit createHierarchyUnit(String path);
-}
+++ /dev/null
-package org.argeo.util.directory;
-
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.UnknownHostException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import org.argeo.util.directory.ldap.IpaUtils;
-import org.argeo.util.naming.NamingUtils;
-
-/** Properties used to configure user admins. */
-public enum DirectoryConf {
- /** Base DN (cannot be configured externally) */
- baseDn(null),
-
- /** URI of the underlying resource (cannot be configured externally) */
- uri(null),
-
- /** User objectClass */
- userObjectClass("inetOrgPerson"),
-
- /** Relative base DN for users */
- userBase("ou=People"),
-
- /** Groups objectClass */
- groupObjectClass("groupOfNames"),
-
- /** Relative base DN for users */
- groupBase("ou=Groups"),
-
- /** Relative base DN for users */
- systemRoleBase("ou=Roles"),
-
- /** Read-only source */
- readOnly(null),
-
- /** Disabled source */
- disabled(null),
-
- /** Authentication realm */
- realm(null),
-
- /** Override all passwords with this value (typically for testing purposes) */
- forcedPassword(null);
-
- public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config";
-
- public final static String SCHEME_LDAP = "ldap";
- public final static String SCHEME_LDAPS = "ldaps";
- public final static String SCHEME_FILE = "file";
- public final static String SCHEME_OS = "os";
- public final static String SCHEME_IPA = "ipa";
-
- private final static String SECURITY_PRINCIPAL = "java.naming.security.principal";
- private final static String SECURITY_CREDENTIALS = "java.naming.security.credentials";
-
- /** The default value. */
- private Object def;
-
- DirectoryConf(Object def) {
- this.def = def;
- }
-
- public Object getDefault() {
- return def;
- }
-
- /**
- * For use as Java property.
- *
- * @deprecated use {@link #name()} instead
- */
- @Deprecated
- public String property() {
- return name();
- }
-
- public String getValue(Dictionary<String, ?> properties) {
- Object res = getRawValue(properties);
- if (res == null)
- return null;
- return res.toString();
- }
-
- @SuppressWarnings("unchecked")
- public <T> T getRawValue(Dictionary<String, ?> properties) {
- Object res = properties.get(name());
- if (res == null)
- res = getDefault();
- return (T) res;
- }
-
- /** @deprecated use {@link #valueOf(String)} instead */
- @Deprecated
- public static DirectoryConf local(String property) {
- return DirectoryConf.valueOf(property);
- }
-
- /** Hides host and credentials. */
- public static URI propertiesAsUri(Dictionary<String, ?> properties) {
- StringBuilder query = new StringBuilder();
-
- boolean first = true;
-// for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
-// String key = keys.nextElement();
-// // TODO clarify which keys are relevant (list only the enum?)
-// if (!key.equals("service.factoryPid") && !key.equals("cn") && !key.equals("dn")
-// && !key.equals(Constants.SERVICE_PID) && !key.startsWith("java") && !key.equals(baseDn.name())
-// && !key.equals(uri.name()) && !key.equals(Constants.OBJECTCLASS)
-// && !key.equals(Constants.SERVICE_ID) && !key.equals("bundle.id")) {
-// if (first)
-// first = false;
-// else
-// query.append('&');
-// query.append(valueOf(key).name());
-// query.append('=').append(properties.get(key).toString());
-// }
-// }
-
- keys: for (DirectoryConf key : DirectoryConf.values()) {
- if (key.equals(baseDn) || key.equals(uri))
- continue keys;
- Object value = properties.get(key.name());
- if (value == null)
- continue keys;
- if (first)
- first = false;
- else
- query.append('&');
- query.append(key.name());
- query.append('=').append(value.toString());
-
- }
-
- Object bDnObj = properties.get(baseDn.name());
- String bDn = bDnObj != null ? bDnObj.toString() : null;
- try {
- return new URI(null, null, bDn != null ? '/' + bDn : null, query.length() != 0 ? query.toString() : null,
- null);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Cannot create URI from properties", e);
- }
- }
-
- public static Dictionary<String, Object> uriAsProperties(String uriStr) {
- try {
- Hashtable<String, Object> res = new Hashtable<String, Object>();
- URI u = new URI(uriStr);
- String scheme = u.getScheme();
- if (scheme != null && scheme.equals(SCHEME_IPA)) {
- return IpaUtils.convertIpaUri(u);
-// scheme = u.getScheme();
- }
- String path = u.getPath();
- // base DN
- String bDn = path.substring(path.lastIndexOf('/') + 1, path.length());
- if (bDn.equals("") && SCHEME_OS.equals(scheme)) {
- bDn = getBaseDnFromHostname();
- }
-
- if (bDn.endsWith(".ldif"))
- bDn = bDn.substring(0, bDn.length() - ".ldif".length());
-
- // Normalize base DN as LDAP name
-// bDn = new LdapName(bDn).toString();
-
- String principal = null;
- String credentials = null;
- if (scheme != null)
- if (scheme.equals(SCHEME_LDAP) || scheme.equals(SCHEME_LDAPS)) {
- // TODO additional checks
- if (u.getUserInfo() != null) {
- String[] userInfo = u.getUserInfo().split(":");
- principal = userInfo.length > 0 ? userInfo[0] : null;
- credentials = userInfo.length > 1 ? userInfo[1] : null;
- }
- } else if (scheme.equals(SCHEME_FILE)) {
- } else if (scheme.equals(SCHEME_IPA)) {
- } else if (scheme.equals(SCHEME_OS)) {
- } else
- throw new IllegalArgumentException("Unsupported scheme " + scheme);
- Map<String, List<String>> query = NamingUtils.queryToMap(u);
- for (String key : query.keySet()) {
- DirectoryConf ldapProp = DirectoryConf.valueOf(key);
- List<String> values = query.get(key);
- if (values.size() == 1) {
- res.put(ldapProp.name(), values.get(0));
- } else {
- throw new IllegalArgumentException("Only single values are supported");
- }
- }
- res.put(baseDn.name(), bDn);
- if (SCHEME_OS.equals(scheme))
- res.put(readOnly.name(), "true");
- if (principal != null)
- res.put(SECURITY_PRINCIPAL, principal);
- if (credentials != null)
- res.put(SECURITY_CREDENTIALS, credentials);
- if (scheme != null) {// relative URIs are dealt with externally
- if (SCHEME_OS.equals(scheme)) {
- res.put(uri.name(), SCHEME_OS + ":///");
- } else {
- URI bareUri = new URI(scheme, null, u.getHost(), u.getPort(),
- scheme.equals(SCHEME_FILE) ? u.getPath() : null, null, null);
- res.put(uri.name(), bareUri.toString());
- }
- }
- return res;
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException("Cannot convert " + uri + " to properties", e);
- }
- }
-
- private static String getBaseDnFromHostname() {
- String hostname;
- try {
- hostname = InetAddress.getLocalHost().getHostName();
- } catch (UnknownHostException e) {
- hostname = "localhost.localdomain";
- }
- int dotIdx = hostname.indexOf('.');
- if (dotIdx >= 0) {
- String domain = hostname.substring(dotIdx + 1, hostname.length());
- String bDn = ("." + domain).replaceAll("\\.", ",dc=");
- bDn = bDn.substring(1, bDn.length());
- return bDn;
- } else {
- return "dc=" + hostname;
- }
- }
-
- /**
- * Hash the base DN in order to have a deterministic string to be used as a cn
- * for the underlying user directory.
- */
- public static String baseDnHash(Dictionary<String, Object> properties) {
- String bDn = (String) properties.get(baseDn.name());
- if (bDn == null)
- throw new IllegalStateException("No baseDn in " + properties);
- return DirectoryDigestUtils.sha1str(bDn);
- }
-}
+++ /dev/null
-package org.argeo.util.directory;
-
-import java.math.BigInteger;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.KeySpec;
-import java.util.Arrays;
-
-import javax.crypto.SecretKeyFactory;
-import javax.crypto.spec.PBEKeySpec;
-
-/** Utilities around digests, mostly those related to passwords. */
-public class DirectoryDigestUtils {
- public final static String PASSWORD_SCHEME_SHA = "SHA";
- public final static String PASSWORD_SCHEME_PBKDF2_SHA256 = "PBKDF2_SHA256";
-
- public static byte[] sha1(byte[] bytes) {
- try {
- MessageDigest digest = MessageDigest.getInstance("SHA1");
- digest.update(bytes);
- byte[] checksum = digest.digest();
- return checksum;
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalStateException("Cannot SHA1 digest", e);
- }
- }
-
- public static byte[] toPasswordScheme(String passwordScheme, char[] password, byte[] salt, Integer iterations,
- Integer keyLength) {
- try {
- if (PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
- MessageDigest digest = MessageDigest.getInstance("SHA1");
- byte[] bytes = charsToBytes(password);
- digest.update(bytes);
- return digest.digest();
- } else if (PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
- KeySpec spec = new PBEKeySpec(password, salt, iterations, keyLength);
-
- SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
- final int ITERATION_LENGTH = 4;
- byte[] key = f.generateSecret(spec).getEncoded();
- byte[] result = new byte[ITERATION_LENGTH + salt.length + key.length];
- byte iterationsArr[] = new BigInteger(iterations.toString()).toByteArray();
- if (iterationsArr.length < ITERATION_LENGTH) {
- Arrays.fill(result, 0, ITERATION_LENGTH - iterationsArr.length, (byte) 0);
- System.arraycopy(iterationsArr, 0, result, ITERATION_LENGTH - iterationsArr.length,
- iterationsArr.length);
- } else {
- System.arraycopy(iterationsArr, 0, result, 0, ITERATION_LENGTH);
- }
- System.arraycopy(salt, 0, result, ITERATION_LENGTH, salt.length);
- System.arraycopy(key, 0, result, ITERATION_LENGTH + salt.length, key.length);
- return result;
- } else {
- throw new UnsupportedOperationException("Unkown password scheme " + passwordScheme);
- }
- } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
- throw new IllegalStateException("Cannot digest", e);
- }
- }
-
- public static char[] bytesToChars(Object obj) {
- if (obj instanceof char[])
- return (char[]) obj;
- if (!(obj instanceof byte[]))
- throw new IllegalArgumentException(obj.getClass() + " is not a byte array");
- ByteBuffer fromBuffer = ByteBuffer.wrap((byte[]) obj);
- CharBuffer toBuffer = StandardCharsets.UTF_8.decode(fromBuffer);
- char[] res = Arrays.copyOfRange(toBuffer.array(), toBuffer.position(), toBuffer.limit());
- // Arrays.fill(fromBuffer.array(), (byte) 0); // clear sensitive data
- // Arrays.fill((byte[]) obj, (byte) 0); // clear sensitive data
- // Arrays.fill(toBuffer.array(), '\u0000'); // clear sensitive data
- return res;
- }
-
- public static byte[] charsToBytes(char[] chars) {
- CharBuffer charBuffer = CharBuffer.wrap(chars);
- ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
- byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit());
- // Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data
- // Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data
- return bytes;
- }
-
- public static String sha1str(String str) {
- byte[] hash = sha1(str.getBytes(StandardCharsets.UTF_8));
- return encodeHexString(hash);
- }
-
- final private static char[] hexArray = "0123456789abcdef".toCharArray();
-
- /**
- * From
- * http://stackoverflow.com/questions/9655181/how-to-convert-a-byte-array-to
- * -a-hex-string-in-java
- */
- public static String encodeHexString(byte[] bytes) {
- char[] hexChars = new char[bytes.length * 2];
- for (int j = 0; j < bytes.length; j++) {
- int v = bytes[j] & 0xFF;
- hexChars[j * 2] = hexArray[v >>> 4];
- hexChars[j * 2 + 1] = hexArray[v & 0x0F];
- }
- return new String(hexChars);
- }
-
- /** singleton */
- private DirectoryDigestUtils() {
- }
-}
+++ /dev/null
-package org.argeo.util.directory;
-
-import java.util.Dictionary;
-import java.util.Locale;
-
-/** A unit within the high-level organisational structure of a directory. */
-public interface HierarchyUnit {
- /** Name to use in paths. */
- String getHierarchyUnitName();
-
- /** Name to use in UI. */
- String getHierarchyUnitLabel(Locale locale);
-
- /**
- * The parent {@link HierarchyUnit}, or <code>null</code> if a
- * {@link Directory}.
- */
- HierarchyUnit getParent();
-
- /** Direct children {@link HierarchyUnit}s. */
- Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly);
-
- /**
- * Whether this is an arbitrary named and placed {@link HierarchyUnit}.
- *
- * @return <code>true</code> if functional, <code>false</code> is technical
- * (e.g. People, Groups, etc.)
- */
- boolean isFunctional();
-
- /**
- * The base of this organisational unit within the hierarchy. This would
- * typically be an LDAP base DN.
- */
- String getBase();
-
- /** The related {@link Directory}. */
- Directory getDirectory();
-
- /** Its metadata (typically LDAP attributes). */
- Dictionary<String, Object> getProperties();
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import static org.argeo.util.directory.ldap.LdapNameUtils.toLdapName;
-
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.StringJoiner;
-
-import javax.naming.InvalidNameException;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-import javax.transaction.xa.XAResource;
-
-import org.argeo.osgi.useradmin.OsUserDirectory;
-import org.argeo.util.directory.Directory;
-import org.argeo.util.directory.DirectoryConf;
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
-import org.argeo.util.transaction.WorkControl;
-import org.argeo.util.transaction.WorkingCopyXaResource;
-import org.argeo.util.transaction.XAResourceProvider;
-
-/** A {@link Directory} based either on LDAP or LDIF. */
-public abstract class AbstractLdapDirectory implements Directory, XAResourceProvider {
- protected static final String SHARED_STATE_USERNAME = "javax.security.auth.login.name";
- protected static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password";
-
- private final LdapName baseDn;
- private final Hashtable<String, Object> configProperties;
- private final Rdn userBaseRdn, groupBaseRdn, systemRoleBaseRdn;
- private final String userObjectClass, groupObjectClass;
- private String memberAttributeId = "member";
-
- private final boolean readOnly;
- private final boolean disabled;
- private final String uri;
-
- private String forcedPassword;
-
- private final boolean scoped;
-
- private List<String> credentialAttributeIds = Arrays
- .asList(new String[] { LdapAttrs.userPassword.name(), LdapAttrs.authPassword.name() });
-
- private WorkControl transactionControl;
- private WorkingCopyXaResource<LdapEntryWorkingCopy> xaResource;
-
- private LdapDirectoryDao directoryDao;
-
- public AbstractLdapDirectory(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
- this.configProperties = new Hashtable<String, Object>();
- for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
- String key = keys.nextElement();
- configProperties.put(key, props.get(key));
- }
-
- String baseDnStr = DirectoryConf.baseDn.getValue(configProperties);
- if (baseDnStr == null)
- throw new IllegalArgumentException("Base DN must be specified: " + configProperties);
- baseDn = toLdapName(baseDnStr);
- this.scoped = scoped;
-
- if (uriArg != null) {
- uri = uriArg.toString();
- // uri from properties is ignored
- } else {
- String uriStr = DirectoryConf.uri.getValue(configProperties);
- if (uriStr == null)
- uri = null;
- else
- uri = uriStr;
- }
-
- forcedPassword = DirectoryConf.forcedPassword.getValue(configProperties);
-
- userObjectClass = DirectoryConf.userObjectClass.getValue(configProperties);
- groupObjectClass = DirectoryConf.groupObjectClass.getValue(configProperties);
-
- String userBase = DirectoryConf.userBase.getValue(configProperties);
- String groupBase = DirectoryConf.groupBase.getValue(configProperties);
- String systemRoleBase = DirectoryConf.systemRoleBase.getValue(configProperties);
- try {
-// baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties));
- userBaseRdn = new Rdn(userBase);
-// userBaseDn = new LdapName(userBase + "," + baseDn);
- groupBaseRdn = new Rdn(groupBase);
-// groupBaseDn = new LdapName(groupBase + "," + baseDn);
- systemRoleBaseRdn = new Rdn(systemRoleBase);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException(
- "Badly formated base DN " + DirectoryConf.baseDn.getValue(configProperties), e);
- }
-
- // read only
- String readOnlyStr = DirectoryConf.readOnly.getValue(configProperties);
- if (readOnlyStr == null) {
- readOnly = readOnlyDefault(uri);
- configProperties.put(DirectoryConf.readOnly.name(), Boolean.toString(readOnly));
- } else
- readOnly = Boolean.parseBoolean(readOnlyStr);
-
- // disabled
- String disabledStr = DirectoryConf.disabled.getValue(configProperties);
- if (disabledStr != null)
- disabled = Boolean.parseBoolean(disabledStr);
- else
- disabled = false;
- if (!getRealm().isEmpty()) {
- // IPA multiple LDAP causes URI parsing to fail
- // TODO manage generic redundant LDAP case
- directoryDao = new LdapDao(this);
- } else {
- if (uri != null) {
- URI u = URI.create(uri);
- if (DirectoryConf.SCHEME_LDAP.equals(u.getScheme())
- || DirectoryConf.SCHEME_LDAPS.equals(u.getScheme())) {
- directoryDao = new LdapDao(this);
- } else if (DirectoryConf.SCHEME_FILE.equals(u.getScheme())) {
- directoryDao = new LdifDao(this);
- } else if (DirectoryConf.SCHEME_OS.equals(u.getScheme())) {
- directoryDao = new OsUserDirectory(this);
- // singleUser = true;
- } else {
- throw new IllegalArgumentException("Unsupported scheme " + u.getScheme());
- }
- } else {
- // in memory
- directoryDao = new LdifDao(this);
- }
- }
- if (directoryDao != null)
- xaResource = new WorkingCopyXaResource<>(directoryDao);
- }
-
- /*
- * INITIALISATION
- */
-
- public void init() {
- getDirectoryDao().init();
- }
-
- public void destroy() {
- getDirectoryDao().destroy();
- }
-
- /*
- * CREATION
- */
- protected abstract LdapEntry newUser(LdapName name);
-
- protected abstract LdapEntry newGroup(LdapName name);
-
- /*
- * EDITION
- */
-
- public boolean isEditing() {
- return xaResource.wc() != null;
- }
-
- public LdapEntryWorkingCopy getWorkingCopy() {
- LdapEntryWorkingCopy wc = xaResource.wc();
- if (wc == null)
- return null;
- return wc;
- }
-
- public void checkEdit() {
- if (xaResource.wc() == null) {
- try {
- transactionControl.getWorkContext().registerXAResource(xaResource, null);
- } catch (Exception e) {
- throw new IllegalStateException("Cannot enlist " + xaResource, e);
- }
- } else {
- }
- }
-
- public void setTransactionControl(WorkControl transactionControl) {
- this.transactionControl = transactionControl;
- }
-
- public XAResource getXaResource() {
- return xaResource;
- }
-
- public boolean removeEntry(LdapName dn) {
- checkEdit();
- LdapEntryWorkingCopy wc = getWorkingCopy();
- boolean actuallyDeleted;
- if (getDirectoryDao().entryExists(dn) || wc.getNewData().containsKey(dn)) {
- LdapEntry user = doGetRole(dn);
- wc.getDeletedData().put(dn, user);
- actuallyDeleted = true;
- } else {// just removing from groups (e.g. system roles)
- actuallyDeleted = false;
- }
- for (LdapName groupDn : getDirectoryDao().getDirectGroups(dn)) {
- LdapEntry group = doGetRole(groupDn);
- group.getAttributes().get(getMemberAttributeId()).remove(dn.toString());
- }
- return actuallyDeleted;
- }
-
- /*
- * RETRIEVAL
- */
-
- protected LdapEntry doGetRole(LdapName dn) {
- LdapEntryWorkingCopy wc = getWorkingCopy();
- LdapEntry user;
- try {
- user = getDirectoryDao().doGetEntry(dn);
- } catch (NameNotFoundException e) {
- user = null;
- }
- if (wc != null) {
- if (user == null && wc.getNewData().containsKey(dn))
- user = wc.getNewData().get(dn);
- else if (wc.getDeletedData().containsKey(dn))
- user = null;
- }
- return user;
- }
-
- protected void collectGroups(LdapEntry user, List<LdapEntry> allRoles) {
- Attributes attrs = user.getAttributes();
- // TODO centralize attribute name
- Attribute memberOf = attrs.get(LdapAttrs.memberOf.name());
- // if user belongs to this directory, we only check memberOf
- if (memberOf != null && user.getDn().startsWith(getBaseDn())) {
- try {
- NamingEnumeration<?> values = memberOf.getAll();
- while (values.hasMore()) {
- Object value = values.next();
- LdapName groupDn = new LdapName(value.toString());
- LdapEntry group = doGetRole(groupDn);
- if (group != null) {
- allRoles.add(group);
- } else {
- // user doesn't have the right to retrieve role, but we know it exists
- // otherwise memberOf would not work
- group = newGroup(groupDn);
- allRoles.add(group);
- }
- }
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get memberOf groups for " + user, e);
- }
- } else {
- directGroups: for (LdapName groupDn : getDirectoryDao().getDirectGroups(user.getDn())) {
- LdapEntry group = doGetRole(groupDn);
- if (group != null) {
- if (allRoles.contains(group)) {
- // important in order to avoi loops
- continue directGroups;
- }
- allRoles.add(group);
- collectGroups(group, allRoles);
- }
- }
- }
- }
-
- /*
- * HIERARCHY
- */
- @Override
- public HierarchyUnit getHierarchyUnit(String path) {
- LdapName dn = pathToName(path);
- return directoryDao.doGetHierarchyUnit(dn);
- }
-
- @Override
- public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
- return directoryDao.doGetDirectHierarchyUnits(baseDn, functionalOnly);
- }
-
- @Override
- public String getHierarchyUnitName() {
- return getName();
- }
-
- @Override
- public String getHierarchyUnitLabel(Locale locale) {
- String key = LdapNameUtils.getLastRdn(getBaseDn()).getType();
- Object value = LdapEntry.getLocalized(asLdapEntry().getProperties(), key, locale);
- if (value == null)
- value = getHierarchyUnitName();
- assert value != null;
- return value.toString();
- }
-
- @Override
- public HierarchyUnit getParent() {
- return null;
- }
-
- @Override
- public boolean isFunctional() {
- return true;
- }
-
- @Override
- public Directory getDirectory() {
- return this;
- }
-
- @Override
- public HierarchyUnit createHierarchyUnit(String path) {
- checkEdit();
- LdapEntryWorkingCopy wc = getWorkingCopy();
- LdapName dn = pathToName(path);
- if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
- || wc.getNewData().containsKey(dn))
- throw new IllegalArgumentException("Already a hierarchy unit " + path);
- BasicAttributes attrs = new BasicAttributes(true);
- attrs.put(LdapAttrs.objectClass.name(), LdapObjs.organizationalUnit.name());
- Rdn nameRdn = dn.getRdn(dn.size() - 1);
- // TODO deal with multiple attr RDN
- attrs.put(nameRdn.getType(), nameRdn.getValue());
- wc.getModifiedData().put(dn, attrs);
- LdapHierarchyUnit newHierarchyUnit = new LdapHierarchyUnit(this, dn);
- wc.getNewData().put(dn, newHierarchyUnit);
- return newHierarchyUnit;
- }
-
- /*
- * PATHS
- */
-
- @Override
- public String getBase() {
- return getBaseDn().toString();
- }
-
- @Override
- public String getName() {
- return nameToSimple(getBaseDn(), ".");
- }
-
- protected String nameToRelativePath(LdapName dn) {
- LdapName name = LdapNameUtils.relativeName(getBaseDn(), dn);
- return nameToSimple(name, "/");
- }
-
- protected String nameToSimple(LdapName name, String separator) {
- StringJoiner path = new StringJoiner(separator);
- for (int i = 0; i < name.size(); i++) {
- path.add(name.getRdn(i).getValue().toString());
- }
- return path.toString();
-
- }
-
- protected LdapName pathToName(String path) {
- try {
- LdapName name = (LdapName) getBaseDn().clone();
- String[] segments = path.split("/");
- Rdn parentRdn = null;
- // segments[0] is the directory itself
- for (int i = 0; i < segments.length; i++) {
- String segment = segments[i];
- // TODO make attr names configurable ?
- String attr = path.startsWith("accounts/")/* IPA */ ? LdapAttrs.cn.name() : LdapAttrs.ou.name();
- if (parentRdn != null) {
- if (getUserBaseRdn().equals(parentRdn))
- attr = LdapAttrs.uid.name();
- else if (getGroupBaseRdn().equals(parentRdn))
- attr = LdapAttrs.cn.name();
- else if (getSystemRoleBaseRdn().equals(parentRdn))
- attr = LdapAttrs.cn.name();
- }
- Rdn rdn = new Rdn(attr, segment);
- name.add(rdn);
- parentRdn = rdn;
- }
- return name;
- } catch (InvalidNameException e) {
- throw new IllegalStateException("Cannot get role " + path, e);
- }
-
- }
-
- /*
- * UTILITIES
- */
- protected boolean isExternal(LdapName name) {
- return !name.startsWith(baseDn);
- }
-
- protected static boolean hasObjectClass(Attributes attrs, LdapObjs objectClass) {
- return hasObjectClass(attrs, objectClass.name());
- }
-
- protected static boolean hasObjectClass(Attributes attrs, String objectClass) {
- try {
- Attribute attr = attrs.get(LdapAttrs.objectClass.name());
- NamingEnumeration<?> en = attr.getAll();
- while (en.hasMore()) {
- String v = en.next().toString();
- if (v.equalsIgnoreCase(objectClass))
- return true;
-
- }
- return false;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot search for objectClass " + objectClass, e);
- }
- }
-
- private static boolean readOnlyDefault(String uriStr) {
- if (uriStr == null)
- return true;
- /// TODO make it more generic
- URI uri;
- try {
- uri = new URI(uriStr.split(" ")[0]);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- if (uri.getScheme() == null)
- return false;// assume relative file to be writable
- if (uri.getScheme().equals(DirectoryConf.SCHEME_FILE)) {
- File file = new File(uri);
- if (file.exists())
- return !file.canWrite();
- else
- return !file.getParentFile().canWrite();
- } else if (uri.getScheme().equals(DirectoryConf.SCHEME_LDAP)) {
- if (uri.getAuthority() != null)// assume writable if authenticated
- return false;
- } else if (uri.getScheme().equals(DirectoryConf.SCHEME_OS)) {
- return true;
- }
- return true;// read only by default
- }
-
- /*
- * AS AN ENTRY
- */
- public LdapEntry asLdapEntry() {
- try {
- return directoryDao.doGetEntry(baseDn);
- } catch (NameNotFoundException e) {
- throw new IllegalStateException("Cannot get " + baseDn + " entry", e);
- }
- }
-
- public Dictionary<String, Object> getProperties() {
- return asLdapEntry().getProperties();
- }
-
- /*
- * ACCESSORS
- */
- @Override
- public Optional<String> getRealm() {
- Object realm = configProperties.get(DirectoryConf.realm.name());
- if (realm == null)
- return Optional.empty();
- return Optional.of(realm.toString());
- }
-
- public LdapName getBaseDn() {
- return (LdapName) baseDn.clone();
- }
-
- public boolean isReadOnly() {
- return readOnly;
- }
-
- public boolean isDisabled() {
- return disabled;
- }
-
- public Rdn getUserBaseRdn() {
- return userBaseRdn;
- }
-
- public Rdn getGroupBaseRdn() {
- return groupBaseRdn;
- }
-
- public Rdn getSystemRoleBaseRdn() {
- return systemRoleBaseRdn;
- }
-
-// public Dictionary<String, Object> getConfigProperties() {
-// return configProperties;
-// }
-
- public Dictionary<String, Object> cloneConfigProperties() {
- return new Hashtable<>(configProperties);
- }
-
- public String getForcedPassword() {
- return forcedPassword;
- }
-
- public boolean isScoped() {
- return scoped;
- }
-
- public List<String> getCredentialAttributeIds() {
- return credentialAttributeIds;
- }
-
- public String getUri() {
- return uri;
- }
-
- public LdapDirectoryDao getDirectoryDao() {
- return directoryDao;
- }
-
- /** dn can be null, in that case a default should be returned. */
- public String getUserObjectClass() {
- return userObjectClass;
- }
-
- public String getGroupObjectClass() {
- return groupObjectClass;
- }
-
- public String getMemberAttributeId() {
- return memberAttributeId;
- }
-
- /*
- * OBJECT METHODS
- */
-
- @Override
- public int hashCode() {
- return baseDn.hashCode();
- }
-
- @Override
- public String toString() {
- return "Directory " + baseDn.toString();
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-public abstract class AbstractLdapDirectoryDao implements LdapDirectoryDao {
-
- private AbstractLdapDirectory directory;
-
- public AbstractLdapDirectoryDao(AbstractLdapDirectory directory) {
- this.directory = directory;
-
- }
-
- public AbstractLdapDirectory getDirectory() {
- return directory;
- }
-
- @Override
- public LdapEntryWorkingCopy newWorkingCopy() {
- return new LdapEntryWorkingCopy();
- }
-
- @Override
- public LdapEntry newUser(LdapName name) {
- return getDirectory().newUser(name);
- }
-
- @Override
- public LdapEntry newGroup(LdapName name) {
- return getDirectory().newGroup(name);
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-
-public class AttributesDictionary extends Dictionary<String, Object> {
- private final Attributes attributes;
-
- /** The provided attributes is wrapped, not copied. */
- public AttributesDictionary(Attributes attributes) {
- if (attributes == null)
- throw new IllegalArgumentException("Attributes cannot be null");
- this.attributes = attributes;
- }
-
- @Override
- public int size() {
- return attributes.size();
- }
-
- @Override
- public boolean isEmpty() {
- return attributes.size() == 0;
- }
-
- @Override
- public Enumeration<String> keys() {
- NamingEnumeration<String> namingEnumeration = attributes.getIDs();
- return new Enumeration<String>() {
-
- @Override
- public boolean hasMoreElements() {
- return namingEnumeration.hasMoreElements();
- }
-
- @Override
- public String nextElement() {
- return namingEnumeration.nextElement();
- }
-
- };
- }
-
- @Override
- public Enumeration<Object> elements() {
- NamingEnumeration<String> namingEnumeration = attributes.getIDs();
- return new Enumeration<Object>() {
-
- @Override
- public boolean hasMoreElements() {
- return namingEnumeration.hasMoreElements();
- }
-
- @Override
- public Object nextElement() {
- String key = namingEnumeration.nextElement();
- return get(key);
- }
-
- };
- }
-
- @Override
- /** @returns a <code>String</code> or <code>String[]</code> */
- public Object get(Object key) {
- try {
- if (key == null)
- throw new IllegalArgumentException("Key cannot be null");
- Attribute attr = attributes.get(key.toString());
- if (attr == null)
- return null;
- if (attr.size() == 0)
- throw new IllegalStateException("There must be at least one value");
- else if (attr.size() == 1) {
- return attr.get().toString();
- } else {// multiple
- String[] res = new String[attr.size()];
- for (int i = 0; i < attr.size(); i++) {
- Object value = attr.get();
- if (value == null)
- throw new RuntimeException("Values cannot be null");
- res[i] = attr.get(i).toString();
- }
- return res;
- }
- } catch (NamingException e) {
- throw new RuntimeException("Cannot get value for " + key, e);
- }
- }
-
- @Override
- public Object put(String key, Object value) {
- if (key == null)
- throw new IllegalArgumentException("Key cannot be null");
- if (value == null)
- throw new IllegalArgumentException("Value cannot be null");
-
- Object oldValue = get(key);
- Attribute attr = attributes.get(key);
- if (attr == null) {
- attr = new BasicAttribute(key);
- attributes.put(attr);
- }
-
- if (value instanceof String[]) {
- String[] values = (String[]) value;
- // clean additional values
- for (int i = values.length; i < attr.size(); i++)
- attr.remove(i);
- // set values
- for (int i = 0; i < values.length; i++) {
- attr.set(i, values[i]);
- }
- } else {
- if (attr.size() > 1)
- throw new IllegalArgumentException("Attribute " + key + " is multi-valued");
- if (attr.size() == 1) {
- try {
- if (!attr.get(0).equals(value))
- attr.set(0, value.toString());
- } catch (NamingException e) {
- throw new RuntimeException("Cannot check existing value", e);
- }
- } else {
- attr.add(value.toString());
- }
- }
- return oldValue;
- }
-
- @Override
- public Object remove(Object key) {
- if (key == null)
- throw new IllegalArgumentException("Key cannot be null");
- Object oldValue = get(key);
- if (oldValue == null)
- return null;
- return attributes.remove(key.toString());
- }
-
- /**
- * Copy the <b>content</b> of an {@link Attributes} to the provided
- * {@link Dictionary}.
- */
- public static void copy(Attributes attributes, Dictionary<String, Object> dictionary) {
- AttributesDictionary ad = new AttributesDictionary(attributes);
- Enumeration<String> keys = ad.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- dictionary.put(key, ad.get(key));
- }
- }
-
- /**
- * Copy a {@link Dictionary} into an {@link Attributes}.
- */
- public static void copy(Dictionary<String, Object> dictionary, Attributes attributes) {
- AttributesDictionary ad = new AttributesDictionary(attributes);
- Enumeration<String> keys = dictionary.keys();
- while (keys.hasMoreElements()) {
- String key = keys.nextElement();
- ad.put(key, dictionary.get(key));
- }
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.StringTokenizer;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.argeo.util.naming.LdapAttrs;
-
-/** LDAP authPassword field according to RFC 3112 */
-public class AuthPassword implements CallbackHandler {
- private final String authScheme;
- private final String authInfo;
- private final String authValue;
-
- public AuthPassword(String value) {
- StringTokenizer st = new StringTokenizer(value, "$");
- // TODO make it more robust, deal with bad formatting
- this.authScheme = st.nextToken().trim();
- this.authInfo = st.nextToken().trim();
- this.authValue = st.nextToken().trim();
-
- String expectedAuthScheme = getExpectedAuthScheme();
- if (expectedAuthScheme != null && !authScheme.equals(expectedAuthScheme))
- throw new IllegalArgumentException(
- "Auth scheme " + authScheme + " is not compatible with " + expectedAuthScheme);
- }
-
- protected AuthPassword(String authInfo, String authValue) {
- this.authScheme = getExpectedAuthScheme();
- if (authScheme == null)
- throw new IllegalArgumentException("Expected auth scheme cannot be null");
- this.authInfo = authInfo;
- this.authValue = authValue;
- }
-
- protected AuthPassword(AuthPassword authPassword) {
- this.authScheme = authPassword.getAuthScheme();
- this.authInfo = authPassword.getAuthInfo();
- this.authValue = authPassword.getAuthValue();
- }
-
- protected String getExpectedAuthScheme() {
- return null;
- }
-
- protected boolean matchAuthValue(Object object) {
- return authValue.equals(object.toString());
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof AuthPassword))
- return false;
- AuthPassword authPassword = (AuthPassword) obj;
- return authScheme.equals(authPassword.authScheme) && authInfo.equals(authPassword.authInfo)
- && authValue.equals(authValue);
- }
-
- public boolean keyEquals(AuthPassword authPassword) {
- return authScheme.equals(authPassword.authScheme) && authInfo.equals(authPassword.authInfo);
- }
-
- @Override
- public int hashCode() {
- return authValue.hashCode();
- }
-
- @Override
- public String toString() {
- return toAuthPassword();
- }
-
- public final String toAuthPassword() {
- return getAuthScheme() + '$' + authInfo + '$' + authValue;
- }
-
- public String getAuthScheme() {
- return authScheme;
- }
-
- public String getAuthInfo() {
- return authInfo;
- }
-
- public String getAuthValue() {
- return authValue;
- }
-
- public static AuthPassword matchAuthValue(Attributes attributes, char[] value) {
- try {
- Attribute authPassword = attributes.get(LdapAttrs.authPassword.name());
- if (authPassword != null) {
- NamingEnumeration<?> values = authPassword.getAll();
- while (values.hasMore()) {
- Object val = values.next();
- AuthPassword token = new AuthPassword(val.toString());
- String auth;
- if (Arrays.binarySearch(value, '$') >= 0) {
- auth = token.authInfo + '$' + token.authValue;
- } else {
- auth = token.authValue;
- }
- if (Arrays.equals(auth.toCharArray(), value))
- return token;
- // if (token.matchAuthValue(value))
- // return token;
- }
- }
- return null;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot check attribute", e);
- }
- }
-
- public static boolean remove(Attributes attributes, AuthPassword value) {
- Attribute authPassword = attributes.get(LdapAttrs.authPassword.name());
- return authPassword.remove(value.toAuthPassword());
- }
-
- @Override
- public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
- for (Callback callback : callbacks) {
- if (callback instanceof NameCallback)
- ((NameCallback) callback).setName(toAuthPassword());
- else if (callback instanceof PasswordCallback)
- ((PasswordCallback) callback).setPassword(getAuthValue().toCharArray());
- }
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import static java.nio.charset.StandardCharsets.US_ASCII;
-
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.StringJoiner;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.DirectoryDigestUtils;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
-
-/** An entry in an LDAP (or LDIF) directory. */
-public class DefaultLdapEntry implements LdapEntry {
- private final AbstractLdapDirectory directory;
-
- private final LdapName dn;
-
-// private Attributes publishedAttributes;
-
- // Temporarily expose the fields
- private AttributeDictionary properties;
- private AttributeDictionary credentials;
-
- protected DefaultLdapEntry(AbstractLdapDirectory directory, LdapName dn) {
- Objects.requireNonNull(directory);
- Objects.requireNonNull(dn);
- this.directory = directory;
- this.dn = dn;
-// this.publishedAttributes = attributes;
-// properties = new AttributeDictionary(false);
-// credentials = new AttributeDictionary(true);
- }
-
- @Override
- public LdapName getDn() {
- return dn;
- }
-
- public synchronized Attributes getAttributes() {
-// // lazy loading
-// if (publishedAttributes == null)
-// publishedAttributes = getDirectory().getDirectoryDao().doGetAttributes(dn);
- return isEditing() ? getModifiedAttributes() : getDirectory().getDirectoryDao().doGetAttributes(dn);
- }
-
- @Override
- public List<LdapName> getReferences(String attributeId) {
- Attribute memberAttribute = getAttributes().get(attributeId);
- if (memberAttribute == null)
- return new ArrayList<LdapName>();
- try {
- List<LdapName> roles = new ArrayList<LdapName>();
- NamingEnumeration<?> values = memberAttribute.getAll();
- while (values.hasMore()) {
- LdapName dn = new LdapName(values.next().toString());
- roles.add(dn);
- }
- return roles;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get members", e);
- }
-
- }
-
- /** Should only be called from working copy thread. */
- protected synchronized Attributes getModifiedAttributes() {
- assert getWc() != null;
- return getWc().getModifiedData().get(getDn());
- }
-
- protected synchronized boolean isEditing() {
- return getWc() != null && getModifiedAttributes() != null;
- }
-
- private synchronized LdapEntryWorkingCopy getWc() {
- return directory.getWorkingCopy();
- }
-
- protected synchronized void startEditing() {
-// if (frozen)
-// throw new IllegalStateException("Cannot edit frozen view");
- if (directory.isReadOnly())
- throw new IllegalStateException("User directory is read-only");
- assert getModifiedAttributes() == null;
- getWc().startEditing(this);
- // modifiedAttributes = (Attributes) publishedAttributes.clone();
- }
-
- public synchronized void publishAttributes(Attributes modifiedAttributes) {
-// publishedAttributes = modifiedAttributes;
- }
-
- /*
- * PROPERTIES
- */
- @Override
- public Dictionary<String, Object> getProperties() {
- if (properties == null)
- properties = new AttributeDictionary(false);
- return properties;
- }
-
- public Dictionary<String, Object> getCredentials() {
- if (credentials == null)
- credentials = new AttributeDictionary(true);
- return credentials;
- }
-
- /*
- * CREDENTIALS
- */
- @Override
- public boolean hasCredential(String key, Object value) {
- if (key == null) {
- // TODO check other sources (like PKCS12)
- // String pwd = new String((char[]) value);
- // authPassword (RFC 312 https://tools.ietf.org/html/rfc3112)
- char[] password = DirectoryDigestUtils.bytesToChars(value);
-
- if (getDirectory().getForcedPassword() != null
- && getDirectory().getForcedPassword().equals(new String(password)))
- return true;
-
- AuthPassword authPassword = AuthPassword.matchAuthValue(getAttributes(), password);
- if (authPassword != null) {
- if (authPassword.getAuthScheme().equals(SharedSecret.X_SHARED_SECRET)) {
- SharedSecret onceToken = new SharedSecret(authPassword);
- if (onceToken.isExpired()) {
- // AuthPassword.remove(getAttributes(), onceToken);
- return false;
- } else {
- // boolean wasRemoved = AuthPassword.remove(getAttributes(), onceToken);
- return true;
- }
- // TODO delete expired tokens?
- } else {
- // TODO implement SHA
- throw new UnsupportedOperationException(
- "Unsupported authPassword scheme " + authPassword.getAuthScheme());
- }
- }
-
- // Regular password
-// byte[] hashedPassword = hash(password, DigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256);
- if (hasCredential(LdapAttrs.userPassword.name(), DirectoryDigestUtils.charsToBytes(password)))
- return true;
- return false;
- }
-
- Object storedValue = getCredentials().get(key);
- if (storedValue == null || value == null)
- return false;
- if (!(value instanceof String || value instanceof byte[]))
- return false;
- if (storedValue instanceof String && value instanceof String)
- return storedValue.equals(value);
- if (storedValue instanceof byte[] && value instanceof byte[]) {
- String storedBase64 = new String((byte[]) storedValue, US_ASCII);
- String passwordScheme = null;
- if (storedBase64.charAt(0) == '{') {
- int index = storedBase64.indexOf('}');
- if (index > 0) {
- passwordScheme = storedBase64.substring(1, index);
- String storedValueBase64 = storedBase64.substring(index + 1);
- byte[] storedValueBytes = Base64.getDecoder().decode(storedValueBase64);
- char[] passwordValue = DirectoryDigestUtils.bytesToChars((byte[]) value);
- byte[] valueBytes;
- if (DirectoryDigestUtils.PASSWORD_SCHEME_SHA.equals(passwordScheme)) {
- valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, null, null,
- null);
- } else if (DirectoryDigestUtils.PASSWORD_SCHEME_PBKDF2_SHA256.equals(passwordScheme)) {
- // see https://www.thesubtlety.com/post/a-389-ds-pbkdf2-password-checker/
- byte[] iterationsArr = Arrays.copyOfRange(storedValueBytes, 0, 4);
- BigInteger iterations = new BigInteger(iterationsArr);
- byte[] salt = Arrays.copyOfRange(storedValueBytes, iterationsArr.length,
- iterationsArr.length + 64);
- byte[] keyArr = Arrays.copyOfRange(storedValueBytes, iterationsArr.length + salt.length,
- storedValueBytes.length);
- int keyLengthBits = keyArr.length * 8;
- valueBytes = DirectoryDigestUtils.toPasswordScheme(passwordScheme, passwordValue, salt,
- iterations.intValue(), keyLengthBits);
- } else {
- throw new UnsupportedOperationException("Unknown password scheme " + passwordScheme);
- }
- return Arrays.equals(storedValueBytes, valueBytes);
- }
- }
- }
-// if (storedValue instanceof byte[] && value instanceof byte[]) {
-// return Arrays.equals((byte[]) storedValue, (byte[]) value);
-// }
- return false;
- }
-
- /** Hash the password */
- private static byte[] sha1hash(char[] password) {
- byte[] hashedPassword = ("{SHA}" + Base64.getEncoder()
- .encodeToString(DirectoryDigestUtils.sha1(DirectoryDigestUtils.charsToBytes(password))))
- .getBytes(StandardCharsets.UTF_8);
- return hashedPassword;
- }
-
- public AbstractLdapDirectory getDirectory() {
- return directory;
- }
-
- public LdapDirectoryDao getDirectoryDao() {
- return directory.getDirectoryDao();
- }
-
- @Override
- public int hashCode() {
- return dn.hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj instanceof LdapEntry) {
- LdapEntry that = (LdapEntry) obj;
- return this.dn.equals(that.getDn());
- }
- return false;
- }
-
- @Override
- public String toString() {
- return dn.toString();
- }
-
- private static boolean isAsciiPrintable(String str) {
- if (str == null) {
- return false;
- }
- int sz = str.length();
- for (int i = 0; i < sz; i++) {
- if (isAsciiPrintable(str.charAt(i)) == false) {
- return false;
- }
- }
- return true;
- }
-
- private static boolean isAsciiPrintable(char ch) {
- return ch >= 32 && ch < 127;
- }
-
- protected class AttributeDictionary extends Dictionary<String, Object> {
- private final List<String> effectiveKeys = new ArrayList<String>();
- private final List<String> attrFilter;
- private final Boolean includeFilter;
-
- public AttributeDictionary(Boolean credentials) {
- this.attrFilter = getDirectory().getCredentialAttributeIds();
- this.includeFilter = credentials;
- try {
- NamingEnumeration<String> ids = getAttributes().getIDs();
- while (ids.hasMore()) {
- String id = ids.next();
- if (credentials && attrFilter.contains(id))
- effectiveKeys.add(id);
- else if (!credentials && !attrFilter.contains(id))
- effectiveKeys.add(id);
- }
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot initialise attribute dictionary", e);
- }
- if (!credentials)
- effectiveKeys.add(LdapAttrs.objectClasses.name());
- }
-
- @Override
- public int size() {
- return effectiveKeys.size();
- }
-
- @Override
- public boolean isEmpty() {
- return effectiveKeys.size() == 0;
- }
-
- @Override
- public Enumeration<String> keys() {
- return Collections.enumeration(effectiveKeys);
- }
-
- @Override
- public Enumeration<Object> elements() {
- final Iterator<String> it = effectiveKeys.iterator();
- return new Enumeration<Object>() {
-
- @Override
- public boolean hasMoreElements() {
- return it.hasNext();
- }
-
- @Override
- public Object nextElement() {
- String key = it.next();
- return get(key);
- }
-
- };
- }
-
- @Override
- public Object get(Object key) {
- try {
- Attribute attr = !key.equals(LdapAttrs.objectClasses.name()) ? getAttributes().get(key.toString())
- : getAttributes().get(LdapAttrs.objectClass.name());
- if (attr == null)
- return null;
- Object value = attr.get();
- if (value instanceof byte[]) {
- if (key.equals(LdapAttrs.userPassword.name()))
- // TODO other cases (certificates, images)
- return value;
- value = new String((byte[]) value, StandardCharsets.UTF_8);
- }
- if (attr.size() == 1)
- return value;
- // special case for object class
- if (key.equals(LdapAttrs.objectClass.name())) {
- // TODO support multiple object classes
- NamingEnumeration<?> en = attr.getAll();
- String first = null;
- attrs: while (en.hasMore()) {
- String v = en.next().toString();
- if (v.equalsIgnoreCase(LdapObjs.top.name()))
- continue attrs;
- if (first == null)
- first = v;
- if (v.equalsIgnoreCase(getDirectory().getUserObjectClass()))
- return getDirectory().getUserObjectClass();
- else if (v.equalsIgnoreCase(getDirectory().getGroupObjectClass()))
- return getDirectory().getGroupObjectClass();
- }
- if (first != null)
- return first;
- throw new IllegalStateException("Cannot find objectClass in " + value);
- } else {
- NamingEnumeration<?> en = attr.getAll();
- StringJoiner values = new StringJoiner("\n");
- while (en.hasMore()) {
- String v = en.next().toString();
- values.add(v);
- }
- return values.toString();
- }
-// else
-// return value;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get value for attribute " + key, e);
- }
- }
-
- @Override
- public Object put(String key, Object value) {
- Objects.requireNonNull(value, "Value for key " + key + " is null");
- try {
- if (key == null) {
- // FIXME remove this "feature", a key should be specified
- // TODO persist to other sources (like PKCS12)
- char[] password = DirectoryDigestUtils.bytesToChars(value);
- byte[] hashedPassword = sha1hash(password);
- return put(LdapAttrs.userPassword.name(), hashedPassword);
- }
- if (key.startsWith("X-")) {
- return put(LdapAttrs.authPassword.name(), value);
- }
-
- // start editing
- getDirectory().checkEdit();
- if (!isEditing())
- startEditing();
-
- // object classes special case.
- if (key.equals(LdapAttrs.objectClasses.name())) {
- Attribute attribute = new BasicAttribute(LdapAttrs.objectClass.name());
- String[] objectClasses = value.toString().split("\n");
- for (String objectClass : objectClasses) {
- if (objectClass.trim().equals(""))
- continue;
- attribute.add(objectClass);
- }
- Attribute previousAttribute = getModifiedAttributes().put(attribute);
- if (previousAttribute != null)
- return previousAttribute.get();
- else
- return null;
- }
-
- if (!(value instanceof String || value instanceof byte[]))
- throw new IllegalArgumentException("Value must be String or byte[]");
-
- if (includeFilter && !attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " not included");
- else if (!includeFilter && attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " excluded");
-
- Attribute attribute = getModifiedAttributes().get(key.toString());
- // if (attribute == null) // block unit tests
- attribute = new BasicAttribute(key.toString());
- if (value instanceof String && !isAsciiPrintable(((String) value)))
- attribute.add(((String) value).getBytes(StandardCharsets.UTF_8));
- else
- attribute.add(value);
- Attribute previousAttribute = getModifiedAttributes().put(attribute);
- if (previousAttribute != null)
- return previousAttribute.get();
- else
- return null;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get value for attribute " + key, e);
- }
- }
-
- @Override
- public Object remove(Object key) {
- getDirectory().checkEdit();
- if (!isEditing())
- startEditing();
-
- if (includeFilter && !attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " not included");
- else if (!includeFilter && attrFilter.contains(key))
- throw new IllegalArgumentException("Key " + key + " excluded");
-
- try {
- Attribute attr = getModifiedAttributes().remove(key.toString());
- if (attr != null)
- return attr.get();
- else
- return null;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot remove attribute " + key, e);
- }
- }
-
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.List;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-import org.argeo.util.directory.DirectoryConf;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.dns.DnsBrowser;
-
-/** Free IPA specific conventions. */
-public class IpaUtils {
- public final static String IPA_USER_BASE = "cn=users";
- public final static String IPA_GROUP_BASE = "cn=groups";
- public final static String IPA_ROLE_BASE = "cn=roles";
- public final static String IPA_SERVICE_BASE = "cn=services,cn=accounts";
-
- public final static Rdn IPA_ACCOUNTS_RDN;
- static {
- try {
- IPA_ACCOUNTS_RDN = new Rdn(LdapAttrs.cn.name(), "accounts");
- } catch (InvalidNameException e) {
- // should not happen
- throw new IllegalStateException(e);
- }
- }
-
- private final static String KRB_PRINCIPAL_NAME = LdapAttrs.krbPrincipalName.name().toLowerCase();
-
- public final static String IPA_USER_DIRECTORY_CONFIG = DirectoryConf.userBase + "=" + IPA_USER_BASE + "&"
- + DirectoryConf.groupBase + "=" + IPA_GROUP_BASE + "&" + DirectoryConf.systemRoleBase + "=" + IPA_ROLE_BASE
- + "&" + DirectoryConf.readOnly + "=true";
-
- @Deprecated
- static String domainToUserDirectoryConfigPath(String realm) {
- return domainToBaseDn(realm) + "?" + IPA_USER_DIRECTORY_CONFIG + "&" + DirectoryConf.realm.name() + "=" + realm;
- }
-
- public static void addIpaConfig(String realm, Dictionary<String, Object> properties) {
- properties.put(DirectoryConf.baseDn.name(), domainToBaseDn(realm));
- properties.put(DirectoryConf.realm.name(), realm);
- properties.put(DirectoryConf.userBase.name(), IPA_USER_BASE);
- properties.put(DirectoryConf.groupBase.name(), IPA_GROUP_BASE);
- properties.put(DirectoryConf.systemRoleBase.name(), IPA_ROLE_BASE);
- properties.put(DirectoryConf.readOnly.name(), Boolean.TRUE.toString());
- }
-
- public static String domainToBaseDn(String domain) {
- String[] dcs = domain.split("\\.");
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < dcs.length; i++) {
- if (i != 0)
- sb.append(',');
- String dc = dcs[i];
- sb.append(LdapAttrs.dc.name()).append('=').append(dc.toLowerCase());
- }
- return sb.toString();
- }
-
- public static LdapName kerberosToDn(String kerberosName) {
- String[] kname = kerberosName.split("@");
- String username = kname[0];
- String baseDn = domainToBaseDn(kname[1]);
- String dn;
- if (!username.contains("/"))
- dn = LdapAttrs.uid + "=" + username + "," + IPA_USER_BASE + "," + IPA_ACCOUNTS_RDN + "," + baseDn;
- else
- dn = KRB_PRINCIPAL_NAME + "=" + kerberosName + "," + IPA_SERVICE_BASE + "," + baseDn;
- try {
- return new LdapName(dn);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Badly formatted name for " + kerberosName + ": " + dn);
- }
- }
-
- private IpaUtils() {
-
- }
-
- public static String kerberosDomainFromDns() {
- String kerberosDomain;
- try (DnsBrowser dnsBrowser = new DnsBrowser()) {
- InetAddress localhost = InetAddress.getLocalHost();
- String hostname = localhost.getHostName();
- String dnsZone = hostname.substring(hostname.indexOf('.') + 1);
- kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT");
- return kerberosDomain;
- } catch (IOException e) {
- throw new IllegalStateException("Cannot determine Kerberos domain from DNS", e);
- }
-
- }
-
- public static Dictionary<String, Object> convertIpaUri(URI uri) {
- String path = uri.getPath();
- String kerberosRealm;
- if (path == null || path.length() <= 1) {
- kerberosRealm = kerberosDomainFromDns();
- } else {
- kerberosRealm = path.substring(1);
- }
-
- if (kerberosRealm == null)
- throw new IllegalStateException("No Kerberos domain available for " + uri);
- // TODO intergrate CA certificate in truststore
- // String schemeToUse = SCHEME_LDAPS;
- String schemeToUse = DirectoryConf.SCHEME_LDAP;
- List<String> ldapHosts;
- String ldapHostsStr = uri.getHost();
- if (ldapHostsStr == null || ldapHostsStr.trim().equals("")) {
- try (DnsBrowser dnsBrowser = new DnsBrowser()) {
- ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase(),
- schemeToUse.equals(DirectoryConf.SCHEME_LDAP) ? true : false);
- if (ldapHosts == null || ldapHosts.size() == 0) {
- throw new IllegalStateException("Cannot configure LDAP for IPA " + uri);
- } else {
- ldapHostsStr = ldapHosts.get(0);
- }
- } catch (IOException e) {
- throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
- }
- } else {
- ldapHosts = new ArrayList<>();
- ldapHosts.add(ldapHostsStr);
- }
-
- StringBuilder uriStr = new StringBuilder();
- try {
- for (String host : ldapHosts) {
- URI convertedUri = new URI(schemeToUse + "://" + host + "/");
- uriStr.append(convertedUri).append(' ');
- }
- } catch (URISyntaxException e) {
- throw new IllegalStateException("Cannot convert IPA uri " + uri, e);
- }
-
- Hashtable<String, Object> res = new Hashtable<>();
- res.put(DirectoryConf.uri.name(), uriStr.toString());
- addIpaConfig(kerberosRealm, res);
- return res;
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import javax.naming.CommunicationException;
-import javax.naming.Context;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.InitialLdapContext;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.transaction.WorkingCopy;
-
-/** A synchronized wrapper for a single {@link InitialLdapContext}. */
-// TODO implement multiple contexts and connection pooling.
-public class LdapConnection {
- private InitialLdapContext initialLdapContext = null;
-
- public LdapConnection(String url, Dictionary<String, ?> properties) {
- try {
- Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
- connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
- connEnv.put(Context.PROVIDER_URL, url);
- connEnv.put("java.naming.ldap.attributes.binary", LdapAttrs.userPassword.name());
- // use pooling in order to avoid connection timeout
-// connEnv.put("com.sun.jndi.ldap.connect.pool", "true");
-// connEnv.put("com.sun.jndi.ldap.connect.pool.timeout", 300000);
-
- initialLdapContext = new InitialLdapContext(connEnv, null);
- // StartTlsResponse tls = (StartTlsResponse) ctx
- // .extendedOperation(new StartTlsRequest());
- // tls.negotiate();
- Object securityAuthentication = properties.get(Context.SECURITY_AUTHENTICATION);
- if (securityAuthentication != null)
- initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, securityAuthentication);
- else
- initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
- Object principal = properties.get(Context.SECURITY_PRINCIPAL);
- if (principal != null) {
- initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString());
- Object creds = properties.get(Context.SECURITY_CREDENTIALS);
- if (creds != null) {
- initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
- }
- }
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot connect to LDAP", e);
- }
-
- }
-
- public void init() {
-
- }
-
- public void destroy() {
- try {
- // tls.close();
- initialLdapContext.close();
- initialLdapContext = null;
- } catch (NamingException e) {
- e.printStackTrace();
- }
- }
-
- protected InitialLdapContext getLdapContext() {
- return initialLdapContext;
- }
-
- protected void reconnect() throws NamingException {
- initialLdapContext.reconnect(initialLdapContext.getConnectControls());
- }
-
- public synchronized NamingEnumeration<SearchResult> search(LdapName searchBase, String searchFilter,
- SearchControls searchControls) throws NamingException {
- NamingEnumeration<SearchResult> results;
- try {
- results = getLdapContext().search(searchBase, searchFilter, searchControls);
- } catch (CommunicationException e) {
- reconnect();
- results = getLdapContext().search(searchBase, searchFilter, searchControls);
- }
- return results;
- }
-
- public synchronized Attributes getAttributes(LdapName name) throws NamingException {
- try {
- return getLdapContext().getAttributes(name);
- } catch (CommunicationException e) {
- reconnect();
- return getLdapContext().getAttributes(name);
- }
- }
-
- public synchronized boolean entryExists(LdapName name) throws NamingException {
- String[] noAttrOID = new String[] { "1.1" };
- try {
- getLdapContext().getAttributes(name, noAttrOID);
- return true;
- } catch (CommunicationException e) {
- reconnect();
- getLdapContext().getAttributes(name, noAttrOID);
- return true;
- } catch (NameNotFoundException e) {
- return false;
- }
- }
-
- public synchronized void prepareChanges(WorkingCopy<?, ?, LdapName> wc) throws NamingException {
- // make sure connection will work
- reconnect();
-
- // delete
- for (LdapName dn : wc.getDeletedData().keySet()) {
- if (!entryExists(dn))
- throw new IllegalStateException("User to delete no found " + dn);
- }
- // add
- for (LdapName dn : wc.getNewData().keySet()) {
- if (entryExists(dn))
- throw new IllegalStateException("User to create found " + dn);
- }
- // modify
- for (LdapName dn : wc.getModifiedData().keySet()) {
- if (!wc.getNewData().containsKey(dn) && !entryExists(dn))
- throw new IllegalStateException("User to modify not found " + dn);
- }
-
- }
-
-// protected boolean entryExists(LdapName dn) throws NamingException {
-// try {
-// return getAttributes(dn).size() != 0;
-// } catch (NameNotFoundException e) {
-// return false;
-// }
-// }
-
- public synchronized void commitChanges(LdapEntryWorkingCopy wc) throws NamingException {
- // delete
- for (LdapName dn : wc.getDeletedData().keySet()) {
- getLdapContext().destroySubcontext(dn);
- }
- // add
- for (LdapName dn : wc.getNewData().keySet()) {
- LdapEntry user = wc.getNewData().get(dn);
- getLdapContext().createSubcontext(dn, user.getAttributes());
- }
- // modify
- for (LdapName dn : wc.getModifiedData().keySet()) {
- Attributes modifiedAttrs = wc.getModifiedData().get(dn);
- getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
- }
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import static org.argeo.util.naming.LdapAttrs.objectClass;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.naming.AuthenticationNotSupportedException;
-import javax.naming.Binding;
-import javax.naming.InvalidNameException;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.directory.SearchControls;
-import javax.naming.directory.SearchResult;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
-
-/** A user admin based on a LDAP server. */
-public class LdapDao extends AbstractLdapDirectoryDao {
- private LdapConnection ldapConnection;
-
- public LdapDao(AbstractLdapDirectory directory) {
- super(directory);
- }
-
- @Override
- public void init() {
- ldapConnection = new LdapConnection(getDirectory().getUri().toString(), getDirectory().cloneConfigProperties());
- }
-
- public void destroy() {
- ldapConnection.destroy();
- }
-
- @Override
- public boolean checkConnection() {
- try {
- return ldapConnection.entryExists(getDirectory().getBaseDn());
- } catch (NamingException e) {
- return false;
- }
- }
-
- @Override
- public boolean entryExists(LdapName dn) {
- try {
- return ldapConnection.entryExists(dn);
- } catch (NameNotFoundException e) {
- return false;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot check " + dn, e);
- }
- }
-
- @Override
- public LdapEntry doGetEntry(LdapName name) throws NameNotFoundException {
-// if (!entryExists(name))
-// throw new NameNotFoundException(name + " was not found in " + getDirectory().getBaseDn());
- try {
- Attributes attrs = ldapConnection.getAttributes(name);
-
- LdapEntry res;
- Rdn technicalRdn = LdapNameUtils.getParentRdn(name);
- if (getDirectory().getGroupBaseRdn().equals(technicalRdn)) {
- if (attrs.size() == 0) {// exists but not accessible
- attrs = new BasicAttributes();
- attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
- attrs.put(LdapAttrs.objectClass.name(), getDirectory().getGroupObjectClass());
- }
- res = newGroup(name);
- } else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn)) {
- if (attrs.size() == 0) {// exists but not accessible
- attrs = new BasicAttributes();
- attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
- attrs.put(LdapAttrs.objectClass.name(), getDirectory().getGroupObjectClass());
- }
- res = newGroup(name);
- } else if (getDirectory().getUserBaseRdn().equals(technicalRdn)) {
- if (attrs.size() == 0) {// exists but not accessible
- attrs = new BasicAttributes();
- attrs.put(LdapAttrs.objectClass.name(), LdapObjs.top.name());
- attrs.put(LdapAttrs.objectClass.name(), getDirectory().getUserObjectClass());
- }
- res = newUser(name);
- } else {
- res = new DefaultLdapEntry(getDirectory(), name);
- }
- return res;
- } catch (NameNotFoundException e) {
- throw e;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot retrieve entry " + name, e);
- }
- }
-
- @Override
- public Attributes doGetAttributes(LdapName name) {
- try {
- Attributes attrs = ldapConnection.getAttributes(name);
- return attrs;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get attributes for " + name);
- }
- }
-
- @Override
- public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
- ArrayList<LdapEntry> res = new ArrayList<>();
- try {
- String searchFilter = f != null ? f.toString()
- : "(|(" + objectClass.name() + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass.name()
- + "=" + getDirectory().getGroupObjectClass() + "))";
- SearchControls searchControls = new SearchControls();
- // only attribute needed is objectClass
- searchControls.setReturningAttributes(new String[] { objectClass.name() });
- // FIXME make one level consistent with deep
- searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
-
- // LdapName searchBase = getBaseDn();
- NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
-
- results: while (results.hasMoreElements()) {
- SearchResult searchResult = results.next();
- Attributes attrs = searchResult.getAttributes();
- Attribute objectClassAttr = attrs.get(objectClass.name());
- LdapName dn = toDn(searchBase, searchResult);
- LdapEntry role;
- if (objectClassAttr.contains(getDirectory().getGroupObjectClass())
- || objectClassAttr.contains(getDirectory().getGroupObjectClass().toLowerCase()))
- role = newGroup(dn);
- else if (objectClassAttr.contains(getDirectory().getUserObjectClass())
- || objectClassAttr.contains(getDirectory().getUserObjectClass().toLowerCase()))
- role = newUser(dn);
- else {
-// log.warn("Unsupported LDAP type for " + searchResult.getName());
- continue results;
- }
- res.add(role);
- }
- return res;
- } catch (AuthenticationNotSupportedException e) {
- // ignore (typically an unsupported anonymous bind)
- // TODO better logging
- return res;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get roles for filter " + f, e);
- }
- }
-
- private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException {
- return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName());
- }
-
- @Override
- public List<LdapName> getDirectGroups(LdapName dn) {
- List<LdapName> directGroups = new ArrayList<LdapName>();
- try {
- String searchFilter = "(&(" + objectClass + "=" + getDirectory().getGroupObjectClass() + ")("
- + getDirectory().getMemberAttributeId() + "=" + dn + "))";
-
- SearchControls searchControls = new SearchControls();
- searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
-
- LdapName searchBase = getDirectory().getBaseDn();
- NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
-
- while (results.hasMoreElements()) {
- SearchResult searchResult = (SearchResult) results.nextElement();
- directGroups.add(toDn(searchBase, searchResult));
- }
- return directGroups;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot populate direct members of " + dn, e);
- }
- }
-
- @Override
- public void prepare(LdapEntryWorkingCopy wc) {
- try {
- ldapConnection.prepareChanges(wc);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot prepare LDAP", e);
- }
- }
-
- @Override
- public void commit(LdapEntryWorkingCopy wc) {
- try {
- ldapConnection.commitChanges(wc);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot commit LDAP", e);
- }
- }
-
- @Override
- public void rollback(LdapEntryWorkingCopy wc) {
- // prepare not impacting
- }
-
- /*
- * HIERARCHY
- */
-
- @Override
- public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
- List<HierarchyUnit> res = new ArrayList<>();
- try {
- String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
- + "=" + LdapObjs.organization.name() + "))";
-// String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
-// + "=" + LdapObjs.organization.name() + ")(cn=accounts)(cn=users)(cn=groups))";
-
- SearchControls searchControls = new SearchControls();
- searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
- // no attributes needed
- searchControls.setReturningAttributes(new String[0]);
-
- NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
-
- while (results.hasMoreElements()) {
- SearchResult searchResult = (SearchResult) results.nextElement();
- LdapName dn = toDn(searchBase, searchResult);
-// Attributes attrs = searchResult.getAttributes();
- LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn);
- if (functionalOnly) {
- if (hierarchyUnit.isFunctional())
- res.add(hierarchyUnit);
- } else {
- res.add(hierarchyUnit);
- }
- }
- return res;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get direct hierarchy units ", e);
- }
- }
-
- @Override
- public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
- try {
- if (getDirectory().getBaseDn().equals(dn))
- return getDirectory();
- if (!dn.startsWith(getDirectory().getBaseDn()))
- throw new IllegalArgumentException(dn + " does not start with base DN " + getDirectory().getBaseDn());
- if (!ldapConnection.entryExists(dn))
- return null;
- return new LdapHierarchyUnit(getDirectory(), dn);
- } catch (NameNotFoundException e) {
- return null;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
- }
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.util.List;
-
-import javax.naming.NameNotFoundException;
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.transaction.WorkingCopyProcessor;
-
-public interface LdapDirectoryDao extends WorkingCopyProcessor<LdapEntryWorkingCopy> {
- boolean checkConnection();
-
- boolean entryExists(LdapName dn);
-
- LdapEntry doGetEntry(LdapName name) throws NameNotFoundException;
-
- Attributes doGetAttributes(LdapName name);
-
- List<LdapEntry> doGetEntries(LdapName searchBase, String filter, boolean deep);
-
- List<LdapName> getDirectGroups(LdapName dn);
-
- Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly);
-
- HierarchyUnit doGetHierarchyUnit(LdapName dn);
-
- LdapEntry newUser(LdapName name);
-
- LdapEntry newGroup(LdapName name);
-
- void init();
-
- void destroy();
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Dictionary;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.StringJoiner;
-import java.util.TreeSet;
-
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.naming.LdapAttrs;
-
-/** An LDAP entry. */
-public interface LdapEntry {
- LdapName getDn();
-
- Attributes getAttributes();
-
- void publishAttributes(Attributes modifiedAttributes);
-
- List<LdapName> getReferences(String attributeId);
-
- Dictionary<String, Object> getProperties();
-
- boolean hasCredential(String key, Object value);
-
- /*
- * UTILITIES
- */
- /**
- * Convert a collection of object classes to the format expected by an LDAP
- * backend.
- */
- public static void addObjectClasses(Dictionary<String, Object> properties, Collection<String> objectClasses) {
- String value = properties.get(LdapAttrs.objectClasses.name()).toString();
- Set<String> currentObjectClasses = new TreeSet<>(Arrays.asList(value.toString().split("\n")));
- currentObjectClasses.addAll(objectClasses);
- StringJoiner values = new StringJoiner("\n");
- currentObjectClasses.forEach((s) -> values.add(s));
- properties.put(LdapAttrs.objectClasses.name(), values.toString());
- }
-
- public static Object getLocalized(Dictionary<String, Object> properties, String key, Locale locale) {
- if (locale == null)
- return null;
- Object value = null;
- value = properties.get(key + ";lang-" + locale.getLanguage() + "-" + locale.getCountry());
- if (value == null)
- value = properties.get(key + ";lang-" + locale.getLanguage());
- return value;
- }
-
- public static String toLocalizedKey(String key, Locale locale) {
- String country = locale.getCountry();
- if ("".equals(country)) {
- return key + ";lang-" + locale.getLanguage();
- } else {
- return key + ";lang-" + locale.getLanguage() + "-" + locale.getCountry();
- }
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.transaction.AbstractWorkingCopy;
-
-/** Working copy for a user directory being edited. */
-public class LdapEntryWorkingCopy extends AbstractWorkingCopy<LdapEntry, Attributes, LdapName> {
- @Override
- protected LdapName getId(LdapEntry entry) {
- return entry.getDn();
- }
-
- @Override
- protected Attributes cloneAttributes(LdapEntry entry) {
- return (Attributes) entry.getAttributes().clone();
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.util.Locale;
-
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-import org.argeo.util.directory.HierarchyUnit;
-
-/** LDIF/LDAP based implementation of {@link HierarchyUnit}. */
-public class LdapHierarchyUnit extends DefaultLdapEntry implements HierarchyUnit {
- private final boolean functional;
-
- public LdapHierarchyUnit(AbstractLdapDirectory directory, LdapName dn) {
- super(directory, dn);
-
- Rdn rdn = LdapNameUtils.getLastRdn(dn);
- functional = !(directory.getUserBaseRdn().equals(rdn) || directory.getGroupBaseRdn().equals(rdn)
- || directory.getSystemRoleBaseRdn().equals(rdn));
- }
-
- @Override
- public HierarchyUnit getParent() {
- return getDirectoryDao().doGetHierarchyUnit(LdapNameUtils.getParent(getDn()));
- }
-
- @Override
- public Iterable<HierarchyUnit> getDirectHierarchyUnits(boolean functionalOnly) {
- return getDirectoryDao().doGetDirectHierarchyUnits(getDn(), functionalOnly);
- }
-
- @Override
- public boolean isFunctional() {
- return functional;
- }
-
- @Override
- public String getHierarchyUnitName() {
- String name = LdapNameUtils.getLastRdnValue(getDn());
- // TODO check ou, o, etc.
- return name;
- }
-
- @Override
- public String getHierarchyUnitLabel(Locale locale) {
- String key = LdapNameUtils.getLastRdn(getDn()).getType();
- Object value = LdapEntry.getLocalized(getProperties(), key, locale);
- if (value == null)
- value = getHierarchyUnitName();
- assert value != null;
- return value.toString();
- }
-
- @Override
- public String getBase() {
- return getDn().toString();
- }
-
- @Override
- public String toString() {
- return "Hierarchy Unit " + getDn().toString();
- }
-
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-/** Utilities to simplify using {@link LdapName}. */
-public class LdapNameUtils {
-
- public static LdapName relativeName(LdapName prefix, LdapName dn) {
- try {
- if (!dn.startsWith(prefix))
- throw new IllegalArgumentException("Prefix " + prefix + " not consistent with " + dn);
- LdapName res = (LdapName) dn.clone();
- for (int i = 0; i < prefix.size(); i++) {
- res.remove(0);
- }
- return res;
- } catch (InvalidNameException e) {
- throw new IllegalStateException("Cannot find realtive name", e);
- }
- }
-
- public static LdapName getParent(LdapName dn) {
- try {
- LdapName parent = (LdapName) dn.clone();
- parent.remove(parent.size() - 1);
- return parent;
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Cannot get parent of " + dn, e);
- }
- }
-
- public static Rdn getParentRdn(LdapName dn) {
- if (dn.size() < 2)
- throw new IllegalArgumentException(dn + " has no parent");
- Rdn parentRdn = dn.getRdn(dn.size() - 2);
- return parentRdn;
- }
-
- public static LdapName toLdapName(String distinguishedName) {
- try {
- return new LdapName(distinguishedName);
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Cannot parse " + distinguishedName + " as LDAP name", e);
- }
- }
-
- public static Rdn getLastRdn(LdapName dn) {
- return dn.getRdn(dn.size() - 1);
- }
-
- public static String getLastRdnAsString(LdapName dn) {
- return getLastRdn(dn).toString();
- }
-
- public static String getLastRdnValue(String dn) {
- return getLastRdnValue(toLdapName(dn));
- }
-
- public static String getLastRdnValue(LdapName dn) {
- return getLastRdn(dn).getValue().toString();
- }
-
- /** singleton */
- private LdapNameUtils() {
-
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import static org.argeo.util.naming.LdapAttrs.objectClass;
-import static org.argeo.util.naming.LdapObjs.inetOrgPerson;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.NavigableMap;
-import java.util.Objects;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-
-import org.argeo.util.directory.HierarchyUnit;
-import org.argeo.util.naming.LdapObjs;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Role;
-
-/** A user admin based on a LDIF files. */
-public class LdifDao extends AbstractLdapDirectoryDao {
- private NavigableMap<LdapName, LdapEntry> entries = new TreeMap<>();
- private NavigableMap<LdapName, LdapHierarchyUnit> hierarchy = new TreeMap<>();
-
- private NavigableMap<LdapName, Attributes> values = new TreeMap<>();
-
- public LdifDao(AbstractLdapDirectory directory) {
- super(directory);
- }
-
- public void init() {
- String uri = getDirectory().getUri();
- if (uri == null)
- return;
- try {
- URI u = new URI(uri);
- if (u.getScheme().equals("file")) {
- File file = new File(u);
- if (!file.exists())
- return;
- }
- load(u.toURL().openStream());
- } catch (IOException | URISyntaxException e) {
- throw new IllegalStateException("Cannot open URL " + getDirectory().getUri(), e);
- }
- }
-
- public void save() {
- if (getDirectory().getUri() == null)
- return; // ignore
- if (getDirectory().isReadOnly())
- throw new IllegalStateException(
- "Cannot save LDIF user admin: " + getDirectory().getUri() + " is read-only");
- try (FileOutputStream out = new FileOutputStream(new File(new URI(getDirectory().getUri())))) {
- save(out);
- } catch (IOException | URISyntaxException e) {
- throw new IllegalStateException("Cannot save user admin to " + getDirectory().getUri(), e);
- }
- }
-
- public void save(OutputStream out) throws IOException {
- try {
- LdifWriter ldifWriter = new LdifWriter(out);
- for (LdapName name : hierarchy.keySet())
- ldifWriter.writeEntry(name, hierarchy.get(name).getAttributes());
- for (LdapName name : entries.keySet())
- ldifWriter.writeEntry(name, entries.get(name).getAttributes());
- } finally {
- out.close();
- }
- }
-
- public void load(InputStream in) {
- try {
- entries.clear();
- hierarchy.clear();
-
- LdifParser ldifParser = new LdifParser();
- SortedMap<LdapName, Attributes> allEntries = ldifParser.read(in);
- for (LdapName key : allEntries.keySet()) {
- Attributes attributes = allEntries.get(key);
- // check for inconsistency
- Set<String> lowerCase = new HashSet<String>();
- NamingEnumeration<String> ids = attributes.getIDs();
- while (ids.hasMoreElements()) {
- String id = ids.nextElement().toLowerCase();
- if (lowerCase.contains(id))
- throw new IllegalStateException(key + " has duplicate id " + id);
- lowerCase.add(id);
- }
-
- values.put(key, attributes);
-
- // analyse object classes
- NamingEnumeration<?> objectClasses = attributes.get(objectClass.name()).getAll();
- // System.out.println(key);
- objectClasses: while (objectClasses.hasMore()) {
- String objectClass = objectClasses.next().toString();
- // System.out.println(" " + objectClass);
- if (objectClass.toLowerCase().equals(inetOrgPerson.name().toLowerCase())) {
- entries.put(key, newUser(key));
- break objectClasses;
- } else if (objectClass.toLowerCase().equals(getDirectory().getGroupObjectClass().toLowerCase())) {
- entries.put(key, newGroup(key));
- break objectClasses;
- } else if (objectClass.equalsIgnoreCase(LdapObjs.organizationalUnit.name())) {
- // TODO skip if it does not contain groups or users
- hierarchy.put(key, new LdapHierarchyUnit(getDirectory(), key));
- break objectClasses;
- }
- }
- }
-
- } catch (NamingException | IOException e) {
- throw new IllegalStateException("Cannot load user admin service from LDIF", e);
- }
- }
-
- public void destroy() {
-// if (users == null || groups == null)
- if (entries == null)
- throw new IllegalStateException("User directory " + getDirectory().getBaseDn() + " is already destroyed");
-// users = null;
-// groups = null;
- entries = null;
- }
-
- /*
- * USER ADMIN
- */
-
- @Override
- public LdapEntry doGetEntry(LdapName key) throws NameNotFoundException {
- if (entries.containsKey(key))
- return entries.get(key);
- throw new NameNotFoundException(key + " not persisted");
- }
-
- @Override
- public Attributes doGetAttributes(LdapName name) {
- if (!values.containsKey(name))
- throw new IllegalStateException(name + " doe not exist in " + getDirectory().getBaseDn());
- return values.get(name);
- }
-
- @Override
- public boolean checkConnection() {
- return true;
- }
-
- @Override
- public boolean entryExists(LdapName dn) {
- return entries.containsKey(dn);// || groups.containsKey(dn);
- }
-
- @Override
- public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
- Objects.requireNonNull(searchBase);
- ArrayList<LdapEntry> res = new ArrayList<>();
- if (f == null && deep && getDirectory().getBaseDn().equals(searchBase)) {
- res.addAll(entries.values());
- } else {
- filterRoles(entries, searchBase, f, deep, res);
- }
- return res;
- }
-
- private void filterRoles(SortedMap<LdapName, ? extends LdapEntry> map, LdapName searchBase, String f, boolean deep,
- List<LdapEntry> res) {
- // FIXME get rid of OSGi references
- try {
- // TODO reduce map with search base ?
- Filter filter = f != null ? FrameworkUtil.createFilter(f) : null;
- roles: for (LdapEntry user : map.values()) {
- LdapName dn = user.getDn();
- if (dn.startsWith(searchBase)) {
- if (!deep && dn.size() != (searchBase.size() + 1))
- continue roles;
- if (filter == null)
- res.add(user);
- else {
- if (user instanceof Role) {
- if (filter.match(((Role) user).getProperties()))
- res.add(user);
- }
- }
- }
- }
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Cannot create filter " + f, e);
- }
-
- }
-
- @Override
- public List<LdapName> getDirectGroups(LdapName dn) {
- List<LdapName> directGroups = new ArrayList<LdapName>();
- entries: for (LdapName name : entries.keySet()) {
- LdapEntry group;
- try {
- LdapEntry entry = doGetEntry(name);
- if (AbstractLdapDirectory.hasObjectClass(entry.getAttributes(), getDirectory().getGroupObjectClass())) {
- group = entry;
- } else {
- continue entries;
- }
- } catch (NameNotFoundException e) {
- throw new IllegalArgumentException("Group " + dn + " not found", e);
- }
- if (group.getReferences(getDirectory().getMemberAttributeId()).contains(dn)) {
- directGroups.add(group.getDn());
- }
- }
- return directGroups;
- }
-
- @Override
- public void prepare(LdapEntryWorkingCopy wc) {
- // delete
- for (LdapName dn : wc.getDeletedData().keySet()) {
- if (entries.containsKey(dn))
- entries.remove(dn);
- else
- throw new IllegalStateException("User to delete not found " + dn);
- }
- // add
- for (LdapName dn : wc.getNewData().keySet()) {
- LdapEntry user = (LdapEntry) wc.getNewData().get(dn);
- if (entries.containsKey(dn))
- throw new IllegalStateException("User to create found " + dn);
- entries.put(dn, user);
- }
- // modify
- for (LdapName dn : wc.getModifiedData().keySet()) {
- Attributes modifiedAttrs = wc.getModifiedData().get(dn);
- LdapEntry user;
- try {
- user = doGetEntry(dn);
- } catch (NameNotFoundException e) {
- throw new IllegalStateException("User to modify no found " + dn, e);
- }
- if (user == null)
- throw new IllegalStateException("User to modify no found " + dn);
- user.publishAttributes(modifiedAttrs);
- }
- }
-
- @Override
- public void commit(LdapEntryWorkingCopy wc) {
- save();
- }
-
- @Override
- public void rollback(LdapEntryWorkingCopy wc) {
- init();
- }
-
- /*
- * HIERARCHY
- */
- @Override
- public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
- if (getDirectory().getBaseDn().equals(dn))
- return getDirectory();
- return hierarchy.get(dn);
- }
-
- @Override
- public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
- List<HierarchyUnit> res = new ArrayList<>();
- for (LdapName n : hierarchy.keySet()) {
- if (n.size() == searchBase.size() + 1) {
- if (n.startsWith(searchBase)) {
- HierarchyUnit hu = hierarchy.get(n);
- if (functionalOnly) {
- if (hu.isFunctional())
- res.add(hu);
- } else {
- res.add(hu);
- }
- }
- }
- }
- return res;
- }
-
- public void scope(LdifDao scoped) {
- scoped.entries = Collections.unmodifiableNavigableMap(entries);
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import javax.naming.InvalidNameException;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.BasicAttribute;
-import javax.naming.directory.BasicAttributes;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-import org.argeo.util.naming.LdapAttrs;
-
-/** Basic LDIF parser. */
-public class LdifParser {
- private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
-
- protected Attributes addAttributes(SortedMap<LdapName, Attributes> res, int lineNumber, LdapName currentDn,
- Attributes currentAttributes) {
- try {
- Rdn nameRdn = currentDn.getRdn(currentDn.size() - 1);
- Attribute nameAttr = currentAttributes.get(nameRdn.getType());
- if (nameAttr == null)
- currentAttributes.put(nameRdn.getType(), nameRdn.getValue());
- else if (!nameAttr.get().equals(nameRdn.getValue()))
- throw new IllegalStateException(
- "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + currentDn
- + " (shortly before line " + lineNumber + " in LDIF file)");
- Attributes previous = res.put(currentDn, currentAttributes);
- return previous;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot add " + currentDn, e);
- }
- }
-
- /** With UTF-8 charset */
- public SortedMap<LdapName, Attributes> read(InputStream in) throws IOException {
- try (Reader reader = new InputStreamReader(in, DEFAULT_CHARSET)) {
- return read(reader);
- } finally {
- try {
- in.close();
- } catch (IOException e) {
- // silent
- }
- }
- }
-
- /** Will close the reader. */
- public SortedMap<LdapName, Attributes> read(Reader reader) throws IOException {
- SortedMap<LdapName, Attributes> res = new TreeMap<LdapName, Attributes>();
- try {
- List<String> lines = new ArrayList<>();
- try (BufferedReader br = new BufferedReader(reader)) {
- String line;
- while ((line = br.readLine()) != null) {
- lines.add(line);
- }
- }
- if (lines.size() == 0)
- return res;
- // add an empty new line since the last line is not checked
- if (!lines.get(lines.size() - 1).equals(""))
- lines.add("");
-
- LdapName currentDn = null;
- Attributes currentAttributes = null;
- StringBuilder currentEntry = new StringBuilder();
-
- readLines: for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) {
- String line = lines.get(lineNumber);
- boolean isLastLine = false;
- if (lineNumber == lines.size() - 1)
- isLastLine = true;
- if (line.startsWith(" ")) {
- currentEntry.append(line.substring(1));
- if (!isLastLine)
- continue readLines;
- }
-
- if (currentEntry.length() != 0 || isLastLine) {
- // read previous attribute
- StringBuilder attrId = new StringBuilder(8);
- boolean isBase64 = false;
- readAttrId: for (int i = 0; i < currentEntry.length(); i++) {
- char c = currentEntry.charAt(i);
- if (c == ':') {
- if (i + 1 < currentEntry.length() && currentEntry.charAt(i + 1) == ':')
- isBase64 = true;
- currentEntry.delete(0, i + (isBase64 ? 2 : 1));
- break readAttrId;
- } else {
- attrId.append(c);
- }
- }
-
- String attributeId = attrId.toString();
- // TODO should we really trim the end of the string as well?
- String cleanValueStr = currentEntry.toString().trim();
- Object attributeValue = isBase64 ? Base64.getDecoder().decode(cleanValueStr) : cleanValueStr;
-
- // manage DN attributes
- if (attributeId.equals(LdapAttrs.DN) || isLastLine) {
- if (currentDn != null) {
- //
- // ADD
- //
- Attributes previous = addAttributes(res, lineNumber, currentDn, currentAttributes);
- if (previous != null) {
-// log.warn("There was already an entry with DN " + currentDn
-// + ", which has been discarded by a subsequent one.");
- }
- }
-
- if (attributeId.equals(LdapAttrs.DN))
- try {
- currentDn = new LdapName(attributeValue.toString());
- currentAttributes = new BasicAttributes(true);
- } catch (InvalidNameException e) {
-// log.error(attributeValue + " not a valid DN, skipping the entry.");
- currentDn = null;
- currentAttributes = null;
- }
- }
-
- // store attribute
- if (currentAttributes != null) {
- Attribute attribute = currentAttributes.get(attributeId);
- if (attribute == null) {
- attribute = new BasicAttribute(attributeId);
- currentAttributes.put(attribute);
- }
- attribute.add(attributeValue);
- }
- currentEntry = new StringBuilder();
- }
- currentEntry.append(line);
- }
- } finally {
- try {
- reader.close();
- } catch (IOException e) {
- // silent
- }
- }
- return res;
- }
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import static org.argeo.util.naming.LdapAttrs.DN;
-import static org.argeo.util.naming.LdapAttrs.member;
-import static org.argeo.util.naming.LdapAttrs.objectClass;
-import static org.argeo.util.naming.LdapAttrs.uniqueMember;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
-import java.util.Base64;
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.ldap.LdapName;
-import javax.naming.ldap.Rdn;
-
-/** Basic LDIF writer */
-public class LdifWriter {
- private final static Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
- private final Writer writer;
-
- /** Writer must be closed by caller */
- public LdifWriter(Writer writer) {
- this.writer = writer;
- }
-
- /** Stream must be closed by caller */
- public LdifWriter(OutputStream out) {
- this(new OutputStreamWriter(out, DEFAULT_CHARSET));
- }
-
- public void writeEntry(LdapName name, Attributes attributes) throws IOException {
- try {
- // check consistency
- Rdn nameRdn = name.getRdn(name.size() - 1);
- Attribute nameAttr = attributes.get(nameRdn.getType());
- if (!nameAttr.get().equals(nameRdn.getValue()))
- throw new IllegalArgumentException(
- "Attribute " + nameAttr.getID() + "=" + nameAttr.get() + " not consistent with DN " + name);
-
- writer.append(DN + ": ").append(name.toString()).append('\n');
- Attribute objectClassAttr = attributes.get(objectClass.name());
- if (objectClassAttr != null)
- writeAttribute(objectClassAttr);
- attributes: for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
- Attribute attribute = attrs.next();
- if (attribute.getID().equals(DN) || attribute.getID().equals(objectClass.name()))
- continue attributes;// skip DN attribute
- if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
- continue attributes;// skip member and uniqueMember attributes, so that they are always written last
- writeAttribute(attribute);
- }
- // write member and uniqueMember attributes last
- for (NamingEnumeration<? extends Attribute> attrs = attributes.getAll(); attrs.hasMore();) {
- Attribute attribute = attrs.next();
- if (attribute.getID().equals(member.name()) || attribute.getID().equals(uniqueMember.name()))
- writeMemberAttribute(attribute);
- }
- writer.append('\n');
- writer.flush();
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot write LDIF", e);
- }
- }
-
- public void write(Map<LdapName, Attributes> entries) throws IOException {
- for (LdapName dn : entries.keySet())
- writeEntry(dn, entries.get(dn));
- }
-
- protected void writeAttribute(Attribute attribute) throws NamingException, IOException {
- for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
- Object value = attrValues.next();
- if (value instanceof byte[]) {
- String encoded = Base64.getEncoder().encodeToString((byte[]) value);
- writer.append(attribute.getID()).append(":: ").append(encoded).append('\n');
- } else {
- writer.append(attribute.getID()).append(": ").append(value.toString()).append('\n');
- }
- }
- }
-
- protected void writeMemberAttribute(Attribute attribute) throws NamingException, IOException {
- // Note: duplicate entries will be swallowed
- SortedSet<String> values = new TreeSet<>();
- for (NamingEnumeration<?> attrValues = attribute.getAll(); attrValues.hasMore();) {
- String value = attrValues.next().toString();
- values.add(value);
- }
-
- for (String value : values) {
- writer.append(attribute.getID()).append(": ").append(value).append('\n');
- }
- }
-}
+++ /dev/null
-package org.argeo.util.directory.ldap;
-
-import java.time.Instant;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-
-import org.argeo.util.naming.NamingUtils;
-
-public class SharedSecret extends AuthPassword {
- public final static String X_SHARED_SECRET = "X-SharedSecret";
- private final Instant expiry;
-
- public SharedSecret(String authInfo, String authValue) {
- super(authInfo, authValue);
- expiry = null;
- }
-
- public SharedSecret(AuthPassword authPassword) {
- super(authPassword);
- String authInfo = getAuthInfo();
- if (authInfo.length() == 16) {
- expiry = NamingUtils.ldapDateToInstant(authInfo);
- } else {
- expiry = null;
- }
- }
-
- public SharedSecret(ZonedDateTime expiryTimestamp, String value) {
- super(NamingUtils.instantToLdapDate(expiryTimestamp), value);
- expiry = expiryTimestamp.withZoneSameInstant(ZoneOffset.UTC).toInstant();
- }
-
- public SharedSecret(int hours, String value) {
- this(ZonedDateTime.now().plusHours(hours), value);
- }
-
- @Override
- protected String getExpectedAuthScheme() {
- return X_SHARED_SECRET;
- }
-
- public boolean isExpired() {
- if (expiry == null)
- return false;
- return expiry.isBefore(Instant.now());
- }
-
-}
+++ /dev/null
-package org.argeo.util.http;
-
-/** Standard HTTP headers (including WebDav). */
-public enum HttpHeader {
- AUTHORIZATION("Authorization"), //
- WWW_AUTHENTICATE("WWW-Authenticate"), //
- ALLOW("Allow"), //
-
- // WebDav
- DAV("DAV"), //
- DEPTH("Depth"), //
- ;
-
- public final static String BASIC = "Basic";
- public final static String REALM = "realm";
- public final static String NEGOTIATE = "Negotiate";
-
- private final String name;
-
- private HttpHeader(String headerName) {
- this.name = headerName;
- }
-
- public String getHeaderName() {
- return name;
- }
-
- @Override
- public String toString() {
- return getHeaderName();
- }
-
-}
+++ /dev/null
-package org.argeo.util.http;
-
-/** Generic HTTP methods. */
-public enum HttpMethod {
- OPTIONS, //
- HEAD, //
- GET, //
- POST, //
- PUT, //
- DELETE, //
-
- // WebDav
- PROPFIND, //
- PROPPATCH, //
- MKCOL, //
- MOVE, //
- COPY, //
- ;
-}
+++ /dev/null
-package org.argeo.util.http;
-
-import java.net.URI;
-import java.util.Objects;
-
-import com.sun.net.httpserver.HttpContext;
-import com.sun.net.httpserver.HttpExchange;
-
-public class HttpServerUtils {
- private final static String SLASH = "/";
-
- private static String extractPathWithingContext(HttpContext httpContext, String fullPath, boolean startWithSlash) {
- Objects.requireNonNull(fullPath);
- String contextPath = httpContext.getPath();
- if (!fullPath.startsWith(contextPath))
- throw new IllegalArgumentException(fullPath + " does not belong to context" + contextPath);
- String path = fullPath.substring(contextPath.length());
- // TODO optimise?
- if (!startWithSlash && path.startsWith(SLASH)) {
- path = path.substring(1);
- } else if (startWithSlash && !path.startsWith(SLASH)) {
- path = SLASH + path;
- }
- return path;
- }
-
- /** Path within the context, NOT starting with a slash. */
- public static String relativize(HttpExchange exchange) {
- URI uri = exchange.getRequestURI();
- HttpContext httpContext = exchange.getHttpContext();
- return extractPathWithingContext(httpContext, uri.getPath(), false);
- }
-
- /** Path within the context, starting with a slash. */
- public static String subPath(HttpExchange exchange) {
- URI uri = exchange.getRequestURI();
- HttpContext httpContext = exchange.getHttpContext();
- return extractPathWithingContext(httpContext, uri.getPath(), true);
- }
-
- /** singleton */
- private HttpServerUtils() {
-
- }
-}
+++ /dev/null
-package org.argeo.util.http;
-
-/**
- * Standard HTTP response status codes (including WebDav ones).
- *
- * @see "https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"
- */
-public enum HttpStatus {
- // Successful responses (200–299)
- OK(200, "OK"), //
- NO_CONTENT(204, "No Content"), //
- MULTI_STATUS(207, "Multi-Status"), // WebDav
- // Client error responses (400–499)
- UNAUTHORIZED(401, "Unauthorized"), //
- FORBIDDEN(403, "Forbidden"), //
- NOT_FOUND(404, "Not Found"), //
- // Server error responses (500-599)
- INTERNAL_SERVER_ERROR(500, "Internal Server Error"), //
- NOT_IMPLEMENTED(501, "Not Implemented"), //
- ;
-
- private final int code;
- private final String reasonPhrase;
-
- HttpStatus(int statusCode, String reasonPhrase) {
- this.code = statusCode;
- this.reasonPhrase = reasonPhrase;
- }
-
- public int getCode() {
- return code;
- }
-
- public String getReasonPhrase() {
- return reasonPhrase;
- }
-
- /**
- * The status line, as defined by RFC2616.
- *
- * @see "https://www.rfc-editor.org/rfc/rfc2616#section-6.1"
- */
- public String getStatusLine(String httpVersion) {
- return httpVersion + " " + code + " " + reasonPhrase;
- }
-
- public static HttpStatus parseStatusLine(String statusLine) {
- try {
- String[] arr = statusLine.split(" ");
- int code = Integer.parseInt(arr[1]);
- for (HttpStatus status : values()) {
- if (status.getCode() == code)
- return status;
- }
- } catch (Exception e) {
- throw new IllegalArgumentException("Invalid status line: " + statusLine, e);
- }
- throw new IllegalArgumentException("Unkown status code: " + statusLine);
- }
-
- @Override
- public String toString() {
- return code + " " + reasonPhrase;
- }
-
-}
+++ /dev/null
-package org.argeo.util.internal;
-
-import javax.xml.namespace.QName;
-
-public class DisplayQName extends QName {
- private static final long serialVersionUID = 2376484886212253123L;
-
- public DisplayQName(String namespaceURI, String localPart, String prefix) {
- super(namespaceURI, localPart, prefix);
- }
-
- public DisplayQName(String localPart) {
- super(localPart);
- }
-
- @Override
- public String toString() {
- String prefix = getPrefix();
- assert prefix != null;
- return "".equals(prefix) ? getLocalPart() : prefix + ":" + getLocalPart();
- }
-
- }
\ No newline at end of file
+++ /dev/null
-package org.argeo.util.naming;
-
-import java.util.EnumSet;
-import java.util.Set;
-import java.util.TreeSet;
-
-import javax.naming.InvalidNameException;
-import javax.naming.ldap.LdapName;
-
-/**
- * An object that can be identified with an X.500 distinguished name.
- *
- * @see "https://tools.ietf.org/html/rfc1779"
- */
-public interface Distinguished {
- /** The related distinguished name. */
- String dn();
-
- /** The related distinguished name as an {@link LdapName}. */
- default LdapName distinguishedName() {
- try {
- return new LdapName(dn());
- } catch (InvalidNameException e) {
- throw new IllegalArgumentException("Distinguished name " + dn() + " is not properly formatted.", e);
- }
- }
-
- /** List all DNs of an enumeration as strings. */
- static Set<String> enumToDns(EnumSet<? extends Distinguished> enumSet) {
- Set<String> res = new TreeSet<>();
- for (Enum<? extends Distinguished> enm : enumSet) {
- res.add(((Distinguished) enm).dn());
- }
- return res;
- }
-}
+++ /dev/null
-uid,,,0.9.2342.19200300.100.1.1,,RFC 4519
-mail,,,0.9.2342.19200300.100.1.3,,RFC 4524
-info,,,0.9.2342.19200300.100.1.4,,RFC 4524
-drink,,,0.9.2342.19200300.100.1.5,,RFC 4524
-roomNumber,,,0.9.2342.19200300.100.1.6,,RFC 4524
-photo,,,0.9.2342.19200300.100.1.7,,RFC 2798
-userClass,,,0.9.2342.19200300.100.1.8,,RFC 4524
-host,,,0.9.2342.19200300.100.1.9,,RFC 4524
-manager,,,0.9.2342.19200300.100.1.10,,RFC 4524
-documentIdentifier,,,0.9.2342.19200300.100.1.11,,RFC 4524
-documentTitle,,,0.9.2342.19200300.100.1.12,,RFC 4524
-documentVersion,,,0.9.2342.19200300.100.1.13,,RFC 4524
-documentAuthor,,,0.9.2342.19200300.100.1.14,,RFC 4524
-documentLocation,,,0.9.2342.19200300.100.1.15,,RFC 4524
-homePhone,,,0.9.2342.19200300.100.1.20,,RFC 4524
-secretary,,,0.9.2342.19200300.100.1.21,,RFC 4524
-dc,,,0.9.2342.19200300.100.1.25,,RFC 4519
-associatedDomain,,,0.9.2342.19200300.100.1.37,,RFC 4524
-associatedName,,,0.9.2342.19200300.100.1.38,,RFC 4524
-homePostalAddress,,,0.9.2342.19200300.100.1.39,,RFC 4524
-personalTitle,,,0.9.2342.19200300.100.1.40,,RFC 4524
-mobile,,,0.9.2342.19200300.100.1.41,,RFC 4524
-pager,,,0.9.2342.19200300.100.1.42,,RFC 4524
-co,,,0.9.2342.19200300.100.1.43,,RFC 4524
-uniqueIdentifier,,,0.9.2342.19200300.100.1.44,,RFC 4524
-organizationalStatus,,,0.9.2342.19200300.100.1.45,,RFC 4524
-buildingName,,,0.9.2342.19200300.100.1.48,,RFC 4524
-audio,,,0.9.2342.19200300.100.1.55,,RFC 2798
-documentPublisher,,,0.9.2342.19200300.100.1.56,,RFC 4524
-jpegPhoto,,,0.9.2342.19200300.100.1.60,,RFC 2798
-vendorName,,,1.3.6.1.1.4,,RFC 3045
-vendorVersion,,,1.3.6.1.1.5,,RFC 3045
-entryUUID,,,1.3.6.1.1.16.4,,RFC 4530
-entryDN,,,1.3.6.1.1.20,,RFC 5020
-labeledURI,,,1.3.6.1.4.1.250.1.57,,RFC 2798
-numSubordinates,,,1.3.6.1.4.1.453.16.2.103,,draft-ietf-boreham-numsubordinates
-namingContexts,,,1.3.6.1.4.1.1466.101.120.5,,RFC 4512
-altServer,,,1.3.6.1.4.1.1466.101.120.6,,RFC 4512
-supportedExtension,,,1.3.6.1.4.1.1466.101.120.7,,RFC 4512
-supportedControl,,,1.3.6.1.4.1.1466.101.120.13,,RFC 4512
-supportedSASLMechanisms,,,1.3.6.1.4.1.1466.101.120.14,,RFC 4512
-supportedLDAPVersion,,,1.3.6.1.4.1.1466.101.120.15,,RFC 4512
-ldapSyntaxes,,,1.3.6.1.4.1.1466.101.120.16,,RFC 4512
-supportedAuthPasswordSchemes,,,1.3.6.1.4.1.4203.1.3.3,,RFC 3112
-authPassword,,,1.3.6.1.4.1.4203.1.3.4,,RFC 3112
-supportedFeatures,,,1.3.6.1.4.1.4203.1.3.5,,RFC 4512
-inheritable,,,1.3.6.1.4.1.7628.5.4.1,,draft-ietf-ldup-subentry
-blockInheritance,,,1.3.6.1.4.1.7628.5.4.2,,draft-ietf-ldup-subentry
-objectClass,,,2.5.4.0,,RFC 4512
-aliasedObjectName,,,2.5.4.1,,RFC 4512
-cn,,,2.5.4.3,,RFC 4519
-sn,,,2.5.4.4,,RFC 4519
-serialNumber,,,2.5.4.5,,RFC 4519
-c,,,2.5.4.6,,RFC 4519
-l,,,2.5.4.7,,RFC 4519
-st,,,2.5.4.8,,RFC 4519
-street,,,2.5.4.9,,RFC 4519
-o,,,2.5.4.10,,RFC 4519
-ou,,,2.5.4.11,,RFC 4519
-title,,,2.5.4.12,,RFC 4519
-description,,,2.5.4.13,,RFC 4519
-searchGuide,,,2.5.4.14,,RFC 4519
-businessCategory,,,2.5.4.15,,RFC 4519
-postalAddress,,,2.5.4.16,,RFC 4519
-postalCode,,,2.5.4.17,,RFC 4519
-postOfficeBox,,,2.5.4.18,,RFC 4519
-physicalDeliveryOfficeName,,,2.5.4.19,,RFC 4519
-telephoneNumber,,,2.5.4.20,,RFC 4519
-telexNumber,,,2.5.4.21,,RFC 4519
-teletexTerminalIdentifier,,,2.5.4.22,,RFC 4519
-facsimileTelephoneNumber,,,2.5.4.23,,RFC 4519
-x121Address,,,2.5.4.24,,RFC 4519
-internationalISDNNumber,,,2.5.4.25,,RFC 4519
-registeredAddress,,,2.5.4.26,,RFC 4519
-destinationIndicator,,,2.5.4.27,,RFC 4519
-preferredDeliveryMethod,,,2.5.4.28,,RFC 4519
-member,,,2.5.4.31,,RFC 4519
-owner,,,2.5.4.32,,RFC 4519
-roleOccupant,,,2.5.4.33,,RFC 4519
-seeAlso,,,2.5.4.34,,RFC 4519
-userPassword,,,2.5.4.35,,RFC 4519
-userCertificate,,,2.5.4.36,,RFC 4523
-cACertificate,,,2.5.4.37,,RFC 4523
-authorityRevocationList,,,2.5.4.38,,RFC 4523
-certificateRevocationList,,,2.5.4.39,,RFC 4523
-crossCertificatePair,,,2.5.4.40,,RFC 4523
-name,,,2.5.4.41,,RFC 4519
-givenName,,,2.5.4.42,,RFC 4519
-initials,,,2.5.4.43,,RFC 4519
-generationQualifier,,,2.5.4.44,,RFC 4519
-x500UniqueIdentifier,,,2.5.4.45,,RFC 4519
-dnQualifier,,,2.5.4.46,,RFC 4519
-enhancedSearchGuide,,,2.5.4.47,,RFC 4519
-distinguishedName,,,2.5.4.49,,RFC 4519
-uniqueMember,,,2.5.4.50,,RFC 4519
-houseIdentifier,,,2.5.4.51,,RFC 4519
-supportedAlgorithms,,,2.5.4.52,,RFC 4523
-deltaRevocationList,,,2.5.4.53,,RFC 4523
-createTimestamp,,,2.5.18.1,,RFC 4512
-modifyTimestamp,,,2.5.18.2,,RFC 4512
-creatorsName,,,2.5.18.3,,RFC 4512
-modifiersName,,,2.5.18.4,,RFC 4512
-subschemaSubentry,,,2.5.18.10,,RFC 4512
-dITStructureRules,,,2.5.21.1,,RFC 4512
-dITContentRules,,,2.5.21.2,,RFC 4512
-matchingRules,,,2.5.21.4,,RFC 4512
-attributeTypes,,,2.5.21.5,,RFC 4512
-objectClasses,,,2.5.21.6,,RFC 4512
-nameForms,,,2.5.21.7,,RFC 4512
-matchingRuleUse,,,2.5.21.8,,RFC 4512
-structuralObjectClass,,,2.5.21.9,,RFC 4512
-governingStructureRule,,,2.5.21.10,,RFC 4512
-carLicense,,,2.16.840.1.113730.3.1.1,,RFC 2798
-departmentNumber,,,2.16.840.1.113730.3.1.2,,RFC 2798
-employeeNumber,,,2.16.840.1.113730.3.1.3,,RFC 2798
-employeeType,,,2.16.840.1.113730.3.1.4,,RFC 2798
-changeNumber,,,2.16.840.1.113730.3.1.5,,draft-good-ldap-changelog
-targetDN,,,2.16.840.1.113730.3.1.6,,draft-good-ldap-changelog
-changeType,,,2.16.840.1.113730.3.1.7,,draft-good-ldap-changelog
-changes,,,2.16.840.1.113730.3.1.8,,draft-good-ldap-changelog
-newRDN,,,2.16.840.1.113730.3.1.9,,draft-good-ldap-changelog
-deleteOldRDN,,,2.16.840.1.113730.3.1.10,,draft-good-ldap-changelog
-newSuperior,,,2.16.840.1.113730.3.1.11,,draft-good-ldap-changelog
-ref,,,2.16.840.1.113730.3.1.34,,RFC 3296
-changelog,,,2.16.840.1.113730.3.1.35,,draft-good-ldap-changelog
-preferredLanguage,,,2.16.840.1.113730.3.1.39,,RFC 2798
-userSMIMECertificate,,,2.16.840.1.113730.3.1.40,,RFC 2798
-userPKCS12,,,2.16.840.1.113730.3.1.216,,RFC 2798
-displayName,,,2.16.840.1.113730.3.1.241,,RFC 2798
+++ /dev/null
-package org.argeo.util.naming;
-
-import java.util.function.Supplier;
-
-import javax.xml.namespace.QName;
-
-import org.argeo.util.internal.DisplayQName;
-
-/**
- * Standard LDAP attributes as per:<br>
- * - <a href= "https://www.ldap.com/ldap-oid-reference">Standard LDAP</a><br>
- * - <a href=
- * "https://github.com/krb5/krb5/blob/master/src/plugins/kdb/ldap/libkdb_ldap/kerberos.schema">Kerberos
- * LDAP (partial)</a>
- */
-public enum LdapAttrs implements SpecifiedName, Supplier<String> {
- /** */
- uid("0.9.2342.19200300.100.1.1", "RFC 4519"),
- /** */
- mail("0.9.2342.19200300.100.1.3", "RFC 4524"),
- /** */
- info("0.9.2342.19200300.100.1.4", "RFC 4524"),
- /** */
- drink("0.9.2342.19200300.100.1.5", "RFC 4524"),
- /** */
- roomNumber("0.9.2342.19200300.100.1.6", "RFC 4524"),
- /** */
- photo("0.9.2342.19200300.100.1.7", "RFC 2798"),
- /** */
- userClass("0.9.2342.19200300.100.1.8", "RFC 4524"),
- /** */
- host("0.9.2342.19200300.100.1.9", "RFC 4524"),
- /** */
- manager("0.9.2342.19200300.100.1.10", "RFC 4524"),
- /** */
- documentIdentifier("0.9.2342.19200300.100.1.11", "RFC 4524"),
- /** */
- documentTitle("0.9.2342.19200300.100.1.12", "RFC 4524"),
- /** */
- documentVersion("0.9.2342.19200300.100.1.13", "RFC 4524"),
- /** */
- documentAuthor("0.9.2342.19200300.100.1.14", "RFC 4524"),
- /** */
- documentLocation("0.9.2342.19200300.100.1.15", "RFC 4524"),
- /** */
- homePhone("0.9.2342.19200300.100.1.20", "RFC 4524"),
- /** */
- secretary("0.9.2342.19200300.100.1.21", "RFC 4524"),
- /** */
- dc("0.9.2342.19200300.100.1.25", "RFC 4519"),
- /** */
- associatedDomain("0.9.2342.19200300.100.1.37", "RFC 4524"),
- /** */
- associatedName("0.9.2342.19200300.100.1.38", "RFC 4524"),
- /** */
- homePostalAddress("0.9.2342.19200300.100.1.39", "RFC 4524"),
- /** */
- personalTitle("0.9.2342.19200300.100.1.40", "RFC 4524"),
- /** */
- mobile("0.9.2342.19200300.100.1.41", "RFC 4524"),
- /** */
- pager("0.9.2342.19200300.100.1.42", "RFC 4524"),
- /** */
- co("0.9.2342.19200300.100.1.43", "RFC 4524"),
- /** */
- uniqueIdentifier("0.9.2342.19200300.100.1.44", "RFC 4524"),
- /** */
- organizationalStatus("0.9.2342.19200300.100.1.45", "RFC 4524"),
- /** */
- buildingName("0.9.2342.19200300.100.1.48", "RFC 4524"),
- /** */
- audio("0.9.2342.19200300.100.1.55", "RFC 2798"),
- /** */
- documentPublisher("0.9.2342.19200300.100.1.56", "RFC 4524"),
- /** */
- jpegPhoto("0.9.2342.19200300.100.1.60", "RFC 2798"),
- /** */
- vendorName("1.3.6.1.1.4", "RFC 3045"),
- /** */
- vendorVersion("1.3.6.1.1.5", "RFC 3045"),
- /** */
- entryUUID("1.3.6.1.1.16.4", "RFC 4530"),
- /** */
- entryDN("1.3.6.1.1.20", "RFC 5020"),
- /** */
- labeledURI("1.3.6.1.4.1.250.1.57", "RFC 2798"),
- /** */
- numSubordinates("1.3.6.1.4.1.453.16.2.103", "draft-ietf-boreham-numsubordinates"),
- /** */
- namingContexts("1.3.6.1.4.1.1466.101.120.5", "RFC 4512"),
- /** */
- altServer("1.3.6.1.4.1.1466.101.120.6", "RFC 4512"),
- /** */
- supportedExtension("1.3.6.1.4.1.1466.101.120.7", "RFC 4512"),
- /** */
- supportedControl("1.3.6.1.4.1.1466.101.120.13", "RFC 4512"),
- /** */
- supportedSASLMechanisms("1.3.6.1.4.1.1466.101.120.14", "RFC 4512"),
- /** */
- supportedLDAPVersion("1.3.6.1.4.1.1466.101.120.15", "RFC 4512"),
- /** */
- ldapSyntaxes("1.3.6.1.4.1.1466.101.120.16", "RFC 4512"),
- /** */
- supportedAuthPasswordSchemes("1.3.6.1.4.1.4203.1.3.3", "RFC 3112"),
- /** */
- authPassword("1.3.6.1.4.1.4203.1.3.4", "RFC 3112"),
- /** */
- supportedFeatures("1.3.6.1.4.1.4203.1.3.5", "RFC 4512"),
- /** */
- inheritable("1.3.6.1.4.1.7628.5.4.1", "draft-ietf-ldup-subentry"),
- /** */
- blockInheritance("1.3.6.1.4.1.7628.5.4.2", "draft-ietf-ldup-subentry"),
- /** */
- objectClass("2.5.4.0", "RFC 4512"),
- /** */
- aliasedObjectName("2.5.4.1", "RFC 4512"),
- /** */
- cn("2.5.4.3", "RFC 4519"),
- /** */
- sn("2.5.4.4", "RFC 4519"),
- /** */
- serialNumber("2.5.4.5", "RFC 4519"),
- /** */
- c("2.5.4.6", "RFC 4519"),
- /** */
- l("2.5.4.7", "RFC 4519"),
- /** */
- st("2.5.4.8", "RFC 4519"),
- /** */
- street("2.5.4.9", "RFC 4519"),
- /** */
- o("2.5.4.10", "RFC 4519"),
- /** */
- ou("2.5.4.11", "RFC 4519"),
- /** */
- title("2.5.4.12", "RFC 4519"),
- /** */
- description("2.5.4.13", "RFC 4519"),
- /** */
- searchGuide("2.5.4.14", "RFC 4519"),
- /** */
- businessCategory("2.5.4.15", "RFC 4519"),
- /** */
- postalAddress("2.5.4.16", "RFC 4519"),
- /** */
- postalCode("2.5.4.17", "RFC 4519"),
- /** */
- postOfficeBox("2.5.4.18", "RFC 4519"),
- /** */
- physicalDeliveryOfficeName("2.5.4.19", "RFC 4519"),
- /** */
- telephoneNumber("2.5.4.20", "RFC 4519"),
- /** */
- telexNumber("2.5.4.21", "RFC 4519"),
- /** */
- teletexTerminalIdentifier("2.5.4.22", "RFC 4519"),
- /** */
- facsimileTelephoneNumber("2.5.4.23", "RFC 4519"),
- /** */
- x121Address("2.5.4.24", "RFC 4519"),
- /** */
- internationalISDNNumber("2.5.4.25", "RFC 4519"),
- /** */
- registeredAddress("2.5.4.26", "RFC 4519"),
- /** */
- destinationIndicator("2.5.4.27", "RFC 4519"),
- /** */
- preferredDeliveryMethod("2.5.4.28", "RFC 4519"),
- /** */
- member("2.5.4.31", "RFC 4519"),
- /** */
- owner("2.5.4.32", "RFC 4519"),
- /** */
- roleOccupant("2.5.4.33", "RFC 4519"),
- /** */
- seeAlso("2.5.4.34", "RFC 4519"),
- /** */
- userPassword("2.5.4.35", "RFC 4519"),
- /** */
- userCertificate("2.5.4.36", "RFC 4523"),
- /** */
- cACertificate("2.5.4.37", "RFC 4523"),
- /** */
- authorityRevocationList("2.5.4.38", "RFC 4523"),
- /** */
- certificateRevocationList("2.5.4.39", "RFC 4523"),
- /** */
- crossCertificatePair("2.5.4.40", "RFC 4523"),
- /** */
- name("2.5.4.41", "RFC 4519"),
- /** */
- givenName("2.5.4.42", "RFC 4519"),
- /** */
- initials("2.5.4.43", "RFC 4519"),
- /** */
- generationQualifier("2.5.4.44", "RFC 4519"),
- /** */
- x500UniqueIdentifier("2.5.4.45", "RFC 4519"),
- /** */
- dnQualifier("2.5.4.46", "RFC 4519"),
- /** */
- enhancedSearchGuide("2.5.4.47", "RFC 4519"),
- /** */
- distinguishedName("2.5.4.49", "RFC 4519"),
- /** */
- uniqueMember("2.5.4.50", "RFC 4519"),
- /** */
- houseIdentifier("2.5.4.51", "RFC 4519"),
- /** */
- supportedAlgorithms("2.5.4.52", "RFC 4523"),
- /** */
- deltaRevocationList("2.5.4.53", "RFC 4523"),
- /** */
- createTimestamp("2.5.18.1", "RFC 4512"),
- /** */
- modifyTimestamp("2.5.18.2", "RFC 4512"),
- /** */
- creatorsName("2.5.18.3", "RFC 4512"),
- /** */
- modifiersName("2.5.18.4", "RFC 4512"),
- /** */
- subschemaSubentry("2.5.18.10", "RFC 4512"),
- /** */
- dITStructureRules("2.5.21.1", "RFC 4512"),
- /** */
- dITContentRules("2.5.21.2", "RFC 4512"),
- /** */
- matchingRules("2.5.21.4", "RFC 4512"),
- /** */
- attributeTypes("2.5.21.5", "RFC 4512"),
- /** */
- objectClasses("2.5.21.6", "RFC 4512"),
- /** */
- nameForms("2.5.21.7", "RFC 4512"),
- /** */
- matchingRuleUse("2.5.21.8", "RFC 4512"),
- /** */
- structuralObjectClass("2.5.21.9", "RFC 4512"),
- /** */
- governingStructureRule("2.5.21.10", "RFC 4512"),
- /** */
- carLicense("2.16.840.1.113730.3.1.1", "RFC 2798"),
- /** */
- departmentNumber("2.16.840.1.113730.3.1.2", "RFC 2798"),
- /** */
- employeeNumber("2.16.840.1.113730.3.1.3", "RFC 2798"),
- /** */
- employeeType("2.16.840.1.113730.3.1.4", "RFC 2798"),
- /** */
- changeNumber("2.16.840.1.113730.3.1.5", "draft-good-ldap-changelog"),
- /** */
- targetDN("2.16.840.1.113730.3.1.6", "draft-good-ldap-changelog"),
- /** */
- changeType("2.16.840.1.113730.3.1.7", "draft-good-ldap-changelog"),
- /** */
- changes("2.16.840.1.113730.3.1.8", "draft-good-ldap-changelog"),
- /** */
- newRDN("2.16.840.1.113730.3.1.9", "draft-good-ldap-changelog"),
- /** */
- deleteOldRDN("2.16.840.1.113730.3.1.10", "draft-good-ldap-changelog"),
- /** */
- newSuperior("2.16.840.1.113730.3.1.11", "draft-good-ldap-changelog"),
- /** */
- ref("2.16.840.1.113730.3.1.34", "RFC 3296"),
- /** */
- changelog("2.16.840.1.113730.3.1.35", "draft-good-ldap-changelog"),
- /** */
- preferredLanguage("2.16.840.1.113730.3.1.39", "RFC 2798"),
- /** */
- userSMIMECertificate("2.16.840.1.113730.3.1.40", "RFC 2798"),
- /** */
- userPKCS12("2.16.840.1.113730.3.1.216", "RFC 2798"),
- /** */
- displayName("2.16.840.1.113730.3.1.241", "RFC 2798"),
-
- // Sun memberOf
- memberOf("1.2.840.113556.1.2.102", "389 DS memberOf"),
-
- // KERBEROS (partial)
- krbPrincipalName("2.16.840.1.113719.1.301.6.8.1", "Novell Kerberos Schema Definitions"),
-
- // RFC 2985 and RFC 3039 (partial)
- dateOfBirth("1.3.6.1.5.5.7.9.1", "RFC 2985"),
- /** */
- placeOfBirth("1.3.6.1.5.5.7.9.2", "RFC 2985"),
- /** */
- gender("1.3.6.1.5.5.7.9.3", "RFC 2985"),
- /** */
- countryOfCitizenship("1.3.6.1.5.5.7.9.4", "RFC 2985"),
- /** */
- countryOfResidence("1.3.6.1.5.5.7.9.5", "RFC 2985"),
-
- // RFC 2307bis (partial)
- /** */
- uidNumber("1.3.6.1.1.1.1.0", "RFC 2307bis"),
- /** */
- gidNumber("1.3.6.1.1.1.1.1", "RFC 2307bis"),
- /** */
- homeDirectory("1.3.6.1.1.1.1.3", "RFC 2307bis"),
- /** */
- loginShell("1.3.6.1.1.1.1.4", "RFC 2307bis"),
- /** */
- memberUid("1.3.6.1.1.1.1.12", "RFC 2307bis"),
-
- //
- ;
-
- public final static String DN = "dn";
-
-// private final static String LDAP_ = "ldap:";
-
- private final String oid, spec;
- private final QName value;
-
- LdapAttrs(String oid, String spec) {
- this.oid = oid;
- this.spec = spec;
- this.value = new DisplayQName(LdapObjs.LDAP_NAMESPACE_URI, name(), LdapObjs.LDAP_DEFAULT_PREFIX);
- }
-
- public QName qName() {
- return value;
- }
-
- @Override
- public String getID() {
- return oid;
- }
-
- @Override
- public String getSpec() {
- return spec;
- }
-
- @Deprecated
- public String property() {
- return get();
- }
-
- @Deprecated
- public String qualified() {
- return get();
- }
-
- @Override
- public String get() {
- return LdapObjs.LDAP_DEFAULT_PREFIX + ":" + name();
- }
-
- @Override
- public final String toString() {
- // must return the name
- return name();
- }
-
-}
+++ /dev/null
-account,,,0.9.2342.19200300.100.4.5,,RFC 4524
-document,,,0.9.2342.19200300.100.4.6,,RFC 4524
-room,,,0.9.2342.19200300.100.4.7,,RFC 4524
-documentSeries,,,0.9.2342.19200300.100.4.9,,RFC 4524
-domain,,,0.9.2342.19200300.100.4.13,,RFC 4524
-rFC822localPart,,,0.9.2342.19200300.100.4.14,,RFC 4524
-domainRelatedObject,,,0.9.2342.19200300.100.4.17,,RFC 4524
-friendlyCountry,,,0.9.2342.19200300.100.4.18,,RFC 4524
-simpleSecurityObject,,,0.9.2342.19200300.100.4.19,,RFC 4524
-uidObject,,,1.3.6.1.1.3.1,,RFC 4519
-extensibleObject,,,1.3.6.1.4.1.1466.101.120.111,,RFC 4512
-dcObject,,,1.3.6.1.4.1.1466.344,,RFC 4519
-authPasswordObject,,,1.3.6.1.4.1.4203.1.4.7,,RFC 3112
-namedObject,,,1.3.6.1.4.1.5322.13.1.1,,draft-howard-namedobject
-inheritableLDAPSubEntry,,,1.3.6.1.4.1.7628.5.6.1.1,,draft-ietf-ldup-subentry
-top,,,2.5.6.0,,RFC 4512
-alias,,,2.5.6.1,,RFC 4512
-country,,,2.5.6.2,,RFC 4519
-locality,,,2.5.6.3,,RFC 4519
-organization,,,2.5.6.4,,RFC 4519
-organizationalUnit,,,2.5.6.5,,RFC 4519
-person,,,2.5.6.6,,RFC 4519
-organizationalPerson,,,2.5.6.7,,RFC 4519
-organizationalRole,,,2.5.6.8,,RFC 4519
-groupOfNames,,,2.5.6.9,,RFC 4519
-residentialPerson,,,2.5.6.10,,RFC 4519
-applicationProcess,,,2.5.6.11,,RFC 4519
-device,,,2.5.6.14,,RFC 4519
-strongAuthenticationUser,,,2.5.6.15,,RFC 4523
-certificationAuthority,,,2.5.6.16,,RFC 4523
-certificationAuthority-V2,,,2.5.6.16.2,,RFC 4523
-groupOfUniqueNames,,,2.5.6.17,,RFC 4519
-userSecurityInformation,,,2.5.6.18,,RFC 4523
-cRLDistributionPoint,,,2.5.6.19,,RFC 4523
-pkiUser,,,2.5.6.21,,RFC 4523
-pkiCA,,,2.5.6.22,,RFC 4523
-deltaCRL,,,2.5.6.23,,RFC 4523
-subschema,,,2.5.20.1,,RFC 4512
-ldapSubEntry,,,2.16.840.1.113719.2.142.6.1.1,,draft-ietf-ldup-subentry
-changeLogEntry,,,2.16.840.1.113730.3.2.1,,draft-good-ldap-changelog
-inetOrgPerson,,,2.16.840.1.113730.3.2.2,,RFC 2798
-referral,,,2.16.840.1.113730.3.2.6,,RFC 3296
+++ /dev/null
-package org.argeo.util.naming;
-
-import java.util.function.Supplier;
-
-import javax.xml.namespace.QName;
-
-import org.argeo.util.internal.DisplayQName;
-
-/**
- * Standard LDAP object classes as per
- * <a href="https://www.ldap.com/ldap-oid-reference">https://www.ldap.com/ldap-
- * oid-reference</a>
- */
-public enum LdapObjs implements SpecifiedName, Supplier<String> {
- account("0.9.2342.19200300.100.4.5", "RFC 4524"),
- /** */
- document("0.9.2342.19200300.100.4.6", "RFC 4524"),
- /** */
- room("0.9.2342.19200300.100.4.7", "RFC 4524"),
- /** */
- documentSeries("0.9.2342.19200300.100.4.9", "RFC 4524"),
- /** */
- domain("0.9.2342.19200300.100.4.13", "RFC 4524"),
- /** */
- rFC822localPart("0.9.2342.19200300.100.4.14", "RFC 4524"),
- /** */
- domainRelatedObject("0.9.2342.19200300.100.4.17", "RFC 4524"),
- /** */
- friendlyCountry("0.9.2342.19200300.100.4.18", "RFC 4524"),
- /** */
- simpleSecurityObject("0.9.2342.19200300.100.4.19", "RFC 4524"),
- /** */
- uidObject("1.3.6.1.1.3.1", "RFC 4519"),
- /** */
- extensibleObject("1.3.6.1.4.1.1466.101.120.111", "RFC 4512"),
- /** */
- dcObject("1.3.6.1.4.1.1466.344", "RFC 4519"),
- /** */
- authPasswordObject("1.3.6.1.4.1.4203.1.4.7", "RFC 3112"),
- /** */
- namedObject("1.3.6.1.4.1.5322.13.1.1", "draft-howard-namedobject"),
- /** */
- inheritableLDAPSubEntry("1.3.6.1.4.1.7628.5.6.1.1", "draft-ietf-ldup-subentry"),
- /** */
- top("2.5.6.0", "RFC 4512"),
- /** */
- alias("2.5.6.1", "RFC 4512"),
- /** */
- country("2.5.6.2", "RFC 4519"),
- /** */
- locality("2.5.6.3", "RFC 4519"),
- /** */
- organization("2.5.6.4", "RFC 4519"),
- /** */
- organizationalUnit("2.5.6.5", "RFC 4519"),
- /** */
- person("2.5.6.6", "RFC 4519"),
- /** */
- organizationalPerson("2.5.6.7", "RFC 4519"),
- /** */
- organizationalRole("2.5.6.8", "RFC 4519"),
- /** */
- groupOfNames("2.5.6.9", "RFC 4519"),
- /** */
- residentialPerson("2.5.6.10", "RFC 4519"),
- /** */
- applicationProcess("2.5.6.11", "RFC 4519"),
- /** */
- device("2.5.6.14", "RFC 4519"),
- /** */
- strongAuthenticationUser("2.5.6.15", "RFC 4523"),
- /** */
- certificationAuthority("2.5.6.16", "RFC 4523"),
- // /** Should be certificationAuthority-V2 */
- // certificationAuthority_V2("2.5.6.16.2", "RFC 4523") {
- // },
- /** */
- groupOfUniqueNames("2.5.6.17", "RFC 4519"),
- /** */
- userSecurityInformation("2.5.6.18", "RFC 4523"),
- /** */
- cRLDistributionPoint("2.5.6.19", "RFC 4523"),
- /** */
- pkiUser("2.5.6.21", "RFC 4523"),
- /** */
- pkiCA("2.5.6.22", "RFC 4523"),
- /** */
- deltaCRL("2.5.6.23", "RFC 4523"),
- /** */
- subschema("2.5.20.1", "RFC 4512"),
- /** */
- ldapSubEntry("2.16.840.1.113719.2.142.6.1.1", "draft-ietf-ldup-subentry"),
- /** */
- changeLogEntry("2.16.840.1.113730.3.2.1", "draft-good-ldap-changelog"),
- /** */
- inetOrgPerson("2.16.840.1.113730.3.2.2", "RFC 2798"),
- /** */
- referral("2.16.840.1.113730.3.2.6", "RFC 3296"),
-
- // RFC 2307bis (partial)
- /** */
- posixAccount("1.3.6.1.1.1.2.0", "RFC 2307bis"),
- /** */
- posixGroup("1.3.6.1.1.1.2.2", "RFC 2307bis"),
-
- //
- ;
-
- /** MUST be equal to ContentRepository LDAP namespace. */
- final static String LDAP_NAMESPACE_URI = "http://www.argeo.org/ns/ldap";
- /** MUST be equal to ContentRepository LDAP prefix. */
- final static String LDAP_DEFAULT_PREFIX = "ldap";
-
- private final String oid, spec;
- private final QName value;
-
- private LdapObjs(String oid, String spec) {
- this.oid = oid;
- this.spec = spec;
- this.value = new DisplayQName(LDAP_NAMESPACE_URI, name(), LDAP_DEFAULT_PREFIX);
- }
-
- public QName qName() {
- return value;
- }
-
- public String getOid() {
- return oid;
- }
-
- public String getSpec() {
- return spec;
- }
-
- @Deprecated
- public String property() {
- return get();
- }
-
- @Override
- public String get() {
- return LdapObjs.LDAP_DEFAULT_PREFIX + ":" + name();
- }
-
-}
+++ /dev/null
-package org.argeo.util.naming;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLDecoder;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.OffsetDateTime;
-import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.time.temporal.ChronoField;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-public class NamingUtils {
- /** As per https://tools.ietf.org/html/rfc4517#section-3.3.13 */
- private final static DateTimeFormatter utcLdapDate = DateTimeFormatter.ofPattern("uuuuMMddHHmmssX")
- .withZone(ZoneOffset.UTC);
-
- /** @return null if not parseable */
- public static Instant ldapDateToInstant(String ldapDate) {
- try {
- return OffsetDateTime.parse(ldapDate, utcLdapDate).toInstant();
- } catch (DateTimeParseException e) {
- return null;
- }
- }
-
- /** @return null if not parseable */
- public static ZonedDateTime ldapDateToZonedDateTime(String ldapDate) {
- try {
- return OffsetDateTime.parse(ldapDate, utcLdapDate).toZonedDateTime();
- } catch (DateTimeParseException e) {
- return null;
- }
- }
-
- public static Calendar ldapDateToCalendar(String ldapDate) {
- OffsetDateTime instant = OffsetDateTime.parse(ldapDate, utcLdapDate);
- GregorianCalendar calendar = new GregorianCalendar();
- calendar.set(Calendar.DAY_OF_MONTH, instant.get(ChronoField.DAY_OF_MONTH));
- calendar.set(Calendar.MONTH, instant.get(ChronoField.MONTH_OF_YEAR));
- calendar.set(Calendar.YEAR, instant.get(ChronoField.YEAR));
- return calendar;
- }
-
- public static String instantToLdapDate(ZonedDateTime instant) {
- return utcLdapDate.format(instant.withZoneSameInstant(ZoneOffset.UTC));
- }
-
- public static String getQueryValue(Map<String, List<String>> query, String key) {
- if (!query.containsKey(key))
- return null;
- List<String> val = query.get(key);
- if (val.size() == 1)
- return val.get(0);
- else
- throw new IllegalArgumentException("There are " + val.size() + " value(s) for " + key);
- }
-
- public static Map<String, List<String>> queryToMap(URI uri) {
- return queryToMap(uri.getQuery());
- }
-
- private static Map<String, List<String>> queryToMap(String queryPart) {
- try {
- final Map<String, List<String>> query_pairs = new LinkedHashMap<String, List<String>>();
- if (queryPart == null)
- return query_pairs;
- final String[] pairs = queryPart.split("&");
- for (String pair : pairs) {
- final int idx = pair.indexOf("=");
- final String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), StandardCharsets.UTF_8.name())
- : pair;
- if (!query_pairs.containsKey(key)) {
- query_pairs.put(key, new LinkedList<String>());
- }
- final String value = idx > 0 && pair.length() > idx + 1
- ? URLDecoder.decode(pair.substring(idx + 1), StandardCharsets.UTF_8.name())
- : null;
- query_pairs.get(key).add(value);
- }
- return query_pairs;
- } catch (UnsupportedEncodingException e) {
- throw new IllegalArgumentException("Cannot convert " + queryPart + " to map", e);
- }
- }
-
- private NamingUtils() {
-
- }
-
- public static void main(String args[]) {
- ZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(ZoneOffset.UTC);
- String str = utcLdapDate.format(now);
- System.out.println(str);
- utcLdapDate.parse(str);
- utcLdapDate.parse("19520512000000Z");
- }
-}
+++ /dev/null
-package org.argeo.util.naming;
-
-interface NodeOID {
- String BASE = "1.3.6.1.4.1" + ".48308" + ".1";
-
- // uuidgen --md5 --namespace @oid --name 1.3.6.1.4.1.48308
- String BASE_UUID_V3 = "6869e86b-96b7-3d49-b6ab-ffffc5ad95fb";
-
- // uuidgen --sha1 --namespace @oid --name 1.3.6.1.4.1.48308
- String BASE_UUID_V5 = "58873947-460c-59a6-a7b4-28a97def5f27";
-
- // ATTRIBUTE TYPES
- String ATTRIBUTE_TYPES = BASE + ".4";
-
- // OBJECT CLASSES
- String OBJECT_CLASSES = BASE + ".6";
-}
+++ /dev/null
-package org.argeo.util.naming;
-
-/**
- * A name which has been specified and for which an id has been defined
- * (typically an OID).
- */
-public interface SpecifiedName {
- /** The name */
- String name();
-
- /** An RFC or the URLof some specification */
- default String getSpec() {
- return null;
- }
-
- /** Typically an OID */
- default String getID() {
- return getClass().getName() + "." + name();
- }
-}
+++ /dev/null
-package org.argeo.util.naming.dns;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Base64;
-import java.util.Collections;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedSet;
-import java.util.StringJoiner;
-import java.util.TreeMap;
-import java.util.TreeSet;
-
-import javax.naming.Binding;
-import javax.naming.Context;
-import javax.naming.NameNotFoundException;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
-import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
-import javax.naming.directory.InitialDirContext;
-
-public class DnsBrowser implements Closeable {
- private final DirContext initialCtx;
-
- public DnsBrowser() {
- this(new ArrayList<>());
- }
-
- public DnsBrowser(List<String> dnsServerUrls) {
- try {
- Objects.requireNonNull(dnsServerUrls);
- Hashtable<String, Object> env = new Hashtable<>();
- env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
- if (!dnsServerUrls.isEmpty()) {
- boolean specified = false;
- StringJoiner providerUrl = new StringJoiner(" ");
- for (String dnsUrl : dnsServerUrls) {
- if (dnsUrl != null) {
- providerUrl.add(dnsUrl);
- specified = true;
- }
- }
- if (specified)
- env.put(Context.PROVIDER_URL, providerUrl.toString());
- }
- initialCtx = new InitialDirContext(env);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot initialise DNS borowser.", e);
- }
- }
-
- public Map<String, List<String>> getAllRecords(String name) {
- try {
- Map<String, List<String>> res = new TreeMap<>();
- Attributes attrs = initialCtx.getAttributes(name);
- NamingEnumeration<String> ids = attrs.getIDs();
- while (ids.hasMore()) {
- String recordType = ids.next();
- List<String> lst = new ArrayList<String>();
- res.put(recordType, lst);
- Attribute attr = attrs.get(recordType);
- addValues(attr, lst);
- }
- return Collections.unmodifiableMap(res);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get allrecords of " + name, e);
- }
- }
-
- /**
- * Return a single record (typically A, AAAA, etc. or null if not available.
- * Will fail if multiple records.
- */
- public String getRecord(String name, String recordType) {
- try {
- Attributes attrs = initialCtx.getAttributes(name, new String[] { recordType });
- if (attrs.size() == 0)
- return null;
- Attribute attr = attrs.get(recordType);
- if (attr.size() > 1)
- throw new IllegalArgumentException("Multiple record type " + recordType);
- assert attr.size() != 0;
- Object value = attr.get();
- assert value != null;
- return value.toString();
- } catch (NameNotFoundException e) {
- return null;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get DNS entry " + recordType + " of " + name, e);
- }
- }
-
- /**
- * Return records of a given type.
- */
- public List<String> getRecords(String name, String recordType) {
- try {
- List<String> res = new ArrayList<String>();
- Attributes attrs = initialCtx.getAttributes(name, new String[] { recordType });
- Attribute attr = attrs.get(recordType);
- addValues(attr, res);
- return res;
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot get records " + recordType + " of " + name, e);
- }
- }
-
- /** Ordered, with preferred first. */
- public List<String> getSrvRecordsAsHosts(String name, boolean withPort) {
- List<String> raw = getRecords(name, "SRV");
- if (raw.size() == 0)
- return null;
- SortedSet<SrvRecord> res = new TreeSet<>();
- for (int i = 0; i < raw.size(); i++) {
- String record = raw.get(i);
- String[] arr = record.split(" ");
- Integer priority = Integer.parseInt(arr[0]);
- Integer weight = Integer.parseInt(arr[1]);
- Integer port = Integer.parseInt(arr[2]);
- String hostname = arr[3];
- SrvRecord order = new SrvRecord(priority, weight, port, hostname);
- res.add(order);
- }
- List<String> lst = new ArrayList<>();
- for (SrvRecord order : res) {
- lst.add(order.toHost(withPort));
- }
- return Collections.unmodifiableList(lst);
- }
-
- private void addValues(Attribute attr, List<String> lst) throws NamingException {
- NamingEnumeration<?> values = attr.getAll();
- while (values.hasMore()) {
- Object value = values.next();
- if (value != null) {
- if (value instanceof byte[]) {
- String str = Base64.getEncoder().encodeToString((byte[]) value);
- lst.add(str);
- } else
- lst.add(value.toString());
- }
- }
-
- }
-
- public List<String> listEntries(String name) {
- try {
- List<String> res = new ArrayList<String>();
- NamingEnumeration<Binding> ne = initialCtx.listBindings(name);
- while (ne.hasMore()) {
- Binding b = ne.next();
- res.add(b.getName());
- }
- return Collections.unmodifiableList(res);
- } catch (NamingException e) {
- throw new IllegalStateException("Cannot list entries of " + name, e);
- }
- }
-
- @Override
- public void close() throws IOException {
- destroy();
- }
-
- public void destroy() {
- try {
- initialCtx.close();
- } catch (NamingException e) {
- // silent
- }
- }
-
- public static void main(String[] args) {
- if (args.length == 0) {
- printUsage(System.err);
- System.exit(1);
- }
- try (DnsBrowser dnsBrowser = new DnsBrowser()) {
- String hostname = args[0];
- String recordType = args.length > 1 ? args[1] : "A";
- if (recordType.equals("*")) {
- Map<String, List<String>> records = dnsBrowser.getAllRecords(hostname);
- for (String type : records.keySet()) {
- for (String record : records.get(type)) {
- String typeLabel;
- if ("44".equals(type))
- typeLabel = "SSHFP";
- else if ("46".equals(type))
- typeLabel = "RRSIG";
- else if ("48".equals(type))
- typeLabel = "DNSKEY";
- else
- typeLabel = type;
- System.out.println(typeLabel + "\t" + record);
- }
- }
- } else {
- System.out.println(dnsBrowser.getRecord(hostname, recordType));
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static void printUsage(PrintStream out) {
- out.println("java org.argeo.naming.DnsBrowser <hostname> [<record type> | *]");
- }
-
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.util.naming.dns;
-
-class SrvRecord implements Comparable<SrvRecord> {
- private final Integer priority;
- private final Integer weight;
- private final Integer port;
- private final String hostname;
-
- public SrvRecord(Integer priority, Integer weight, Integer port, String hostname) {
- this.priority = priority;
- this.weight = weight;
- this.port = port;
- this.hostname = hostname;
- }
-
- @Override
- public int compareTo(SrvRecord other) {
- // https: // en.wikipedia.org/wiki/SRV_record
- if (priority != other.priority)
- return priority - other.priority;
- if (weight != other.weight)
- return other.weight - other.weight;
- String host = toHost(false);
- String otherHost = other.toHost(false);
- if (host.length() == otherHost.length())
- return host.compareTo(otherHost);
- else
- return host.length() - otherHost.length();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof SrvRecord) {
- SrvRecord other = (SrvRecord) obj;
- return priority == other.priority && weight == other.weight && port == other.port
- && hostname.equals(other.hostname);
- }
- return false;
- }
-
- @Override
- public String toString() {
- return priority + " " + weight;
- }
-
- public String toHost(boolean withPort) {
- String hostStr = hostname;
- if (hostname.charAt(hostname.length() - 1) == '.')
- hostStr = hostname.substring(0, hostname.length() - 1);
- return hostStr + (withPort ? ":" + port : "");
- }
-}
+++ /dev/null
-/** Generic naming and LDAP support. */
-package org.argeo.util.naming;
\ No newline at end of file
+++ /dev/null
-/** Generic Java utilities. */
-package org.argeo.util;
\ No newline at end of file
+++ /dev/null
-package org.argeo.util.register;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionStage;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-/**
- * A wrapper for an object, whose dependencies and life cycle can be managed.
- */
-public class Component<I> implements Supplier<I>, Comparable<Component<?>> {
-
- private final I instance;
-
- private final Runnable init;
- private final Runnable close;
-
- private final Map<Class<? super I>, PublishedType<? super I>> types;
- private final Set<Dependency<?>> dependencies;
- private final Map<String, Object> properties;
-
- private CompletableFuture<Void> activationStarted = null;
- private CompletableFuture<Void> activated = null;
-
- private CompletableFuture<Void> deactivationStarted = null;
- private CompletableFuture<Void> deactivated = null;
-
- // internal
- private Set<Dependency<?>> dependants = new HashSet<>();
-
- private RankingKey rankingKey;
-
- Component(ComponentRegister register, I instance, Runnable init, Runnable close, Set<Dependency<?>> dependencies,
- Set<Class<? super I>> classes, Map<String, Object> properties) {
- assert instance != null;
- assert init != null;
- assert close != null;
- assert dependencies != null;
- assert classes != null;
-
- this.instance = instance;
- this.init = init;
- this.close = close;
-
- // types
- Map<Class<? super I>, PublishedType<? super I>> types = new HashMap<>(classes.size());
- for (Class<? super I> clss : classes) {
-// if (!clss.isAssignableFrom(instance.getClass()))
-// throw new IllegalArgumentException(
-// "Type " + clss.getName() + " is not compatible with " + instance.getClass().getName());
- types.put(clss, new PublishedType<>(this, clss));
- }
- this.types = Collections.unmodifiableMap(types);
-
- // dependencies
- this.dependencies = Collections.unmodifiableSet(new HashSet<>(dependencies));
- for (Dependency<?> dependency : this.dependencies) {
- dependency.setDependantComponent(this);
- }
-
- // deactivated by default
- deactivated = CompletableFuture.completedFuture(null);
- deactivationStarted = CompletableFuture.completedFuture(null);
-
- // TODO check whether context is active, so that we start right away
- prepareNextActivation();
-
- long serviceId = register.register(this);
- Map<String, Object> props = new HashMap<>(properties);
- props.put(RankingKey.SERVICE_ID, serviceId);
- this.properties = Collections.unmodifiableMap(props);
- rankingKey = new RankingKey(properties);
- }
-
- private void prepareNextActivation() {
- activationStarted = new CompletableFuture<Void>();
- activated = activationStarted //
- .thenComposeAsync(this::dependenciesActivated) //
- .thenRun(this.init) //
- .thenRun(() -> prepareNextDeactivation());
- }
-
- private void prepareNextDeactivation() {
- deactivationStarted = new CompletableFuture<Void>();
- deactivated = deactivationStarted //
- .thenComposeAsync(this::dependantsDeactivated) //
- .thenRun(this.close) //
- .thenRun(() -> prepareNextActivation());
- }
-
- CompletableFuture<Void> getActivated() {
- return activated;
- }
-
- CompletableFuture<Void> getDeactivated() {
- return deactivated;
- }
-
- void startActivating() {
- if (activated.isDone() || activationStarted.isDone())
- return;
- activationStarted.complete(null);
- }
-
- void startDeactivating() {
- if (deactivated.isDone() || deactivationStarted.isDone())
- return;
- deactivationStarted.complete(null);
- }
-
- CompletableFuture<Void> dependenciesActivated(Void v) {
- Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependencies.size());
- for (Dependency<?> dependency : this.dependencies) {
- CompletableFuture<Void> dependencyActivated = dependency.publisherActivated() //
- .thenCompose(dependency::set);
- constraints.add(dependencyActivated);
- }
- return CompletableFuture.allOf(constraints.toArray(new CompletableFuture[constraints.size()]));
- }
-
- CompletableFuture<Void> dependantsDeactivated(Void v) {
- Set<CompletableFuture<?>> constraints = new HashSet<>(this.dependants.size());
- for (Dependency<?> dependant : this.dependants) {
- CompletableFuture<Void> dependantDeactivated = dependant.dependantDeactivated() //
- .thenCompose(dependant::unset);
- constraints.add(dependantDeactivated);
- }
- CompletableFuture<Void> dependantsDeactivated = CompletableFuture
- .allOf(constraints.toArray(new CompletableFuture[constraints.size()]));
- return dependantsDeactivated;
-
- }
-
- void addDependant(Dependency<?> dependant) {
- dependants.add(dependant);
- }
-
- @Override
- public I get() {
- return instance;
- }
-
- @SuppressWarnings("unchecked")
- public <T> PublishedType<T> getType(Class<T> clss) {
- if (!types.containsKey(clss))
- throw new IllegalArgumentException(clss.getName() + " is not a type published by this component");
- return (PublishedType<T>) types.get(clss);
- }
-
- public <T> boolean isPublishedType(Class<T> clss) {
- return types.containsKey(clss);
- }
-
- public Map<String, Object> getProperties() {
- return properties;
- }
-
- @Override
- public int compareTo(Component<?> o) {
- return rankingKey.compareTo(rankingKey);
- }
-
- @Override
- public int hashCode() {
- Long serviceId = (Long) properties.get(RankingKey.SERVICE_ID);
- if (serviceId != null)
- return serviceId.intValue();
- else
- return super.hashCode();
- }
-
- @Override
- public String toString() {
- List<String> classes = new ArrayList<>();
- for (Class<?> clss : types.keySet()) {
- classes.add(clss.getName());
- }
- return "Component " + classes + " " + properties + "";
- }
-
- /** A type which has been explicitly exposed by a component. */
- public static class PublishedType<T> {
- private Component<? extends T> component;
- private Class<T> clss;
-
- private CompletableFuture<T> value;
-
- public PublishedType(Component<? extends T> component, Class<T> clss) {
- this.clss = clss;
- this.component = component;
- value = CompletableFuture.completedFuture((T) component.instance);
- }
-
- public Component<?> getPublisher() {
- return component;
- }
-
- public Class<T> getType() {
- return clss;
- }
-
- public CompletionStage<T> getValue() {
- return value.minimalCompletionStage();
- }
- }
-
- /** Builds a {@link Component}. */
- public static class Builder<I> implements Supplier<I> {
- private final I instance;
-
- private Runnable init;
- private Runnable close;
-
- private Set<Dependency<?>> dependencies = new HashSet<>();
- private Set<Class<? super I>> types = new HashSet<>();
- private final Map<String, Object> properties = new HashMap<>();
-
- public Builder(I instance) {
- this.instance = instance;
- }
-
- public Component<I> build(ComponentRegister register) {
- // default values
- if (types.isEmpty()) {
- types.add(getInstanceClass());
- }
-
- if (init == null)
- init = () -> {
- };
- if (close == null)
- close = () -> {
- };
-
- // instantiation
- Component<I> component = new Component<I>(register, instance, init, close, dependencies, types, properties);
- for (Dependency<?> dependency : dependencies) {
- dependency.type.getPublisher().addDependant(dependency);
- }
- return component;
- }
-
- public Builder<I> addType(Class<? super I> clss) {
- types.add(clss);
- return this;
- }
-
- public Builder<I> addActivation(Runnable init) {
- if (this.init != null)
- throw new IllegalArgumentException("init method is already set");
- this.init = init;
- return this;
- }
-
- public Builder<I> addDeactivation(Runnable close) {
- if (this.close != null)
- throw new IllegalArgumentException("close method is already set");
- this.close = close;
- return this;
- }
-
- public <D> Builder<I> addDependency(PublishedType<D> type, Consumer<D> set, Consumer<D> unset) {
- dependencies.add(new Dependency<D>(type, set, unset));
- return this;
- }
-
- public void addProperty(String key, Object value) {
- if (properties.containsKey(key))
- throw new IllegalStateException("Key " + key + " is already set.");
- properties.put(key, value);
- }
-
- @Override
- public I get() {
- return instance;
- }
-
- @SuppressWarnings("unchecked")
- private Class<I> getInstanceClass() {
- return (Class<I>) instance.getClass();
- }
-
- }
-
- static class Dependency<D> {
- private PublishedType<D> type;
- private Consumer<D> set;
- private Consumer<D> unset;
-
- // live
- Component<?> dependantComponent;
- CompletableFuture<Void> setStage;
- CompletableFuture<Void> unsetStage;
-
- public Dependency(PublishedType<D> types, Consumer<D> set, Consumer<D> unset) {
- super();
- this.type = types;
- this.set = set != null ? set : t -> {
- };
- this.unset = unset != null ? unset : t -> {
- };
- }
-
- // live
- void setDependantComponent(Component<?> component) {
- this.dependantComponent = component;
- }
-
- CompletableFuture<Void> publisherActivated() {
- return type.getPublisher().activated.copy();
- }
-
- CompletableFuture<Void> dependantDeactivated() {
- return dependantComponent.deactivated.copy();
- }
-
- CompletableFuture<Void> set(Void v) {
- return type.value.thenAccept(set);
- }
-
- CompletableFuture<Void> unset(Void v) {
- return type.value.thenAccept(unset);
- }
-
- }
-}
+++ /dev/null
-package org.argeo.util.register;
-
-import java.util.Map;
-import java.util.SortedSet;
-import java.util.function.Predicate;
-
-/** A register of components which can coordinate their activation. */
-public interface ComponentRegister {
- long register(Component<?> component);
-
- <T> SortedSet<Component<? extends T>> find(Class<T> clss, Predicate<Map<String, Object>> filter);
-
- default <T> Component.PublishedType<T> getSingleton(Class<T> type) {
- SortedSet<Component<? extends T>> found = find(type, null);
- if (found.size() == 0)
- throw new IllegalStateException("No component found for " + type);
- return found.first().getType(type);
- }
-
- default <T> T getObject(Class<T> clss) {
- SortedSet<Component<? extends T>> found = find(clss, null);
- if (found.size() == 0)
- return null;
- return found.first().get();
- }
-
- Component<?> get(Object instance);
-
-// default <T> PublishedType<T> getType(Class<T> clss) {
-// SortedSet<Component<? extends T>> components = find(clss, null);
-// if (components.size() == 0)
-// return null;
-// return components.first().getType(clss);
-// }
-
- void activate();
-
- void deactivate();
-
- boolean isActive();
-
- void clear();
-}
+++ /dev/null
-package org.argeo.util.register;
-
-import java.util.Map;
-import java.util.Objects;
-
-/**
- * Key used to classify and filter available components.
- */
-public class RankingKey implements Comparable<RankingKey> {
- public final static String SERVICE_PID = "service.pid";
- public final static String SERVICE_ID = "service.id";
- public final static String SERVICE_RANKING = "service.ranking";
-
- private String pid;
- private Integer ranking = 0;
- private Long id = 0l;
-
- public RankingKey(String pid, Integer ranking, Long id) {
- super();
- this.pid = pid;
- this.ranking = ranking;
- this.id = id;
- }
-
- public RankingKey(Map<String, Object> properties) {
- this.pid = properties.containsKey(SERVICE_PID) ? properties.get(SERVICE_PID).toString() : null;
- this.ranking = properties.containsKey(SERVICE_RANKING)
- ? Integer.parseInt(properties.get(SERVICE_RANKING).toString())
- : 0;
- this.id = properties.containsKey(SERVICE_ID) ? (Long) properties.get(SERVICE_ID) : null;
- }
-
- @Override
- public int hashCode() {
- Integer result = 0;
- if (pid != null)
- result = +pid.hashCode();
- if (ranking != null)
- result = +ranking;
- return result;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return new RankingKey(pid, ranking, id);
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder("");
- if (pid != null)
- sb.append(pid);
- if (ranking != null && ranking != 0)
- sb.append(' ').append(ranking);
- return sb.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof RankingKey))
- return false;
- RankingKey other = (RankingKey) obj;
- return Objects.equals(pid, other.pid) && Objects.equals(ranking, other.ranking) && Objects.equals(id, other.id);
- }
-
- @Override
- public int compareTo(RankingKey o) {
- if (pid != null && o.pid != null) {
- if (pid.equals(o.pid)) {
- if (ranking.equals(o.ranking))
- if (id != null && o.id != null)
- return id.compareTo(o.id);
- else
- return 0;
- else
- return ranking.compareTo(o.ranking);
- } else {
- return pid.compareTo(o.pid);
- }
-
- } else {
- }
- return -1;
- }
-
- public String getPid() {
- return pid;
- }
-
- public Integer getRanking() {
- return ranking;
- }
-
- public Long getId() {
- return id;
- }
-
- public static RankingKey minPid(String pid) {
- return new RankingKey(pid, Integer.MIN_VALUE, null);
- }
-
- public static RankingKey maxPid(String pid) {
- return new RankingKey(pid, Integer.MAX_VALUE, null);
- }
-}
+++ /dev/null
-package org.argeo.util.register;
-
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Predicate;
-
-/** A minimal component register. */
-public class SimpleRegister implements ComponentRegister {
- private final AtomicBoolean started = new AtomicBoolean(false);
- private final IdentityHashMap<Object, Component<?>> components = new IdentityHashMap<>();
- private final AtomicLong nextServiceId = new AtomicLong(0l);
-
- @Override
- public long register(Component<?> component) {
- return registerComponent(component);
- }
-
- @SuppressWarnings({ "unchecked" })
- @Override
- public synchronized <T> SortedSet<Component<? extends T>> find(Class<T> clss,
- Predicate<Map<String, Object>> filter) {
- SortedSet<Component<? extends T>> result = new TreeSet<>();
- instances: for (Object instance : components.keySet()) {
- if (!clss.isAssignableFrom(instance.getClass()))
- continue instances;
- Component<? extends T> component = (Component<? extends T>) components.get(instance);
-
- if (component.isPublishedType(clss)) {
- if (filter != null) {
- filter.test(component.getProperties());
- }
- result.add(component);
- }
- }
- if (result.isEmpty())
- return null;
- return result;
-
- }
-
- synchronized long registerComponent(Component<?> component) {
- if (started.get()) // TODO make it really dynamic
- throw new IllegalStateException("Already activated");
- if (components.containsKey(component.get()))
- throw new IllegalArgumentException("Already registered as component");
- components.put(component.get(), component);
- return nextServiceId.incrementAndGet();
- }
-
- @Override
- public synchronized Component<?> get(Object instance) {
- if (!components.containsKey(instance))
- throw new IllegalArgumentException("Not registered as component");
- return components.get(instance);
- }
-
- @Override
- public synchronized void activate() {
- if (started.get())
- throw new IllegalStateException("Already activated");
- Set<CompletableFuture<?>> constraints = new HashSet<>();
- for (Component<?> component : components.values()) {
- component.startActivating();
- constraints.add(component.getActivated());
- }
-
- // wait
- try {
- CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(true))
- .get();
- } catch (InterruptedException e) {
- throw new RuntimeException("Register activation has been interrupted", e);
- } catch (ExecutionException e) {
- if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
- throw (RuntimeException) e.getCause();
- } else {
- throw new IllegalStateException("Cannot activate register", e.getCause());
- }
- }
- }
-
- @Override
- public synchronized void deactivate() {
- if (!started.get())
- throw new IllegalStateException("Not activated");
- Set<CompletableFuture<?>> constraints = new HashSet<>();
- for (Component<?> component : components.values()) {
- component.startDeactivating();
- constraints.add(component.getDeactivated());
- }
-
- // wait
- try {
- CompletableFuture.allOf(constraints.toArray(new CompletableFuture[0])).thenRun(() -> started.set(false))
- .get();
- } catch (InterruptedException e) {
- throw new RuntimeException("Register deactivation has been interrupted", e);
- } catch (ExecutionException e) {
- if (RuntimeException.class.isAssignableFrom(e.getCause().getClass())) {
- throw (RuntimeException) e.getCause();
- } else {
- throw new IllegalStateException("Cannot deactivate register", e.getCause());
- }
- }
- }
-
- @Override
- public synchronized boolean isActive() {
- return started.get();
- }
-
- @Override
- public synchronized void clear() {
- components.clear();
- }
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public abstract class AbstractWorkingCopy<DATA, ATTR, ID> implements WorkingCopy<DATA, ATTR, ID> {
- private Map<ID, DATA> newData = new HashMap<ID, DATA>();
- private Map<ID, ATTR> modifiedData = new HashMap<ID, ATTR>();
- private Map<ID, DATA> deletedData = new HashMap<ID, DATA>();
-
- protected abstract ID getId(DATA data);
-
- protected abstract ATTR cloneAttributes(DATA data);
-
- public void cleanUp() {
- // clean collections
- newData.clear();
- newData = null;
- modifiedData.clear();
- modifiedData = null;
- deletedData.clear();
- deletedData = null;
- }
-
- public boolean noModifications() {
- return newData.size() == 0 && modifiedData.size() == 0 && deletedData.size() == 0;
- }
-
- public void startEditing(DATA user) {
- ID id = getId(user);
- if (modifiedData.containsKey(id))
- throw new IllegalStateException("Already editing " + id);
- modifiedData.put(id, cloneAttributes(user));
- }
-
- public Map<ID, DATA> getNewData() {
- return newData;
- }
-
- public Map<ID, DATA> getDeletedData() {
- return deletedData;
- }
-
- public Map<ID, ATTR> getModifiedData() {
- return modifiedData;
- }
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-/** JTA transaction status. */
-public class JtaStatusAdapter implements TransactionStatusAdapter<Integer> {
- private static final Integer STATUS_ACTIVE = 0;
- private static final Integer STATUS_COMMITTED = 3;
- private static final Integer STATUS_COMMITTING = 8;
- private static final Integer STATUS_MARKED_ROLLBACK = 1;
- private static final Integer STATUS_NO_TRANSACTION = 6;
- private static final Integer STATUS_PREPARED = 2;
- private static final Integer STATUS_PREPARING = 7;
- private static final Integer STATUS_ROLLEDBACK = 4;
- private static final Integer STATUS_ROLLING_BACK = 9;
-// private static final Integer STATUS_UNKNOWN = 5;
-
- @Override
- public Integer getActiveStatus() {
- return STATUS_ACTIVE;
- }
-
- @Override
- public Integer getPreparingStatus() {
- return STATUS_PREPARING;
- }
-
- @Override
- public Integer getMarkedRollbackStatus() {
- return STATUS_MARKED_ROLLBACK;
- }
-
- @Override
- public Integer getPreparedStatus() {
- return STATUS_PREPARED;
- }
-
- @Override
- public Integer getCommittingStatus() {
- return STATUS_COMMITTING;
- }
-
- @Override
- public Integer getCommittedStatus() {
- return STATUS_COMMITTED;
- }
-
- @Override
- public Integer getRollingBackStatus() {
- return STATUS_ROLLING_BACK;
- }
-
- @Override
- public Integer getRolledBackStatus() {
- return STATUS_ROLLEDBACK;
- }
-
- @Override
- public Integer getNoTransactionStatus() {
- return STATUS_NO_TRANSACTION;
- }
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-/** Internal unchecked rollback exception. */
-class SimpleRollbackException extends RuntimeException {
- private static final long serialVersionUID = 8055601819719780566L;
-
- public SimpleRollbackException() {
- super();
- }
-
- public SimpleRollbackException(Throwable cause) {
- super(cause);
- }
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-/** Simple implementation of an XA transaction. */
-class SimpleTransaction<T>
-//implements Transaction, Status
-{
- private final Xid xid;
- private T status;
- private final List<XAResource> xaResources = new ArrayList<XAResource>();
-
- private final SimpleTransactionManager transactionManager;
- private TransactionStatusAdapter<T> tsa;
-
- public SimpleTransaction(SimpleTransactionManager transactionManager, TransactionStatusAdapter<T> tsa) {
- this.tsa = tsa;
- this.status = tsa.getActiveStatus();
- this.xid = new UuidXid();
- this.transactionManager = transactionManager;
- }
-
- public synchronized void commit()
-// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
-// SecurityException, IllegalStateException, SystemException
- {
- status = tsa.getPreparingStatus();
- for (XAResource xaRes : xaResources) {
- if (status.equals(tsa.getMarkedRollbackStatus()))
- break;
- try {
- xaRes.prepare(xid);
- } catch (XAException e) {
- status = tsa.getMarkedRollbackStatus();
- error("Cannot prepare " + xaRes + " for " + xid, e);
- }
- }
- if (status.equals(tsa.getMarkedRollbackStatus())) {
- rollback();
- throw new SimpleRollbackException();
- }
- status = tsa.getPreparedStatus();
-
- status = tsa.getCommittingStatus();
- for (XAResource xaRes : xaResources) {
- if (status.equals(tsa.getMarkedRollbackStatus()))
- break;
- try {
- xaRes.commit(xid, false);
- } catch (XAException e) {
- status = tsa.getMarkedRollbackStatus();
- error("Cannot prepare " + xaRes + " for " + xid, e);
- }
- }
- if (status.equals(tsa.getMarkedRollbackStatus())) {
- rollback();
- throw new SimpleRollbackException();
- }
-
- // complete
- status = tsa.getCommittedStatus();
- clearResources(XAResource.TMSUCCESS);
- transactionManager.unregister(xid);
- }
-
- public synchronized void rollback()
-// throws IllegalStateException, SystemException
- {
- status = tsa.getRollingBackStatus();
- for (XAResource xaRes : xaResources) {
- try {
- xaRes.rollback(xid);
- } catch (XAException e) {
- error("Cannot rollback " + xaRes + " for " + xid, e);
- }
- }
-
- // complete
- status = tsa.getRolledBackStatus();
- clearResources(XAResource.TMFAIL);
- transactionManager.unregister(xid);
- }
-
- public synchronized boolean enlistResource(XAResource xaRes)
-// throws RollbackException, IllegalStateException, SystemException
- {
- if (xaResources.add(xaRes)) {
- try {
- xaRes.start(getXid(), XAResource.TMNOFLAGS);
- return true;
- } catch (XAException e) {
- error("Cannot enlist " + xaRes, e);
- return false;
- }
- } else
- return false;
- }
-
- public synchronized boolean delistResource(XAResource xaRes, int flag)
-// throws IllegalStateException, SystemException
- {
- if (xaResources.remove(xaRes)) {
- try {
- xaRes.end(getXid(), flag);
- } catch (XAException e) {
- error("Cannot delist " + xaRes, e);
- return false;
- }
- return true;
- } else
- return false;
- }
-
- protected void clearResources(int flag) {
- for (XAResource xaRes : xaResources)
- try {
- xaRes.end(getXid(), flag);
- } catch (XAException e) {
- error("Cannot end " + xaRes, e);
- }
- xaResources.clear();
- }
-
- protected void error(Object obj, Exception e) {
- System.err.println(obj);
- e.printStackTrace();
- }
-
- public synchronized T getStatus()
-// throws SystemException
- {
- return status;
- }
-
-// public void registerSynchronization(Synchronization sync)
-// throws RollbackException, IllegalStateException, SystemException {
-// throw new UnsupportedOperationException();
-// }
-
- public void setRollbackOnly()
-// throws IllegalStateException, SystemException
- {
- status = tsa.getMarkedRollbackStatus();
- }
-
- @Override
- public int hashCode() {
- return xid.hashCode();
- }
-
- Xid getXid() {
- return xid;
- }
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-/**
- * Simple implementation of an XA transaction manager.
- */
-public class SimpleTransactionManager
-// implements TransactionManager, UserTransaction
- implements WorkControl, WorkTransaction {
- private ThreadLocal<SimpleTransaction<Integer>> current = new ThreadLocal<SimpleTransaction<Integer>>();
-
- private Map<Xid, SimpleTransaction<Integer>> knownTransactions = Collections
- .synchronizedMap(new HashMap<Xid, SimpleTransaction<Integer>>());
- private TransactionStatusAdapter<Integer> tsa = new JtaStatusAdapter();
-// private SyncRegistry syncRegistry = new SyncRegistry();
-
- /*
- * WORK IMPLEMENTATION
- */
- @Override
- public <T> T required(Callable<T> work) {
- T res;
- begin();
- try {
- res = work.call();
- commit();
- } catch (Exception e) {
- rollback();
- throw new SimpleRollbackException(e);
- }
- return res;
- }
-
- @Override
- public WorkContext getWorkContext() {
- return new WorkContext() {
-
- @Override
- public void registerXAResource(XAResource resource, String recoveryId) {
- getTransaction().enlistResource(resource);
- }
- };
- }
-
- /*
- * WORK TRANSACTION IMPLEMENTATION
- */
-
- @Override
- public boolean isNoTransactionStatus() {
- return tsa.getNoTransactionStatus().equals(getStatus());
- }
-
- /*
- * JTA IMPLEMENTATION
- */
-
- public void begin()
-// throws NotSupportedException, SystemException
- {
- if (getCurrent() != null)
- throw new UnsupportedOperationException("Nested transactions are not supported");
- SimpleTransaction<Integer> transaction = new SimpleTransaction<Integer>(this, tsa);
- knownTransactions.put(transaction.getXid(), transaction);
- current.set(transaction);
- }
-
- public void commit()
-// throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
-// SecurityException, IllegalStateException, SystemException
- {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().commit();
- }
-
- public int getStatus()
-// throws SystemException
- {
- if (getCurrent() == null)
- return tsa.getNoTransactionStatus();
- return getTransaction().getStatus();
- }
-
- public SimpleTransaction<Integer> getTransaction()
-// throws SystemException
- {
- return getCurrent();
- }
-
- protected SimpleTransaction<Integer> getCurrent()
-// throws SystemException
- {
- SimpleTransaction<Integer> transaction = current.get();
- if (transaction == null)
- return null;
- Integer status = transaction.getStatus();
- if (status.equals(tsa.getCommittedStatus()) || status.equals(tsa.getRolledBackStatus())) {
- current.remove();
- return null;
- }
- return transaction;
- }
-
- void unregister(Xid xid) {
- knownTransactions.remove(xid);
- }
-
- public void resume(SimpleTransaction<Integer> tobj)
-// throws InvalidTransactionException, IllegalStateException, SystemException
- {
- if (getCurrent() != null)
- throw new IllegalStateException("Transaction " + current.get() + " already registered");
- current.set(tobj);
- }
-
- public void rollback()
-// throws IllegalStateException, SecurityException, SystemException
- {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().rollback();
- }
-
- public void setRollbackOnly()
-// throws IllegalStateException, SystemException
- {
- if (getCurrent() == null)
- throw new IllegalStateException("No transaction registered with the current thread.");
- getCurrent().setRollbackOnly();
- }
-
- public void setTransactionTimeout(int seconds)
-// throws SystemException
- {
- throw new UnsupportedOperationException();
- }
-
- public SimpleTransaction<Integer> suspend()
-// throws SystemException
- {
- SimpleTransaction<Integer> transaction = getCurrent();
- current.remove();
- return transaction;
- }
-
-// public TransactionSynchronizationRegistry getTsr() {
-// return syncRegistry;
-// }
-//
-// private class SyncRegistry implements TransactionSynchronizationRegistry {
-// @Override
-// public Object getTransactionKey() {
-// try {
-// SimpleTransaction transaction = getCurrent();
-// if (transaction == null)
-// return null;
-// return getCurrent().getXid();
-// } catch (SystemException e) {
-// throw new IllegalStateException("Cannot get transaction key", e);
-// }
-// }
-//
-// @Override
-// public void putResource(Object key, Object value) {
-// throw new UnsupportedOperationException();
-// }
-//
-// @Override
-// public Object getResource(Object key) {
-// throw new UnsupportedOperationException();
-// }
-//
-// @Override
-// public void registerInterposedSynchronization(Synchronization sync) {
-// throw new UnsupportedOperationException();
-// }
-//
-// @Override
-// public int getTransactionStatus() {
-// try {
-// return getStatus();
-// } catch (SystemException e) {
-// throw new IllegalStateException("Cannot get status", e);
-// }
-// }
-//
-// @Override
-// public boolean getRollbackOnly() {
-// try {
-// return getStatus() == Status.STATUS_MARKED_ROLLBACK;
-// } catch (SystemException e) {
-// throw new IllegalStateException("Cannot get status", e);
-// }
-// }
-//
-// @Override
-// public void setRollbackOnly() {
-// try {
-// getCurrent().setRollbackOnly();
-// } catch (Exception e) {
-// throw new IllegalStateException("Cannot set rollback only", e);
-// }
-// }
-//
-// }
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-/** Abstract the various approaches to represent transaction status. */
-public interface TransactionStatusAdapter<T> {
- T getActiveStatus();
-
- T getPreparingStatus();
-
- T getMarkedRollbackStatus();
-
- T getPreparedStatus();
-
- T getCommittingStatus();
-
- T getCommittedStatus();
-
- T getRollingBackStatus();
-
- T getRolledBackStatus();
-
- T getNoTransactionStatus();
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.io.Serializable;
-import java.nio.ByteBuffer;
-import java.util.Arrays;
-import java.util.UUID;
-
-import javax.transaction.xa.Xid;
-
-/**
- * Implementation of {@link Xid} based on {@link UUID}, using max significant
- * bits as global transaction id, and least significant bits as branch
- * qualifier.
- */
-public class UuidXid implements Xid, Serializable {
- private static final long serialVersionUID = -5380531989917886819L;
- public final static int FORMAT = (int) serialVersionUID;
-
- private final static int BYTES_PER_LONG = Long.SIZE / Byte.SIZE;
-
- private final int format;
- private final byte[] globalTransactionId;
- private final byte[] branchQualifier;
- private final String uuid;
- private final int hashCode;
-
- public UuidXid() {
- this(UUID.randomUUID());
- }
-
- public UuidXid(UUID uuid) {
- this.format = FORMAT;
- this.globalTransactionId = uuidToBytes(uuid.getMostSignificantBits());
- this.branchQualifier = uuidToBytes(uuid.getLeastSignificantBits());
- this.uuid = uuid.toString();
- this.hashCode = uuid.hashCode();
- }
-
- public UuidXid(Xid xid) {
- this(xid.getFormatId(), xid.getGlobalTransactionId(), xid
- .getBranchQualifier());
- }
-
- private UuidXid(int format, byte[] globalTransactionId,
- byte[] branchQualifier) {
- this.format = format;
- this.globalTransactionId = globalTransactionId;
- this.branchQualifier = branchQualifier;
- this.uuid = bytesToUUID(globalTransactionId, branchQualifier)
- .toString();
- this.hashCode = uuid.hashCode();
- }
-
- @Override
- public int getFormatId() {
- return format;
- }
-
- @Override
- public byte[] getGlobalTransactionId() {
- return Arrays.copyOf(globalTransactionId, globalTransactionId.length);
- }
-
- @Override
- public byte[] getBranchQualifier() {
- return Arrays.copyOf(branchQualifier, branchQualifier.length);
- }
-
- @Override
- public int hashCode() {
- return hashCode;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj instanceof UuidXid) {
- UuidXid that = (UuidXid) obj;
- return Arrays.equals(globalTransactionId, that.globalTransactionId)
- && Arrays.equals(branchQualifier, that.branchQualifier);
- }
- if (obj instanceof Xid) {
- Xid that = (Xid) obj;
- return Arrays.equals(globalTransactionId,
- that.getGlobalTransactionId())
- && Arrays
- .equals(branchQualifier, that.getBranchQualifier());
- }
- return uuid.equals(obj.toString());
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return new UuidXid(format, globalTransactionId, branchQualifier);
- }
-
- @Override
- public String toString() {
- return uuid;
- }
-
- public UUID asUuid() {
- return bytesToUUID(globalTransactionId, branchQualifier);
- }
-
- public static byte[] uuidToBytes(long bits) {
- ByteBuffer buffer = ByteBuffer.allocate(BYTES_PER_LONG);
- buffer.putLong(0, bits);
- return buffer.array();
- }
-
- public static UUID bytesToUUID(byte[] most, byte[] least) {
- if (most.length < BYTES_PER_LONG)
- most = Arrays.copyOf(most, BYTES_PER_LONG);
- if (least.length < BYTES_PER_LONG)
- least = Arrays.copyOf(least, BYTES_PER_LONG);
- ByteBuffer buffer = ByteBuffer.allocate(2 * BYTES_PER_LONG);
- buffer.put(most, 0, BYTES_PER_LONG);
- buffer.put(least, 0, BYTES_PER_LONG);
- buffer.flip();
- return new UUID(buffer.getLong(), buffer.getLong());
- }
-
- // public static void main(String[] args) {
- // UUID uuid = UUID.randomUUID();
- // System.out.println(uuid);
- // uuid = bytesToUUID(uuidToBytes(uuid.getMostSignificantBits()),
- // uuidToBytes(uuid.getLeastSignificantBits()));
- // System.out.println(uuid);
- // }
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import javax.transaction.xa.XAResource;
-
-/**
- * A minimalistic interface similar to OSGi transaction context in order to
- * register XA resources.
- */
-public interface WorkContext {
- void registerXAResource(XAResource resource, String recoveryId);
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.concurrent.Callable;
-
-/**
- * A minimalistic interface inspired by OSGi transaction control in order to
- * commit units of work externally.
- */
-public interface WorkControl {
- <T> T required(Callable<T> work);
-
- void setRollbackOnly();
-
- WorkContext getWorkContext();
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-/**
- * A minimalistic interface inspired by JTA user transaction in order to commit
- * units of work externally.
- */
-public interface WorkTransaction {
- void begin();
-
- void commit();
-
- void rollback();
-
- boolean isNoTransactionStatus();
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.Map;
-
-public interface WorkingCopy<DATA, ATTR, ID> {
- void startEditing(DATA user);
-
- boolean noModifications();
-
- void cleanUp();
-
- Map<ID, DATA> getNewData();
-
- Map<ID, DATA> getDeletedData();
-
- Map<ID, ATTR> getModifiedData();
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-public interface WorkingCopyProcessor<WC extends WorkingCopy<?, ?, ?>> {
- void prepare(WC wc);
-
- void commit(WC wc);
-
- void rollback(WC wc);
-
- WC newWorkingCopy();
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-/** {@link XAResource} for a user directory being edited. */
-public class WorkingCopyXaResource<WC extends WorkingCopy<?, ?, ?>> implements XAResource {
- private final WorkingCopyProcessor<WC> processor;
-
- private Map<Xid, WC> workingCopies = new HashMap<Xid, WC>();
- private Xid editingXid = null;
- private int transactionTimeout = 0;
-
- public WorkingCopyXaResource(WorkingCopyProcessor<WC> processor) {
- this.processor = processor;
- }
-
- @Override
- public synchronized void start(Xid xid, int flags) throws XAException {
- if (editingXid != null)
- throw new IllegalStateException("Already editing " + editingXid);
- WC wc = workingCopies.put(xid, processor.newWorkingCopy());
- if (wc != null)
- throw new IllegalStateException("There is already a working copy for " + xid);
- this.editingXid = xid;
- }
-
- @Override
- public void end(Xid xid, int flags) throws XAException {
- checkXid(xid);
- }
-
- private WC wc(Xid xid) {
- return workingCopies.get(xid);
- }
-
- public synchronized WC wc() {
- if (editingXid == null)
- return null;
- WC wc = workingCopies.get(editingXid);
- if (wc == null)
- throw new IllegalStateException("No working copy found for " + editingXid);
- return wc;
- }
-
- private synchronized void cleanUp(Xid xid) {
- WC wc = workingCopies.get(xid);
- if (wc != null) {
- wc.cleanUp();
- workingCopies.remove(xid);
- }
- editingXid = null;
- }
-
- @Override
- public int prepare(Xid xid) throws XAException {
- checkXid(xid);
- WC wc = wc(xid);
- if (wc.noModifications())
- return XA_RDONLY;
- try {
- processor.prepare(wc);
- } catch (Exception e) {
- e.printStackTrace();
- throw new XAException(XAException.XAER_RMERR);
- }
- return XA_OK;
- }
-
- @Override
- public void commit(Xid xid, boolean onePhase) throws XAException {
- try {
- checkXid(xid);
- WC wc = wc(xid);
- if (wc.noModifications())
- return;
- if (onePhase)
- processor.prepare(wc);
- processor.commit(wc);
- } catch (Exception e) {
- e.printStackTrace();
- throw new XAException(XAException.XAER_RMERR);
- } finally {
- cleanUp(xid);
- }
- }
-
- @Override
- public void rollback(Xid xid) throws XAException {
- try {
- checkXid(xid);
- processor.rollback(wc(xid));
- } catch (Exception e) {
- e.printStackTrace();
- throw new XAException(XAException.XAER_RMERR);
- } finally {
- cleanUp(xid);
- }
- }
-
- @Override
- public void forget(Xid xid) throws XAException {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isSameRM(XAResource xares) throws XAException {
- return xares == this;
- }
-
- @Override
- public Xid[] recover(int flag) throws XAException {
- return new Xid[0];
- }
-
- @Override
- public int getTransactionTimeout() throws XAException {
- return transactionTimeout;
- }
-
- @Override
- public boolean setTransactionTimeout(int seconds) throws XAException {
- transactionTimeout = seconds;
- return true;
- }
-
- private void checkXid(Xid xid) throws XAException {
- if (xid == null)
- throw new XAException(XAException.XAER_OUTSIDE);
- if (!xid.equals(xid))
- throw new XAException(XAException.XAER_NOTA);
- }
-
-}
+++ /dev/null
-package org.argeo.util.transaction;
-
-import javax.transaction.xa.XAResource;
-
-public interface XAResourceProvider {
- XAResource getXaResource();
-}
+++ /dev/null
-/** Minimalistic and partial XA transaction manager implementation. */
-package org.argeo.util.transaction;
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.cms.lib.equinox</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ds.core.builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" activate="start" deactivate="stop" name="Jetty Service Factory">
+ <implementation class="org.argeo.cms.equinox.http.jetty.EquinoxJettyServer"/>
+ <property name="service.pid" type="String" value="org.argeo.equinox.jetty.config"/>
+ <reference bind="setCmsState" cardinality="1..1" interface="org.argeo.api.cms.CmsState" name="CmsState" policy="static"/>
+ <service>
+ <provide interface="com.sun.net.httpserver.HttpServer"/>
+ </service>
+</scr:component>
--- /dev/null
+Service-Component: \
+OSGI-INF/jettyServiceFactory.xml,\
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+package org.argeo.cms.equinox.http.jetty;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionIdListener;
+import javax.servlet.http.HttpSessionListener;
+
+import org.argeo.cms.jetty.CmsJettyServer;
+import org.eclipse.equinox.http.servlet.HttpServiceServlet;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.osgi.framework.Constants;
+
+/** A {@link CmsJettyServer} integrating with Equinox HTTP framework. */
+public class EquinoxJettyServer extends CmsJettyServer {
+ private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
+
+ @Override
+ protected void addServlets(ServletContextHandler rootContextHandler) throws ServletException {
+ ServletHolder holder = new ServletHolder(new InternalHttpServiceServlet());
+ holder.setInitOrder(0);
+ holder.setInitParameter(Constants.SERVICE_VENDOR, "Eclipse.org"); //$NON-NLS-1$
+ holder.setInitParameter(Constants.SERVICE_DESCRIPTION, "Equinox Jetty-based Http Service"); //$NON-NLS-1$
+
+ rootContextHandler.addServlet(holder, "/*");
+
+ // post-start
+ SessionHandler sessionManager = rootContextHandler.getSessionHandler();
+ sessionManager.addEventListener((HttpSessionIdListener) holder.getServlet());
+ }
+
+ public static class InternalHttpServiceServlet implements HttpSessionListener, HttpSessionIdListener, Servlet {
+ private final Servlet httpServiceServlet = new HttpServiceServlet();
+ private ClassLoader contextLoader;
+ private final Method sessionDestroyed;
+ private final Method sessionIdChanged;
+
+ public InternalHttpServiceServlet() {
+ Class<?> clazz = httpServiceServlet.getClass();
+
+ try {
+ sessionDestroyed = clazz.getMethod("sessionDestroyed", new Class<?>[] { String.class }); //$NON-NLS-1$
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ try {
+ sessionIdChanged = clazz.getMethod("sessionIdChanged", new Class<?>[] { String.class }); //$NON-NLS-1$
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Override
+ public void init(ServletConfig config) throws ServletException {
+ ServletContext context = config.getServletContext();
+ contextLoader = (ClassLoader) context.getAttribute(INTERNAL_CONTEXT_CLASSLOADER);
+
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.init(config);
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.destroy();
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ contextLoader = null;
+ }
+
+ @Override
+ public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ httpServiceServlet.service(req, res);
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+
+ @Override
+ public ServletConfig getServletConfig() {
+ return httpServiceServlet.getServletConfig();
+ }
+
+ @Override
+ public String getServletInfo() {
+ return httpServiceServlet.getServletInfo();
+ }
+
+ @Override
+ public void sessionCreated(HttpSessionEvent event) {
+ // Nothing to do.
+ }
+
+ @Override
+ public void sessionDestroyed(HttpSessionEvent event) {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ sessionDestroyed.invoke(httpServiceServlet, event.getSession().getId());
+ } catch (IllegalAccessException | IllegalArgumentException e) {
+ // not likely
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+
+ @Override
+ public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
+ Thread thread = Thread.currentThread();
+ ClassLoader current = thread.getContextClassLoader();
+ thread.setContextClassLoader(contextLoader);
+ try {
+ sessionIdChanged.invoke(httpServiceServlet, oldSessionId);
+ } catch (IllegalAccessException | IllegalArgumentException e) {
+ // not likely
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e.getCause());
+ } finally {
+ thread.setContextClassLoader(current);
+ }
+ }
+ }
+
+}
--- /dev/null
+package org.argeo.cms.servlet.internal.jetty;
+
+import java.io.File;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ForkJoinPool;
+
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+import org.argeo.api.cms.CmsConstants;
+import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.CmsState;
+import org.argeo.cms.CmsDeployProperty;
+import org.argeo.cms.util.LangUtils;
+import org.argeo.cms.websocket.server.CmsWebSocketConfigurator;
+import org.argeo.cms.websocket.server.TestEndpoint;
+import org.eclipse.equinox.http.jetty.JettyConfigurator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class JettyConfig {
+ private final static CmsLog log = CmsLog.getLog(JettyConfig.class);
+
+ final static String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer";
+
+ private CmsState cmsState;
+
+ private final BundleContext bc = FrameworkUtil.getBundle(JettyConfig.class).getBundleContext();
+
+ // private static final String JETTY_PROPERTY_PREFIX =
+ // "org.eclipse.equinox.http.jetty.";
+
+ public void start() {
+ // We need to start asynchronously so that Jetty bundle get started by lazy init
+ // due to the non-configurable behaviour of its activator
+ ForkJoinPool.commonPool().execute(() -> {
+ Dictionary<String, Object> properties = getHttpServerConfig();
+ startServer(properties);
+ });
+
+ ServiceTracker<ServerContainer, ServerContainer> serverSt = new ServiceTracker<ServerContainer, ServerContainer>(
+ bc, ServerContainer.class, null) {
+
+ @Override
+ public ServerContainer addingService(ServiceReference<ServerContainer> reference) {
+ ServerContainer serverContainer = super.addingService(reference);
+
+ BundleContext bc = reference.getBundle().getBundleContext();
+ ServiceReference<ServerEndpointConfig.Configurator> srConfigurator = bc
+ .getServiceReference(ServerEndpointConfig.Configurator.class);
+ ServerEndpointConfig.Configurator endpointConfigurator = bc.getService(srConfigurator);
+ ServerEndpointConfig config = ServerEndpointConfig.Builder
+ .create(TestEndpoint.class, "/ws/test/events/").configurator(endpointConfigurator).build();
+ try {
+ serverContainer.addEndpoint(config);
+ } catch (DeploymentException e) {
+ throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
+ }
+ return serverContainer;
+ }
+
+ };
+ serverSt.open();
+
+ // check initialisation
+// ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
+//
+// @Override
+// public HttpService addingService(ServiceReference<HttpService> sr) {
+// Object httpPort = sr.getProperty("http.port");
+// Object httpsPort = sr.getProperty("https.port");
+// log.info(httpPortsMsg(httpPort, httpsPort));
+// close();
+// return super.addingService(sr);
+// }
+// };
+// httpSt.open();
+ }
+
+ public void stop() {
+ try {
+ JettyConfigurator.stopServer(CmsConstants.DEFAULT);
+ } catch (Exception e) {
+ log.error("Cannot stop default Jetty server.", e);
+ }
+
+ }
+
+ public void startServer(Dictionary<String, Object> properties) {
+ // Explicitly configures Jetty so that the default server is not started by the
+ // activator of the Equinox Jetty bundle.
+ Map<String, String> config = LangUtils.dictToStringMap(properties);
+ if (!config.isEmpty()) {
+ config.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS);
+
+ // TODO centralise with Jetty extender
+ Object webSocketEnabled = config.get(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty());
+ if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
+ bc.registerService(ServerEndpointConfig.Configurator.class, new CmsWebSocketConfigurator(), null);
+ // config.put(WEBSOCKET_ENABLED, "true");
+ }
+ }
+
+ properties.put(Constants.SERVICE_PID, "default");
+ File jettyWorkDir = new File(bc.getDataFile(""), "jettywork"); //$NON-NLS-1$
+ jettyWorkDir.mkdir();
+
+// HttpServerManager serverManager = new HttpServerManager(jettyWorkDir);
+// try {
+// serverManager.updated("default", properties);
+// } catch (ConfigurationException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+ Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
+ Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
+ log.info(httpPortsMsg(httpPort, httpsPort));
+
+// long begin = System.currentTimeMillis();
+// int tryCount = 60;
+// try {
+// while (tryCount > 0) {
+// try {
+// // FIXME deal with multiple ids
+// JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config));
+//
+// Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
+// Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
+// log.info(httpPortsMsg(httpPort, httpsPort));
+//
+// // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi
+// // configuration is not cleaned
+// FrameworkUtil.getBundle(JettyConfigurator.class).start();
+// return;
+// } catch (IllegalStateException e) {
+// // e.printStackTrace();
+// // Jetty may not be ready
+// try {
+// Thread.sleep(1000);
+// } catch (Exception e1) {
+// // silent
+// }
+// tryCount--;
+// }
+// }
+// long duration = System.currentTimeMillis() - begin;
+// log.error("Gave up with starting Jetty server after " + (duration / 1000) + " s");
+// } catch (Exception e) {
+// log.error("Cannot start default Jetty server with config " + properties, e);
+// }
+
+ }
+
+ private String httpPortsMsg(Object httpPort, Object httpsPort) {
+ return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : "");
+ }
+
+ /** Override the provided config with the framework properties */
+ public Dictionary<String, Object> getHttpServerConfig() {
+ String httpPort = getFrameworkProp(CmsDeployProperty.HTTP_PORT);
+ String httpsPort = getFrameworkProp(CmsDeployProperty.HTTPS_PORT);
+ /// TODO make it more generic
+ String httpHost = getFrameworkProp(CmsDeployProperty.HOST);
+// String httpsHost = getFrameworkProp(
+// JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
+ String webSocketEnabled = getFrameworkProp(CmsDeployProperty.WEBSOCKET_ENABLED);
+
+ final Hashtable<String, Object> props = new Hashtable<String, Object>();
+ // try {
+ if (httpPort != null || httpsPort != null) {
+ boolean httpEnabled = httpPort != null;
+ props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled);
+ boolean httpsEnabled = httpsPort != null;
+ props.put(JettyHttpConstants.HTTPS_ENABLED, httpsEnabled);
+
+ if (httpEnabled) {
+ props.put(JettyHttpConstants.HTTP_PORT, httpPort);
+ if (httpHost != null)
+ props.put(JettyHttpConstants.HTTP_HOST, httpHost);
+ }
+
+ if (httpsEnabled) {
+ props.put(JettyHttpConstants.HTTPS_PORT, httpsPort);
+ if (httpHost != null)
+ props.put(JettyHttpConstants.HTTPS_HOST, httpHost);
+
+ // keystore
+ props.put(JettyHttpConstants.SSL_KEYSTORETYPE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORETYPE));
+ props.put(JettyHttpConstants.SSL_KEYSTORE, getFrameworkProp(CmsDeployProperty.SSL_KEYSTORE));
+ props.put(JettyHttpConstants.SSL_PASSWORD, getFrameworkProp(CmsDeployProperty.SSL_PASSWORD));
+
+ // truststore
+ props.put(JettyHttpConstants.SSL_TRUSTSTORETYPE,
+ getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORETYPE));
+ props.put(JettyHttpConstants.SSL_TRUSTSTORE, getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORE));
+ props.put(JettyHttpConstants.SSL_TRUSTSTOREPASSWORD,
+ getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTOREPASSWORD));
+
+ // client certificate authentication
+ String wantClientAuth = getFrameworkProp(CmsDeployProperty.SSL_WANTCLIENTAUTH);
+ if (wantClientAuth != null)
+ props.put(JettyHttpConstants.SSL_WANTCLIENTAUTH, Boolean.parseBoolean(wantClientAuth));
+ String needClientAuth = getFrameworkProp(CmsDeployProperty.SSL_NEEDCLIENTAUTH);
+ if (needClientAuth != null)
+ props.put(JettyHttpConstants.SSL_NEEDCLIENTAUTH, Boolean.parseBoolean(needClientAuth));
+ }
+
+ // web socket
+ if (webSocketEnabled != null && webSocketEnabled.equals("true"))
+ props.put(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty(), true);
+
+ props.put(CmsConstants.CN, CmsConstants.DEFAULT);
+ }
+ return props;
+ }
+
+ private String getFrameworkProp(CmsDeployProperty deployProperty) {
+ return cmsState.getDeployProperty(deployProperty.getProperty());
+ }
+
+ public void setCmsState(CmsState cmsState) {
+ this.cmsState = cmsState;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.servlet.internal.jetty;
+
+/** Compatible with Jetty. */
+interface JettyHttpConstants {
+ static final String HTTP_ENABLED = "http.enabled";
+ static final String HTTP_PORT = "http.port";
+ static final String HTTP_HOST = "http.host";
+ static final String HTTPS_ENABLED = "https.enabled";
+ static final String HTTPS_HOST = "https.host";
+ static final String HTTPS_PORT = "https.port";
+ static final String SSL_KEYSTORE = "ssl.keystore";
+ static final String SSL_PASSWORD = "ssl.password";
+ static final String SSL_KEYPASSWORD = "ssl.keypassword";
+ static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth";
+ static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth";
+ static final String SSL_PROTOCOL = "ssl.protocol";
+ static final String SSL_ALGORITHM = "ssl.algorithm";
+ static final String SSL_KEYSTORETYPE = "ssl.keystoretype";
+
+ // Argeo
+ static final String SSL_TRUSTSTORE = "ssl.truststore";
+ static final String SSL_TRUSTSTOREPASSWORD = "ssl.truststorepassword";
+ static final String SSL_TRUSTSTORETYPE = "ssl.truststoretype";
+
+}
--- /dev/null
+package org.argeo.equinox.jetty;
+
+import java.util.Dictionary;
+
+import javax.servlet.ServletContext;
+import javax.websocket.DeploymentException;
+import javax.websocket.server.ServerContainer;
+
+import org.eclipse.equinox.http.jetty.JettyCustomizer;
+import org.eclipse.jetty.server.ConnectionFactory;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
+import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+
+/** Customises the Jetty HTTP server. */
+public class CmsJettyCustomizer extends JettyCustomizer {
+ static final String SSL_TRUSTSTORE = "ssl.truststore";
+ static final String SSL_TRUSTSTOREPASSWORD = "ssl.truststorepassword";
+ static final String SSL_TRUSTSTORETYPE = "ssl.truststoretype";
+
+ private BundleContext bc = FrameworkUtil.getBundle(CmsJettyCustomizer.class).getBundleContext();
+
+ public final static String WEBSOCKET_ENABLED = "argeo.websocket.enabled";
+
+ @Override
+ public Object customizeContext(Object context, Dictionary<String, ?> settings) {
+ // WebSocket
+ Object webSocketEnabled = settings.get(WEBSOCKET_ENABLED);
+ if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) {
+ ServletContextHandler servletContextHandler = (ServletContextHandler) context;
+ JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
+
+ @Override
+ public void accept(ServletContext servletContext, ServerContainer serverContainer)
+ throws DeploymentException {
+ bc.registerService(javax.websocket.server.ServerContainer.class, serverContainer, null);
+ }
+ });
+ }
+ return super.customizeContext(context, settings);
+
+ }
+
+ @Override
+ public Object customizeHttpsConnector(Object connector, Dictionary<String, ?> settings) {
+ ServerConnector httpsConnector = (ServerConnector) connector;
+ if (httpsConnector != null)
+ for (ConnectionFactory connectionFactory : httpsConnector.getConnectionFactories()) {
+ if (connectionFactory instanceof SslConnectionFactory) {
+ SslContextFactory.Server sslContextFactory = ((SslConnectionFactory) connectionFactory)
+ .getSslContextFactory();
+ sslContextFactory.setTrustStorePath((String) settings.get(SSL_TRUSTSTORE));
+ sslContextFactory.setTrustStoreType((String) settings.get(SSL_TRUSTSTORETYPE));
+ sslContextFactory.setTrustStorePassword((String) settings.get(SSL_TRUSTSTOREPASSWORD));
+ }
+ }
+ return super.customizeHttpsConnector(connector, settings);
+ }
+
+}
--- /dev/null
+/** Equinox Jetty extensions. */
+package org.argeo.equinox.jetty;
\ No newline at end of file
-Subproject commit 639ffc61c03f6aebf9cfe5e0f79dd0c4c6aa632a
+Subproject commit 5bf388711048a659992c292c4b9bdcbc595e066b
major=2
minor=3
-micro=9
+micro=14
qualifier=.next
\ No newline at end of file
org.argeo.cms.lib.equinox,\
org.argeo.cms.lib.jetty,\
-argeo.osgi.start.4=\
-org.argeo.cms.jcr
-
-argeo.osgi.start.5.node=\
-org.argeo.cms.e4.rap
# Local
argeo.node.repo.type=h2
--- /dev/null
+!bin/
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+curl $(cat $XDG_RUNTIME_DIR/argeo.rcp.url)$1
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+java -Dorg.argeo.api.cli.rootCommand=$0 -jar /usr/share/a2/org.argeo.cms/org.argeo.cms.cli.2.3.jar "$@"
\ No newline at end of file
[Unit]
Description=Argeo node %I
-After=network.target
+After=network-online.target
Wants=postgresql.service
[Service]
Type=simple
+
+User=daemon
+Group=daemon
+
StateDirectory=argeo.d/%I
LogsDirectory=argeo.d/%I
ConfigurationDirectory=argeo.d/%I
CacheDirectory=argeo.d/%I
WorkingDirectory=/var/lib/argeo.d/%I
-ExecStart=/usr/lib/jvm/java-17-openjdk-amd64/bin/java \
+ExecStart=java \
-Dosgi.configuration.cascaded=true \
-Dosgi.sharedConfiguration.area=/etc/argeo.d/%I/ \
-Dosgi.sharedConfiguration.area.readOnly=true \
--Dosgi.configuration.area=/var/lib/argeo.d/%I/state/ \
--Dosgi.instance.area=/var/lib/argeo.d/%I/data/ \
--Dargeo.node.repo.indexesBase=/var/cache/argeo.d/%I/indexes \
+-Dosgi.configuration.area=${STATE_DIRECTORY}/state/ \
+-Dosgi.instance.area=${STATE_DIRECTORY}/data/ \
+-Dargeo.node.repo.indexesBase=${CACHE_DIRECTORY}/indexes \
-Declipse.ignoreApp=true \
-Dosgi.noShutdown=true \
-Dorg.eclipse.equinox.http.jetty.autostart=false \
@/etc/argeo.d/jvm.args \
-@/etc/argeo.d/%I/jvm.args \
+@${CONFIGURATION_DIRECTORY}/jvm.args \
@/usr/share/argeo/jvm.args
+
# Exit codes of the JVM when SIGTERM or SIGINT have been caught:
SuccessExitStatus=143 130
+CPUAccounting=true
+MemoryAccounting=true
+TasksAccounting=true
+IOAccounting=true
+IPAccounting=true
+
[Install]
WantedBy=multi-user.target
--- /dev/null
+[Unit]
+Description=Argeo user node %I
+
+[Service]
+Type=simple
+StateDirectory=argeo.d/%I
+LogsDirectory=argeo.d/%I
+ConfigurationDirectory=argeo.d/%I
+CacheDirectory=argeo.d/%I
+#WorkingDirectory=
+
+ExecStart=java \
+-Dosgi.configuration.cascaded=true \
+-Dosgi.sharedConfiguration.area=/etc/argeo.user.d/%I/ \
+-Dosgi.sharedConfiguration.area.readOnly=true \
+-Dosgi.configuration.area=${STATE_DIRECTORY}/state/ \
+-Dosgi.instance.area=${STATE_DIRECTORY}/data/ \
+-Dargeo.node.repo.indexesBase=${CACHE_DIRECTORY}/indexes \
+-Declipse.ignoreApp=true \
+-Dosgi.noShutdown=true \
+-Dorg.eclipse.equinox.http.jetty.autostart=false \
+-Djava.library.path=/usr/lib/a2/swt/rcp/org.argeo.tp.swt/ \
+@/etc/argeo.user.d/jvm.args \
+@/etc/argeo.user.d/%I/jvm.args \
+@/usr/share/argeo/jvm.args
+# Exit codes of the JVM when SIGTERM or SIGINT have been caught:
+SuccessExitStatus=143 130
+
+[Install]
+WantedBy=multi-user.target
--cp /usr/share/a2/osgi/equinox/org.argeo.tp.osgi/org.eclipse.osgi.3.17.jar:/usr/share/a2/org.argeo.cms/org.argeo.init.2.1.jar org.argeo.init.Service
\ No newline at end of file
+-cp /usr/share/a2/osgi/equinox/org.argeo.tp.osgi/org.eclipse.osgi.3.18.jar:/usr/share/a2/org.argeo.cms/org.argeo.init.2.3.jar org.argeo.init.Service
\ No newline at end of file
+++ /dev/null
-/MANIFEST.MF
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="Home Repository">
- <implementation class="org.argeo.cms.e4.OsgiFilterContextFunction"/>
- <property name="service.context.key" type="String" value="(cn=ego)"/>
- <service>
- <provide interface="org.eclipse.e4.core.contexts.IContextFunction"/>
- </service>
-</scr:component>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" name="User Admin Wrapper">
- <implementation class="org.argeo.cms.e4.users.UserAdminWrapper"/>
- <reference bind="setUserTransaction" cardinality="1..1" interface="org.argeo.util.transaction.WorkTransaction" name="UserTransaction" policy="static"/>
- <reference bind="setUserAdmin" cardinality="1..1" interface="org.osgi.service.useradmin.UserAdmin" name="UserAdmin" policy="static"/>
- <service>
- <provide interface="org.argeo.cms.e4.users.UserAdminWrapper"/>
- </service>
- <reference bind="addUserDirectory" cardinality="0..n" interface="org.argeo.osgi.useradmin.UserDirectory" name="UserDirectory" policy="static" unbind="removeUserDirectory"/>
-</scr:component>
-Service-Component: OSGI-INF/homeRepository.xml,\
-OSGI-INF/userAdminWrapper.xml,\
-OSGI-INF/defaultCallbackHandler.xml
+Service-Component: OSGI-INF/defaultCallbackHandler.xml
Bundle-ActivationPolicy: lazy
Import-Package: \
org.argeo.api.acr,\
org.eclipse.swt,\
org.eclipse.swt.widgets;version="0.0.0",\
-org.eclipse.e4.ui.model.application.ui,\
-org.eclipse.e4.ui.model.application,\
+org.eclipse.e4.ui.model.application.ui;resolution:=optional,\
+org.eclipse.e4.ui.model.application;resolution:=optional,\
org.argeo.cms,\
org.eclipse.core.commands.common,\
org.eclipse.jface.window,\
org.eclipse.jface.dialogs,\
org.argeo.cms.swt.auth,\
+org.argeo.cms.ux.widgets,\
javax.servlet.*;version="[3,5)",\
+org.eclipse.*;resolution:=optional,\
+javax.*;resolution:=optional,\
*
+++ /dev/null
-<?xml version="1.0" encoding="ASCII"?>
-<application:Application xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:advanced="http://www.eclipse.org/ui/2010/UIModel/application/ui/advanced" xmlns:application="http://www.eclipse.org/ui/2010/UIModel/application" xmlns:basic="http://www.eclipse.org/ui/2010/UIModel/application/ui/basic" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_XqkCQKknEeObFrG_clJBYA" elementId="">
- <children xsi:type="basic:TrimmedWindow" xmi:id="_Zdy6cKknEeObFrG_clJBYA" elementId="org.argeo.cms.e4.apps.admin.trimmedwindow.0" label="" x="10" y="10" width="500" height="500">
- <persistedState key="styleOverride" value="8"/>
- <tags>shellMaximized</tags>
- <tags>auth.cn=admin,ou=roles,ou=node</tags>
- <children xsi:type="advanced:PerspectiveStack" xmi:id="_jXVqsCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.perspectivestack.0" selectedElement="_xOVlsDvOEeiF1foPJZSZkw">
- <children xsi:type="advanced:Perspective" xmi:id="_xOVlsDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.perspective.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png">
- <tags>auth.cn=admin,ou=roles,ou=node</tags>
- <children xsi:type="basic:PartSashContainer" xmi:id="_1tQoEDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partsashcontainer.2" horizontal="true">
- <children xsi:type="basic:PartStack" xmi:id="_vtbKkDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partstack.4" containerData="4000" selectedElement="_9gukYDvOEeiF1foPJZSZkw">
- <children xsi:type="basic:Part" xmi:id="_9gukYDvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.users" containerData="" contributionURI="bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.userssers.UsersView" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/person.png">
- <handlers xmi:id="_0mN68DvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.4" contributionUbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.userse4.users.handlers.NewUser" command="_uL5i4DvjEeiF1foPJZSZkw"/>
- <handlers xmi:id="_ODLdgDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.5" contributbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.userscms.e4.users.handlers.DeleteUsers" command="_xkcMADvjEeiF1foPJZSZkw"/>
- <toolbar xmi:id="_jLWmkDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.toolbar.1">
- <children xsi:type="menu:HandledToolItem" xmi:id="_jy_OUDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.swt/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
- <children xsi:type="menu:HandledToolItem" xmi:id="_9qszMDvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
- </toolbar>
- </children>
- </children>
- <children xsi:type="basic:PartStack" xmi:id="__g1a8DvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partstack.3" containerData="4000">
- <tags>usersEditorArea</tags>
- </children>
- <children xsi:type="basic:PartStack" xmi:id="_-mFn8DvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partstack.5" containerData="2000">
- <children xsi:type="basic:Part" xmi:id="_6etk4DvOEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.part.groups" containerData="" contrbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.usersgeo.cms.e4.users.GroupsView" label="Groups" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png">
- <handlers xmi:id="_cmShoDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.6" cbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.usersg.argeo.cms.e4.users.handlers.NewGroup" command="_uL5i4DvjEeiF1foPJZSZkw"/>
- <handlers xmi:id="_fbYfcDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.users4/org.argeo.cms.e4.users.handlers.DeleteGroups" command="_xkcMADvjEeiF1foPJZSZkw"/>
- <toolbar xmi:id="_Us0rADvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.toolbar.2">
- <children xsi:type="menu:HandledToolItem" xmi:id="_VQTLgDvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.new" label="New" iconURI="platform:/plugin/org.argeo.cms.swt/icons/add.png" command="_uL5i4DvjEeiF1foPJZSZkw"/>
- <children xsi:type="menu:HandledToolItem" xmi:id="_XfME8DvkEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/delete.png" command="_xkcMADvjEeiF1foPJZSZkw"/>
- </toolbar>
- </children>
- </children>
- </children>
- </children>
- <children xsi:type="advanced:Perspective" xmi:id="_jvjWYCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.perspective.data" label="Data" iconURI="platform:/plugin/org.argeo.cms.swt/icons/nodes.gif">
- <children xsi:type="basic:PartSashContainer" xmi:id="_h3tvMCkxEein5vuhpK-Dew" elementId="org.argeo.cms.e4.partsashcontainer.0" selectedElement="_0B9SECkxEein5vuhpK-Dew" horizontal="true">
- <children xsi:type="basic:PartStack" xmi:id="_0B9SECkxEein5vuhpK-Dew" elementId="org.argeo.cms.e4.partstack.0" containerData="4000" selectedElement="_WAjPkCkTEein5vuhpK-Dew">
- <children xsi:type="basic:Part" xmi:id="_WAjPkCkTEein5vuhpK-Dew" elementId="org.argeo.cms.e4.jcrbrowser" containerData="" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrBrowserView" label="JCR" iconURI="platform:/plugin/org.argeo.cms.swt/icons/browser.gif">
- <menus xsi:type="menu:PopupMenu" xmi:id="_eXiUECqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.popupmenu.nodeViewer">
- <children xsi:type="menu:HandledMenuItem" xmi:id="_GVeO8CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.swt/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_fU238CqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_U4o9cCqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.swt/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_Ncxo0CqhEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.remove" label="Remove" iconURI="platform:/plugin/org.argeo.cms.swt/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
- </menus>
- <menus xmi:id="_oRg_ACqTEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.menu.0">
- <tags>ViewMenu</tags>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_yJR8ECqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.refresh" label="Refresh" iconURI="platform:/plugin/org.argeo.cms.swt/icons/refresh.png" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_o6HQECqTEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.addfoldernode" label="Add folder" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addFolder.gif" command="_RgE5cCqREeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_5D7aACqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.rename" label="Rename" iconURI="platform:/plugin/org.argeo.cms.swt/icons/rename.gif" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_7rR2wCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handledmenuitem.delete" label="Delete" iconURI="platform:/plugin/org.argeo.cms.swt/icons/remove.gif" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
- <children xsi:type="menu:HandledMenuItem" xmi:id="_XsHLgFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledmenuitem.0" iconURI="platform:/plugin/org.argeo.cms.swt/icons/addRepo.gif" command="_ZWpasFgQEeiknZQLx-vtnA"/>
- </menus>
- </children>
- </children>
- <children xsi:type="basic:PartStack" xmi:id="_mHrEUCk4Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.partstack.1" containerData="6000">
- <tags>dataExplorer</tags>
- </children>
- </children>
- </children>
- <children xsi:type="advanced:Perspective" xmi:id="_u5ZakFhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.perspective.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif">
- <children xsi:type="basic:PartStack" xmi:id="_7i7t8FhJEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.partstack.6">
- <children xsi:type="basic:Part" xmi:id="_KqRZIFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.modules" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.ModulesView" label="Modules" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif"/>
- <children xsi:type="basic:Part" xmi:id="_dXtIoFhNEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.part.bundles" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.monitoring.BundlesView" label="Bundles" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif"/>
- </children>
- </children>
- <children xsi:type="advanced:Perspective" xmi:id="_ABK2ADsNEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.perspective.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif">
- <children xsi:type="basic:PartSashContainer" xmi:id="_FPimEDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.partsashcontainer.1" horizontal="true">
- <children xsi:type="basic:PartStack" xmi:id="_H93NgDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.partstack.2" containerData="4000">
- <children xsi:type="basic:Part" xmi:id="_Izxh0DsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.part.files" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.files.NodeFsBrowserView" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif"/>
- </children>
- <children xsi:type="basic:Part" xmi:id="_TMqBMDsSEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.part.0" containerData="6000"/>
- </children>
- </children>
- </children>
- <handlers xmi:id="_Vwax0DvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handler.8" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.handlers.OpenPerspective" command="_AF1UsDvrEeiF1foPJZSZkw"/>
- <trimBars xmi:id="_euVxMCk2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.trimbar.0" side="Left">
- <children xsi:type="menu:ToolBar" xmi:id="_fotHsCk2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.toolbar.0">
- <children xsi:type="menu:HandledToolItem" xmi:id="_jCSQgDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.users" label="Users" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png" command="_AF1UsDvrEeiF1foPJZSZkw">
- <tags>auth.cn=admin,ou=roles,ou=node</tags>
- <parameters xmi:id="_lu_uYDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.2" name="perspectiveId" value="org.argeo.cms.e4.perspective.users"/>
- </children>
- <children xsi:type="menu:HandledToolItem" xmi:id="_jfUM4Ck2Eein5vuhpK-Dew" elementId="org.argeo.cms.e4.handledtoolitem.test" label="Data" iconURI="platform:/plugin/org.argeo.cms.swt/icons/nodes.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
- <parameters xmi:id="_KDlXQDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.0" name="perspectiveId" value="org.argeo.cms.e4.perspective.data"/>
- </children>
- <children xsi:type="menu:HandledToolItem" xmi:id="_dhv80FhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.monitoring" label="Monitoring" iconURI="platform:/plugin/org.argeo.cms.swt/icons/bundles.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
- <parameters xmi:id="_kjN0cFhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.parameter.3" name="perspectiveId" value="org.argeo.cms.e4.perspective.monitoring"/>
- </children>
- <children xsi:type="menu:HandledToolItem" xmi:id="_b0OHUDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.handledtoolitem.files" label="Files" iconURI="platform:/plugin/org.argeo.cms.swt/icons/file.gif" command="_AF1UsDvrEeiF1foPJZSZkw">
- <parameters xmi:id="_fXvRYDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.parameter.1" name="perspectiveId" value="org.argeo.cms.e4.perspective.files"/>
- </children>
- <children xsi:type="menu:ToolBarSeparator" xmi:id="_wuoL8FhLEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.toolbarseparator.0"/>
- <children xsi:type="menu:HandledToolItem" xmi:id="_2v8DkFhKEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handledtoolitem.logout" label="Log out" iconURI="platform:/plugin/org.argeo.cms.swt/icons/logout.png" command="_PsWd0FhLEeiknZQLx-vtnA"/>
- </children>
- </trimBars>
- </children>
- <handlers xmi:id="_Xp-P4CqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handler.0" contributionURI="bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.handlerslers.AddFolderNode" command="_RgE5cCqREeidr6NYQH6GbQ"/>
- <handlers xmi:id="_jbnNwCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handler.1" contributionUbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.handlershandlers.DeleteNodes" command="_ChJ-4CqYEeidr6NYQH6GbQ"/>
- <handlers xmi:id="_loxB0CqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handler.2" contributbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.handlersjcr.handlers.Refresh" command="_TOKHsCqYEeidr6NYQH6GbQ"/>
- <handlers xmi:id="_omPfkCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.handler.3" contrbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.handlers.e4.jcr.handlers.RenameNode" command="_ZrcUMCqYEeidr6NYQH6GbQ"/>
- <handlers xmi:id="_dUg-cFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handler.9" cbundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.handlers.cms.e4.jcr.handlers.AddRemoteRepository" command="_ZWpasFgQEeiknZQLx-vtnA"/>
- <handlers xmi:id="_RQyFAFhLEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.handler.10" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.handlers.CloseWorkbench" command="_PsWd0FhLEeiknZQLx-vtnA"/>
- <descriptors xmi:id="_XzfoMCqlEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.partdescriptor.nodeEditor" label="Node Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/node.gif" allowMultiple="true" category="dataExplorer" closeable="true" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.jcr.JcrNodeEditor"/>
- <descriptors xmi:id="_sAdNwDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.userEditor" label="User Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/person.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyable=bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.userscr.e4/org.argeo.cms.e4.users.UserEditor"/>
- <descriptors xmi:id="_5nK7EDvdEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.partdescriptor.groupEditor" label="Group Editor" iconURI="platform:/plugin/org.argeo.cms.swt/icons/group.png" allowMultiple="true" category="usersEditorArea" closeable="true" dirtyabundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.usersms.jcr.e4/org.argeo.cms.e4.users.GroupEditor"/>
- <commands xmi:id="_RgE5cCqREeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.addFolderNode" commandName="Add folder node" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
- <commands xmi:id="_ChJ-4CqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.deleteNodes" commandName="Delete nodes" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
- <commands xmi:id="_TOKHsCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.refreshNodes" commandName="Refresh nodes" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
- <commands xmi:id="_ZrcUMCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.command.renameNode" commandName="Rename node" category="_MDkwUCqYEeidr6NYQH6GbQ"/>
- <commands xmi:id="_uL5i4DvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.command.add" commandName="Add"/>
- <commands xmi:id="_xkcMADvjEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.command.delete" commandName="Delete"/>
- <commands xmi:id="_AF1UsDvrEeiF1foPJZSZkw" elementId="org.argeo.cms.e4.command.openPerspective" commandName="Open Perspective">
- <parameters xmi:id="_F3WAUDvrEeiF1foPJZSZkw" elementId="perspectiveId" name="Perspective Id" optional="false"/>
- </commands>
- <commands xmi:id="_ZWpasFgQEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.command.addRemoteRepository" commandName="Add Remote Repository"/>
- <commands xmi:id="_PsWd0FhLEeiknZQLx-vtnA" elementId="org.argeo.cms.e4.command.logout" commandName="Log out"/>
- <addons xmi:id="_XqkCQaknEeObFrG_clJBYA" elementId="org.eclipse.e4.core.commands.service" contributionURI="bundleclass://org.eclipse.e4.core.commands/org.eclipse.e4.core.commands.CommandServiceAddon"/>
- <addons xmi:id="_XqkCQqknEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.contexts.service" contributionURI="bundleclass://org.eclipse.e4.ui.services/org.eclipse.e4.ui.services.ContextServiceAddon"/>
- <addons xmi:id="_XqkCQ6knEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.bindings.service" contributionURI="bundleclass://org.eclipse.e4.ui.bindings/org.eclipse.e4.ui.bindings.BindingServiceAddon"/>
- <addons xmi:id="_XqkCRKknEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.workbench.commands.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.CommandProcessingAddon"/>
- <addons xmi:id="_XqkCRaknEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.workbench.contexts.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.ContextProcessingAddon"/>
- <addons xmi:id="_XqkCRqknEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.workbench.bindings.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench.swt/org.eclipse.e4.ui.workbench.swt.util.BindingProcessingAddon"/>
- <addons xmi:id="_XqkCR6knEeObFrG_clJBYA" elementId="org.eclipse.e4.ui.workbench.handler.model" contributionURI="bundleclass://org.eclipse.e4.ui.workbench/org.eclipse.e4.ui.internal.workbench.addons.HandlerProcessingAddon"/>
- <addons xmi:id="_8VnK8OdKEeijEOqYKRSeoQ" elementId="org.argeo.cms.e4.addon.locale" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.addons.LocaleAddon"/>
- <addons xmi:id="_-xeJYOdKEeijEOqYKRSeoQ" elementId="org.argeo.cms.e4.addon.auth" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.addons.AuthAddon"/>
- <categories xmi:id="_MDkwUCqYEeidr6NYQH6GbQ" elementId="org.argeo.cms.e4.category.jcrBrowser" name="JCR Browser"/>
-</application:Application>
import javax.servlet.http.HttpServletRequest;
import org.argeo.api.cms.CmsLog;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.swt.CmsException;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
+++ /dev/null
-package org.argeo.cms.e4.files;
-
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.spi.FileSystemProvider;
-
-import javax.annotation.PostConstruct;
-import javax.inject.Inject;
-
-import org.argeo.eclipse.ui.fs.SimpleFsBrowser;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-
-/** Browse the node file system. */
-public class NodeFsBrowserView {
- // public final static String ID = WorkbenchUiPlugin.PLUGIN_ID +
- // ".nodeFsBrowserView";
-
- @Inject
- FileSystemProvider nodeFileSystemProvider;
-
- @PostConstruct
- public void createPartControl(Composite parent) {
- try {
- // URI uri = new URI("node://root:demo@localhost:7070/");
- URI uri = new URI("node:///");
- FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri);
- if (fileSystem == null)
- fileSystem = nodeFileSystemProvider.newFileSystem(uri, null);
- Path nodePath = fileSystem.getPath("/");
-
- Path localPath = Paths.get(System.getProperty("user.home"));
-
- SimpleFsBrowser browser = new SimpleFsBrowser(parent, SWT.NO_FOCUS);
- browser.setInput(nodePath, localPath);
-// AdvancedFsBrowser browser = new AdvancedFsBrowser();
-// browser.createUi(parent, localPath);
- } catch (Exception e) {
- throw new RuntimeException("Cannot open file system browser", e);
- }
- }
-
- public void setFocus() {
- }
-}
+++ /dev/null
-/** Files browser perspective. */
-package org.argeo.cms.e4.files;
\ No newline at end of file
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.security.CryptoKeyring;
-import org.argeo.cms.swt.CmsException;
+import org.argeo.api.cms.keyring.CryptoKeyring;
+import org.argeo.api.cms.transaction.WorkTransaction;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.swt.dialogs.CmsFeedback;
import org.argeo.cms.swt.dialogs.CmsMessageDialog;
-import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
-import org.argeo.util.transaction.WorkTransaction;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
-import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
@Execute
public void execute() {
ChangePasswordDialog dialog = new ChangePasswordDialog(Display.getCurrent().getActiveShell(), userAdmin);
- if (dialog.open() == Dialog.OK) {
+ if (dialog.open() == CmsDialog.OK) {
new CmsMessageDialog(Display.getCurrent().getActiveShell(), passwordChanged.lead(),
CmsMessageDialog.INFORMATION).open();
}
try {
dn = new LdapName(name);
} catch (InvalidNameException e) {
- throw new CmsException("Invalid user dn " + name, e);
+ throw new IllegalArgumentException("Invalid user dn " + name, e);
}
User user = (User) userAdmin.getRole(dn.toString());
if (!user.hasCredential(null, oldPassword))
- throw new CmsException("Invalid password");
+ throw new IllegalArgumentException("Invalid password");
if (Arrays.equals(newPassword, new char[0]))
- throw new CmsException("New password empty");
+ throw new IllegalArgumentException("New password empty");
try {
userTransaction.begin();
user.getCredentials().put(null, newPassword);
if (e instanceof RuntimeException)
throw (RuntimeException) e;
else
- throw new CmsException("Cannot change password", e);
+ throw new IllegalStateException("Cannot change password", e);
}
}
protected void okPressed() {
try {
if (!newPassword1.getText().equals(newPassword2.getText()))
- throw new CmsException("New passwords are different");
+ throw new IllegalArgumentException("New passwords are different");
changePassword(oldPassword.getTextChars(), newPassword1.getTextChars());
- closeShell(OK);
+ closeShell(CmsDialog.OK);
} catch (Exception e) {
- ErrorFeedback.show("Cannot change password", e);
+ CmsFeedback.error("Cannot change password", e);
}
}
package org.argeo.cms.e4.handlers;
-import java.security.AccessController;
-
import javax.security.auth.Subject;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.swt.CmsException;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.util.CurrentSubject;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.ui.workbench.IWorkbench;
}
protected void logout() {
- Subject subject = Subject.getSubject(AccessController.getContext());
+ Subject subject = CurrentSubject.current();
try {
CurrentUser.logoutCmsSession(subject);
} catch (Exception e) {
- throw new CmsException("Cannot log out", e);
+ throw new IllegalStateException("Cannot log out", e);
}
}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import org.argeo.cms.ux.widgets.TreeParent;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
-
-/** A tree element representing a {@link Bundle} */
-class BundleNode extends TreeParent {
- private final Bundle bundle;
-
- public BundleNode(Bundle bundle) {
- this(bundle, false);
- }
-
- @SuppressWarnings("rawtypes")
- public BundleNode(Bundle bundle, boolean hasChildren) {
- super(bundle.getSymbolicName());
- this.bundle = bundle;
-
- if (hasChildren) {
- // REFERENCES
- ServiceReference[] usedServices = bundle.getServicesInUse();
- if (usedServices != null) {
- for (ServiceReference sr : usedServices) {
- if (sr != null)
- addChild(new ServiceReferenceNode(sr, false));
- }
- }
-
- // SERVICES
- ServiceReference[] registeredServices = bundle
- .getRegisteredServices();
- if (registeredServices != null) {
- for (ServiceReference sr : registeredServices) {
- if (sr != null)
- addChild(new ServiceReferenceNode(sr, true));
- }
- }
- }
-
- }
-
- Bundle getBundle() {
- return bundle;
- }
-}
+++ /dev/null
-//package org.argeo.eclipse.ui.workbench.osgi;
-//public class BundlesView {}
-
-package org.argeo.cms.e4.monitoring;
-
-import javax.annotation.PostConstruct;
-
-import org.argeo.eclipse.ui.ColumnViewerComparator;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.eclipse.e4.ui.di.Focus;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-/**
- * Overview of the bundles as a table. Equivalent to Equinox 'ss' console
- * command.
- */
-public class BundlesView {
- private final static BundleContext bc = FrameworkUtil.getBundle(BundlesView.class).getBundleContext();
- private TableViewer viewer;
-
- @PostConstruct
- public void createPartControl(Composite parent) {
- viewer = new TableViewer(parent);
- viewer.setContentProvider(new BundleContentProvider());
- viewer.getTable().setHeaderVisible(true);
-
- EclipseUiSpecificUtils.enableToolTipSupport(viewer);
-
- // ID
- TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(30);
- column.getColumn().setText("ID");
- column.getColumn().setAlignment(SWT.RIGHT);
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -3122136344359358605L;
-
- public String getText(Object element) {
- return Long.toString(((Bundle) element).getBundleId());
- }
- });
- new ColumnViewerComparator(column);
-
- // State
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(18);
- column.getColumn().setText("State");
- column.setLabelProvider(new StateLabelProvider());
- new ColumnViewerComparator(column);
-
- // Symbolic name
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(250);
- column.getColumn().setText("Symbolic Name");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -4280840684440451080L;
-
- public String getText(Object element) {
- return ((Bundle) element).getSymbolicName();
- }
- });
- new ColumnViewerComparator(column);
-
- // Version
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(250);
- column.getColumn().setText("Version");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = 6871926308708629989L;
-
- public String getText(Object element) {
- Bundle bundle = (org.osgi.framework.Bundle) element;
- return bundle.getVersion().toString();
- }
- });
- new ColumnViewerComparator(column);
-
- viewer.setInput(bc);
-
- }
-
- @Focus
- public void setFocus() {
- if (viewer != null)
- viewer.getControl().setFocus();
- }
-
- /** Content provider managing the array of bundles */
- private static class BundleContentProvider implements IStructuredContentProvider {
- private static final long serialVersionUID = -8533792785725875977L;
-
- public Object[] getElements(Object inputElement) {
- if (inputElement instanceof BundleContext) {
- BundleContext bc = (BundleContext) inputElement;
- return bc.getBundles();
- }
- return null;
- }
-
- public void dispose() {
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
- }
-}
+++ /dev/null
-//package org.argeo.eclipse.ui.workbench.osgi;
-//public class BundlesView {}
-
-package org.argeo.cms.e4.monitoring;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-
-import org.argeo.api.cms.CmsSession;
-import org.argeo.cms.auth.RoleNameUtils;
-import org.argeo.eclipse.ui.ColumnViewerComparator;
-import org.argeo.eclipse.ui.specific.EclipseUiSpecificUtils;
-import org.argeo.util.LangUtils;
-import org.eclipse.e4.ui.di.Focus;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-/**
- * Overview of the active CMS sessions.
- */
-public class CmsSessionsView {
- private final static BundleContext bc = FrameworkUtil.getBundle(CmsSessionsView.class).getBundleContext();
-
- private TableViewer viewer;
-
- @PostConstruct
- public void createPartControl(Composite parent) {
- viewer = new TableViewer(parent);
- viewer.setContentProvider(new CmsSessionContentProvider());
- viewer.getTable().setHeaderVisible(true);
-
- EclipseUiSpecificUtils.enableToolTipSupport(viewer);
-
- int longColWidth = 150;
- int smallColWidth = 100;
-
- // Display name
- TableViewerColumn column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(longColWidth);
- column.getColumn().setText("User");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -5234573509093747505L;
-
- public String getText(Object element) {
- return ((CmsSession) element).getDisplayName();
- }
-
- public String getToolTipText(Object element) {
- return ((CmsSession) element).getUserDn().toString();
- }
- });
- new ColumnViewerComparator(column);
-
- // Creation time
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(smallColWidth);
- column.getColumn().setText("Since");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -5234573509093747505L;
-
- public String getText(Object element) {
- return LangUtils.since(((CmsSession) element).getCreationTime());
- }
-
- public String getToolTipText(Object element) {
- return ((CmsSession) element).getCreationTime().toString();
- }
- });
- new ColumnViewerComparator(column);
-
- // Username
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(smallColWidth);
- column.getColumn().setText("Username");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -5234573509093747505L;
-
- public String getText(Object element) {
- String userDn = ((CmsSession) element).getUserDn();
- return RoleNameUtils.getLastRdnValue(userDn);
- }
-
- public String getToolTipText(Object element) {
- return ((CmsSession) element).getUserDn().toString();
- }
- });
- new ColumnViewerComparator(column);
-
- // UUID
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(smallColWidth);
- column.getColumn().setText("UUID");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -5234573509093747505L;
-
- public String getText(Object element) {
- return ((CmsSession) element).getUuid().toString();
- }
-
- public String getToolTipText(Object element) {
- return getText(element);
- }
- });
- new ColumnViewerComparator(column);
-
- // Local ID
- column = new TableViewerColumn(viewer, SWT.NONE);
- column.getColumn().setWidth(smallColWidth);
- column.getColumn().setText("Local ID");
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = -5234573509093747505L;
-
- public String getText(Object element) {
- return ((CmsSession) element).getLocalId();
- }
-
- public String getToolTipText(Object element) {
- return getText(element);
- }
- });
- new ColumnViewerComparator(column);
-
- viewer.setInput(bc);
-
- }
-
- @Focus
- public void setFocus() {
- if (viewer != null)
- viewer.getControl().setFocus();
- }
-
- /** Content provider managing the array of bundles */
- private static class CmsSessionContentProvider implements IStructuredContentProvider {
- private static final long serialVersionUID = -8533792785725875977L;
-
- public Object[] getElements(Object inputElement) {
- if (inputElement instanceof BundleContext) {
- BundleContext bc = (BundleContext) inputElement;
- Collection<ServiceReference<CmsSession>> srs;
- try {
- srs = bc.getServiceReferences(CmsSession.class, null);
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Cannot retrieve CMS sessions", e);
- }
- List<CmsSession> res = new ArrayList<>();
- for (ServiceReference<CmsSession> sr : srs) {
- res.add(bc.getService(sr));
- }
- return res.toArray();
- }
- return null;
- }
-
- public void dispose() {
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
- }
-}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-
-import org.argeo.cms.ux.widgets.TreeParent;
-import org.eclipse.e4.ui.di.Focus;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-/** The OSGi runtime from a module perspective. */
-public class ModulesView {
- private final static BundleContext bc = FrameworkUtil.getBundle(ModulesView.class).getBundleContext();
- private TreeViewer viewer;
-
- @PostConstruct
- public void createPartControl(Composite parent) {
- viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
- viewer.setContentProvider(new ModulesContentProvider());
- viewer.setLabelProvider(new ModulesLabelProvider());
- viewer.setInput(bc);
- }
-
- @Focus
- public void setFocus() {
- viewer.getTree().setFocus();
- }
-
- private class ModulesContentProvider implements ITreeContentProvider {
- private static final long serialVersionUID = 3819934804640641721L;
-
- public Object[] getElements(Object inputElement) {
- return getChildren(inputElement);
- }
-
- public Object[] getChildren(Object parentElement) {
- if (parentElement instanceof BundleContext) {
- BundleContext bundleContext = (BundleContext) parentElement;
- Bundle[] bundles = bundleContext.getBundles();
-
- List<BundleNode> modules = new ArrayList<BundleNode>();
- for (Bundle bundle : bundles) {
- if (bundle.getState() == Bundle.ACTIVE)
- modules.add(new BundleNode(bundle, true));
- }
- return modules.toArray();
- } else if (parentElement instanceof TreeParent) {
- return ((TreeParent) parentElement).getChildren();
- } else {
- return null;
- }
- }
-
- public Object getParent(Object element) {
- // TODO Auto-generated method stub
- return null;
- }
-
- public boolean hasChildren(Object element) {
- if (element instanceof TreeParent) {
- return ((TreeParent) element).hasChildren();
- }
- return false;
- }
-
- public void dispose() {
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
- }
-
- private class ModulesLabelProvider extends StateLabelProvider {
- private static final long serialVersionUID = 5290046145534824722L;
-
- @Override
- public String getText(Object element) {
- if (element instanceof BundleNode)
- return element.toString() + " [" + ((BundleNode) element).getBundle().getBundleId() + "]";
- return element.toString();
- }
- }
-}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Dictionary;
-import java.util.List;
-
-import javax.annotation.PostConstruct;
-
-import org.argeo.cms.swt.CmsException;
-import org.argeo.util.LangUtils;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ITreeContentProvider;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.TreeViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Composite;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class OsgiConfigurationsView {
- private final static BundleContext bc = FrameworkUtil.getBundle(OsgiConfigurationsView.class).getBundleContext();
-
- @PostConstruct
- public void createPartControl(Composite parent) {
- ConfigurationAdmin configurationAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
-
- TreeViewer viewer = new TreeViewer(parent);
- // viewer.getTree().setHeaderVisible(true);
-
- TreeViewerColumn tvc = new TreeViewerColumn(viewer, SWT.NONE);
- tvc.getColumn().setWidth(400);
- tvc.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = 835407996597566763L;
-
- @Override
- public String getText(Object element) {
- if (element instanceof Configuration) {
- return ((Configuration) element).getPid();
- } else if (element instanceof Prop) {
- return ((Prop) element).key;
- }
- return super.getText(element);
- }
-
- @Override
- public Image getImage(Object element) {
- if (element instanceof Configuration)
- return OsgiExplorerImages.CONFIGURATION;
- return null;
- }
-
- });
-
- tvc = new TreeViewerColumn(viewer, SWT.NONE);
- tvc.getColumn().setWidth(400);
- tvc.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = 6999659261190014687L;
-
- @Override
- public String getText(Object element) {
- if (element instanceof Configuration) {
- // return ((Configuration) element).getFactoryPid();
- return null;
- } else if (element instanceof Prop) {
- return ((Prop) element).value.toString();
- }
- return super.getText(element);
- }
- });
-
- viewer.setContentProvider(new ConfigurationsContentProvider());
- viewer.setInput(configurationAdmin);
- }
-
- static class ConfigurationsContentProvider implements ITreeContentProvider {
- private static final long serialVersionUID = -4892768279440981042L;
- private ConfigurationComparator configurationComparator = new ConfigurationComparator();
-
- @Override
- public void dispose() {
- }
-
- @Override
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
-
- @Override
- public Object[] getElements(Object inputElement) {
- ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) inputElement;
- try {
- Configuration[] configurations = configurationAdmin.listConfigurations(null);
- Arrays.sort(configurations, configurationComparator);
- return configurations;
- } catch (IOException | InvalidSyntaxException e) {
- throw new CmsException("Cannot list configurations", e);
- }
- }
-
- @Override
- public Object[] getChildren(Object parentElement) {
- if (parentElement instanceof Configuration) {
- List<Prop> res = new ArrayList<>();
- Configuration configuration = (Configuration) parentElement;
- Dictionary<String, Object> props = configuration.getProperties();
- keys: for (String key : LangUtils.keys(props)) {
- if (Constants.SERVICE_PID.equals(key))
- continue keys;
- if (ConfigurationAdmin.SERVICE_FACTORYPID.equals(key))
- continue keys;
- res.add(new Prop(configuration, key, props.get(key)));
- }
- return res.toArray(new Prop[res.size()]);
- }
- return null;
- }
-
- @Override
- public Object getParent(Object element) {
- if (element instanceof Prop)
- return ((Prop) element).configuration;
- return null;
- }
-
- @Override
- public boolean hasChildren(Object element) {
- if (element instanceof Configuration)
- return true;
- return false;
- }
-
- }
-
- static class Prop {
- final Configuration configuration;
- final String key;
- final Object value;
-
- public Prop(Configuration configuration, String key, Object value) {
- this.configuration = configuration;
- this.key = key;
- this.value = value;
- }
-
- }
-
- static class ConfigurationComparator implements Comparator<Configuration> {
-
- @Override
- public int compare(Configuration o1, Configuration o2) {
- return o1.getPid().compareTo(o2.getPid());
- }
-
- }
-}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import org.argeo.cms.ui.theme.CmsImages;
-import org.eclipse.swt.graphics.Image;
-
-/** Shared icons. */
-public class OsgiExplorerImages extends CmsImages {
- public final static Image INSTALLED = createIcon("installed.gif");
- public final static Image RESOLVED = createIcon("resolved.gif");
- public final static Image STARTING = createIcon("starting.gif");
- public final static Image ACTIVE = createIcon("active.gif");
- public final static Image SERVICE_PUBLISHED = createIcon("service_published.gif");
- public final static Image SERVICE_REFERENCED = createIcon("service_referenced.gif");
- public final static Image CONFIGURATION = createIcon("node.gif");
-}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import org.argeo.cms.ux.widgets.TreeParent;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.ServiceReference;
-
-/** A tree element representing a {@link ServiceReference} */
-@SuppressWarnings({ "rawtypes" })
-class ServiceReferenceNode extends TreeParent {
- private final ServiceReference serviceReference;
- private final boolean published;
-
- public ServiceReferenceNode(ServiceReference serviceReference,
- boolean published) {
- super(serviceReference.toString());
- this.serviceReference = serviceReference;
- this.published = published;
-
- if (isPublished()) {
- Bundle[] usedBundles = serviceReference.getUsingBundles();
- if (usedBundles != null) {
- for (Bundle b : usedBundles) {
- if (b != null)
- addChild(new BundleNode(b));
- }
- }
- } else {
- Bundle provider = serviceReference.getBundle();
- addChild(new BundleNode(provider));
- }
-
- for (String key : serviceReference.getPropertyKeys()) {
- addChild(new TreeParent(key + "="
- + serviceReference.getProperty(key)));
- }
-
- }
-
- public ServiceReference getServiceReference() {
- return serviceReference;
- }
-
- public boolean isPublished() {
- return published;
- }
-}
+++ /dev/null
-package org.argeo.cms.e4.monitoring;
-
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.swt.graphics.Image;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-
-/** Label provider showing the sate of bundles */
-class StateLabelProvider extends ColumnLabelProvider {
- private static final long serialVersionUID = -7885583135316000733L;
-
- @Override
- public Image getImage(Object element) {
- int state;
- if (element instanceof Bundle)
- state = ((Bundle) element).getState();
- else if (element instanceof BundleNode)
- state = ((BundleNode) element).getBundle().getState();
- else if (element instanceof ServiceReferenceNode)
- if (((ServiceReferenceNode) element).isPublished())
- return OsgiExplorerImages.SERVICE_PUBLISHED;
- else
- return OsgiExplorerImages.SERVICE_REFERENCED;
- else
- return null;
-
- switch (state) {
- case Bundle.UNINSTALLED:
- return OsgiExplorerImages.INSTALLED;
- case Bundle.INSTALLED:
- return OsgiExplorerImages.INSTALLED;
- case Bundle.RESOLVED:
- return OsgiExplorerImages.RESOLVED;
- case Bundle.STARTING:
- return OsgiExplorerImages.STARTING;
- case Bundle.STOPPING:
- return OsgiExplorerImages.STARTING;
- case Bundle.ACTIVE:
- return OsgiExplorerImages.ACTIVE;
- default:
- return null;
- }
- }
-
- @Override
- public String getText(Object element) {
- return null;
- }
-
- @Override
- public String getToolTipText(Object element) {
- Bundle bundle = (Bundle) element;
- Integer state = bundle.getState();
- switch (state) {
- case Bundle.UNINSTALLED:
- return "UNINSTALLED";
- case Bundle.INSTALLED:
- return "INSTALLED";
- case Bundle.RESOLVED:
- return "RESOLVED";
- case Bundle.STARTING:
- String activationPolicy = bundle.getHeaders()
- .get(Constants.BUNDLE_ACTIVATIONPOLICY).toString();
-
- // .get("Bundle-ActivationPolicy").toString();
- // FIXME constant triggers the compilation failure
- if (activationPolicy != null
- && activationPolicy.equals(Constants.ACTIVATION_LAZY))
- // && activationPolicy.equals("lazy"))
- // FIXME constant triggers the compilation failure
- // && activationPolicy.equals(Constants.ACTIVATION_LAZY))
- return "<<LAZY>>";
- return "STARTING";
- case Bundle.STOPPING:
- return "STOPPING";
- case Bundle.ACTIVE:
- return "ACTIVE";
- default:
- return null;
- }
- }
-}
+++ /dev/null
-/** Monitoring perspective. */
-package org.argeo.cms.e4.monitoring;
\ No newline at end of file
+++ /dev/null
-package org.argeo.cms.e4.parts;
-
-import java.time.ZonedDateTime;
-
-import javax.annotation.PostConstruct;
-
-import org.argeo.api.cms.CmsSession;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.swt.CmsSwtUtils;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-
-/** A canonical view of the logged in user. */
-public class EgoDashboard {
-// private BundleContext bc = FrameworkUtil.getBundle(EgoDashboard.class).getBundleContext();
-
- @PostConstruct
- public void createPartControl(Composite p) {
- p.setLayout(new GridLayout());
- String username = CurrentUser.getUsername();
-
- CmsSwtUtils.lbl(p, "<strong>" + CurrentUser.getDisplayName() + "</strong>");
- CmsSwtUtils.txt(p, username);
- CmsSwtUtils.lbl(p, "Roles:");
- roles: for (String role : CurrentUser.roles()) {
- if (username.equals(role))
- continue roles;
- CmsSwtUtils.txt(p, role);
- }
-
-// Subject subject = Subject.getSubject(AccessController.getContext());
-// if (subject != null) {
- CmsSession cmsSession = CurrentUser.getCmsSession();
- ZonedDateTime loggedIndSince = cmsSession.getCreationTime();
- CmsSwtUtils.lbl(p, "Session:");
- CmsSwtUtils.txt(p, cmsSession.getUuid().toString());
- CmsSwtUtils.lbl(p, "Logged in since:");
- CmsSwtUtils.txt(p, loggedIndSince.toString());
-// }
- }
-}
Import-Package: org.eclipse.swt,\
org.eclipse.jface.window,\
+org.eclipse.jface.dialogs,\
org.eclipse.core.commands.common,\
javax.servlet.*;version="[3,5)",\
*
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.Selected;
import org.argeo.cms.swt.dialogs.LightweightDialog;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.wizard.IWizard;
Button cancelButton = new Button(messageArea, SWT.FLAT);
cancelButton.setText(CmsMsg.cancel.lead());
cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3));
- cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL));
+ cancelButton.addSelectionListener((Selected) (e) -> closeShell(CmsDialog.CANCEL));
message = new Label(messageArea, SWT.WRAP);
message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2));
updateMessage();
protected void finishPressed() {
if (wizard.performFinish())
- closeShell(OK);
+ closeShell(CmsDialog.OK);
}
private static void setSwitchingFormData(Composite composite) {
import org.argeo.api.cms.ux.CmsUi;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.api.cms.ux.UxContext;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.util.CurrentSubject;
+import org.argeo.cms.CurrentUser;
+import org.argeo.cms.util.CurrentSubject;
import org.eclipse.swt.widgets.Display;
public abstract class AbstractSwtCmsView implements CmsView {
import org.argeo.api.acr.spi.ProvidedContent;
import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsEditable;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.swt.SwtEditablePart;
import org.argeo.cms.swt.widgets.ScrolledPage;
import org.eclipse.swt.SWT;
public ContentComposite(Composite parent, int style, Content item) {
super(parent, style);
- setData(item);
+ if (item != null)
+ setData(item);
+ }
+
+ public boolean hasContent() {
+ if (getData() == null)
+ return false;
+ return getData() instanceof Content;
}
public Content getContent() {
this(section, section, style, node);
}
+ public SwtSection(SwtSection section, int style) {
+ this(section, style, null);
+ }
+
protected SwtSection(Composite parent, SwtSection parentSection, int style, Content node) {
super(parent, style, node);
this.parentSection = parentSection;
- if (parentSection != null) {
+ if (parentSection != null && hasContent() && parentSection.hasContent()) {
relativeDepth = getProvidedContent().getDepth() - parentSection.getProvidedContent().getDepth();
} else {
relativeDepth = 0;
private StackLayout stackLayout;
private boolean singleTab = false;
+ private String singleTabTitle = null;
public SwtTabbedArea(Composite parent, int style) {
super(parent, SWT.NONE);
Button title = new Button(sectionHeader, SWT.FLAT);
CmsSwtUtils.style(title, selected ? tabSelectedStyle : tabStyle);
title.setLayoutData(CmsSwtUtils.fillWidth());
- title.addSelectionListener((Selected) (e) -> showTab(tabIndex(section.getNode())));
+ title.addSelectionListener((Selected) (e) -> showTab(tabIndex(section.getContent())));
Content node = section.getContent();
// FIXME find a standard way to display titles
String titleStr = node.getName().getLocalPart();
-
- // TODO internationalize
+ if (singleTab && singleTabTitle != null)
+ titleStr = singleTabTitle;
+
+ // TODO internationalise
title.setText(titleStr);
if (!singleTab) {
ToolBar toolBar = new ToolBar(sectionHeader, SWT.NONE);
return;
}
SwtSection section = (SwtSection) body.getChildren()[0];
- previousNode = (ProvidedContent) section.getNode();
+ previousNode = (ProvidedContent) section.getContent();
if (previousNode == null) {// empty state
previousNode = (ProvidedContent) context;
previousUiProvider = uiProvider;
public Content getCurrentContext() {
SwtSection section = getCurrentSection();
if (section != null) {
- return section.getNode();
+ return section.getContent();
} else {
return null;
}
this.singleTab = singleTab;
}
+ public void setSingleTabTitle(String singleTabTitle) {
+ this.singleTabTitle = singleTabTitle;
+ }
+
}
import org.argeo.api.acr.Content;
import org.argeo.api.acr.NamespaceUtils;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.cms.swt.widgets.SwtTreeView;
import org.argeo.cms.swt.widgets.SwtTableView;
+import org.argeo.cms.swt.widgets.SwtTreeView;
import org.argeo.cms.ux.acr.ContentHierarchicalPart;
import org.argeo.cms.ux.widgets.Column;
import org.argeo.cms.ux.widgets.DefaultTabularPart;
split.setLayoutData(CmsSwtUtils.fillAll());
ContentHierarchicalPart contentPart = new ContentHierarchicalPart();
+ contentPart.addColumn((model) -> {
+ try {
+ return NamespaceUtils.toPrefixedName(model.getName());
+ } catch (IllegalStateException e) {
+ return model.getName().toString();
+ }
+ });
contentPart.setInput(rootContent);
new SwtTreeView<>(split, getStyle(), contentPart);
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
-import org.argeo.eclipse.ui.dialogs.LightweightDialog;
+import org.argeo.cms.swt.dialogs.LightweightDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import java.util.concurrent.Callable;
import org.argeo.api.cms.CmsLog;
+import org.argeo.api.cms.directory.CmsUserManager;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.cms.CmsMsg;
-import org.argeo.cms.CmsUserManager;
import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
if (Arrays.equals(newPassword.getTextChars(), confirmPassword.getTextChars())) {
try {
cmsUserManager.changeOwnPassword(previousPassword.getTextChars(), newPassword.getTextChars());
- return OK;
+ return CmsDialog.OK;
} catch (Exception e1) {
log.error("Could not change password", e1);
cancel();
CmsMessageDialog.openError(CmsMsg.invalidPassword.lead());
- return CANCEL;
+ return CmsDialog.CANCEL;
}
} else {
cancel();
CmsMessageDialog.openError(CmsMsg.repeatNewPassword.lead());
- return CANCEL;
+ return CmsDialog.CANCEL;
}
};
@Override
protected void okPressed() {
Integer returnCode = cmsView.doAs(doIt);
- if (returnCode.equals(OK)) {
+ if (returnCode.equals(CmsDialog.OK)) {
super.okPressed();
CmsMessageDialog.openInformation(CmsMsg.passwordChanged.lead());
}
import org.argeo.api.cms.CmsLog;
import org.argeo.cms.CmsMsg;
import org.argeo.cms.swt.Selected;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
Button close = new Button(parent, SWT.FLAT);
close.setText(CmsMsg.close.lead());
close.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false));
- close.addSelectionListener((Selected) (e) -> closeShell(OK));
+ close.addSelectionListener((Selected) (e) -> closeShell(CmsDialog.OK));
if (exception != null) {
stack = new Text(parent, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
import org.argeo.cms.CmsMsg;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.Selected;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.argeo.eclipse.ui.EclipseUiUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.TraverseEvent;
Button close = new Button(buttons, SWT.FLAT);
close.setText(CmsMsg.close.lead());
close.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
- close.addSelectionListener((Selected) (e) -> closeShell(OK));
+ close.addSelectionListener((Selected) (e) -> closeShell(CmsDialog.OK));
close.setFocus();
close.addTraverseListener(traverseListener);
}
protected void okPressed() {
- closeShell(OK);
+ closeShell(CmsDialog.OK);
}
protected void cancelPressed() {
- closeShell(CANCEL);
+ closeShell(CmsDialog.CANCEL);
}
protected void cancel() {
- closeShell(CANCEL);
+ closeShell(CmsDialog.CANCEL);
}
protected Point getInitialSize() {
package org.argeo.cms.swt.dialogs;
import org.argeo.api.cms.CmsLog;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.argeo.eclipse.ui.EclipseUiException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
public class LightweightDialog {
private final static CmsLog log = CmsLog.getLog(LightweightDialog.class);
- // must be the same value as org.eclipse.jface.window.Window#OK
- public final static int OK = 0;
- // must be the same value as org.eclipse.jface.window.Window#CANCEL
- public final static int CANCEL = 1;
-
private Shell parentShell;
private Shell backgroundShell;
private Shell foregoundShell;
if (hasChildShells())
return;
if (returnCode == null)// not yet closed
- closeShell(CANCEL);
+ closeShell(CmsDialog.CANCEL);
}
@Override
if (hasChildShells())
return;
if (returnCode == null)// not yet closed
- closeShell(CANCEL);
+ closeShell(CmsDialog.CANCEL);
}
});
backgroundShell.addDisposeListener((event) -> onClose());
block();
}
if (returnCode == null)
- returnCode = OK;
+ returnCode = CmsDialog.OK;
return returnCode;
}
try {
runEventLoop(foregoundShell);
} catch (ThreadDeath t) {
- returnCode = CANCEL;
+ returnCode = CmsDialog.CANCEL;
if (log.isTraceEnabled())
log.error("Thread death, canceling dialog", t);
} catch (Throwable t) {
- returnCode = CANCEL;
+ returnCode = CmsDialog.CANCEL;
log.error("Cannot open blocking lightweight dialog", t);
}
}
private synchronized void notifyClose() {
if (returnCode == null)
- returnCode = CANCEL;
+ returnCode = CmsDialog.CANCEL;
notifyAll();
}
protected void closeShell(int returnCode) {
this.returnCode = returnCode;
- if (CANCEL == returnCode)
+ if (CmsDialog.CANCEL == returnCode)
onCancel();
if (foregoundShell != null && !foregoundShell.isDisposed()) {
foregoundShell.close();
+++ /dev/null
-package org.argeo.cms.swt.useradmin;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.eclipse.ui.ColumnDefinition;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.parts.LdifUsersTable;
-import org.argeo.util.naming.LdapAttrs;
-import org.argeo.util.naming.LdapObjs;
-import org.eclipse.jface.dialogs.MessageDialog;
-import org.eclipse.jface.dialogs.TrayDialog;
-import org.eclipse.jface.viewers.DoubleClickEvent;
-import org.eclipse.jface.viewers.IDoubleClickListener;
-import org.eclipse.jface.viewers.ISelectionChangedListener;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.viewers.SelectionChangedEvent;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.events.SelectionListener;
-import org.eclipse.swt.layout.FillLayout;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Shell;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.useradmin.Group;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-import org.osgi.service.useradmin.UserAdmin;
-
-/** Dialog with a user (or group) list to pick up one */
-public class PickUpUserDialog extends TrayDialog {
- private static final long serialVersionUID = -1420106871173920369L;
-
- // Business objects
- private final UserAdmin userAdmin;
- private User selectedUser;
-
- // this page widgets and UI objects
- private String title;
- private LdifUsersTable userTableViewerCmp;
- private TableViewer userViewer;
- private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
-
- /**
- * A dialog to pick up a group or a user, showing a table with default
- * columns
- */
- public PickUpUserDialog(Shell parentShell, String title, UserAdmin userAdmin) {
- super(parentShell);
- this.title = title;
- this.userAdmin = userAdmin;
-
- columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_ICON), "",
- 24, 24));
- columnDefs.add(new ColumnDefinition(
- new UserLP(UserLP.COL_DISPLAY_NAME), "Common Name", 150, 100));
- columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DOMAIN),
- "Domain", 100, 120));
- columnDefs.add(new ColumnDefinition(new UserLP(UserLP.COL_DN),
- "Distinguished Name", 300, 100));
- }
-
- /** A dialog to pick up a group or a user */
- public PickUpUserDialog(Shell parentShell, String title,
- UserAdmin userAdmin, List<ColumnDefinition> columnDefs) {
- super(parentShell);
- this.title = title;
- this.userAdmin = userAdmin;
- this.columnDefs = columnDefs;
- }
-
- @Override
- protected void okPressed() {
- if (getSelected() == null)
- MessageDialog.openError(getShell(), "No user chosen",
- "Please, choose a user or press Cancel.");
- else
- super.okPressed();
- }
-
- protected Control createDialogArea(Composite parent) {
- Composite dialogArea = (Composite) super.createDialogArea(parent);
- dialogArea.setLayout(new FillLayout());
-
- Composite bodyCmp = new Composite(dialogArea, SWT.NO_FOCUS);
- bodyCmp.setLayout(new GridLayout());
-
- // Create and configure the table
- userTableViewerCmp = new MyUserTableViewer(bodyCmp, SWT.MULTI
- | SWT.H_SCROLL | SWT.V_SCROLL);
-
- userTableViewerCmp.setColumnDefinitions(columnDefs);
- userTableViewerCmp.populateWithStaticFilters(false, false);
- GridData gd = EclipseUiUtils.fillAll();
- gd.minimumHeight = 300;
- userTableViewerCmp.setLayoutData(gd);
- userTableViewerCmp.refresh();
-
- // Controllers
- userViewer = userTableViewerCmp.getTableViewer();
- userViewer.addDoubleClickListener(new MyDoubleClickListener());
- userViewer
- .addSelectionChangedListener(new MySelectionChangedListener());
-
- parent.pack();
- return dialogArea;
- }
-
- public User getSelected() {
- if (selectedUser == null)
- return null;
- else
- return selectedUser;
- }
-
- protected void configureShell(Shell shell) {
- super.configureShell(shell);
- shell.setText(title);
- }
-
- class MyDoubleClickListener implements IDoubleClickListener {
- public void doubleClick(DoubleClickEvent evt) {
- if (evt.getSelection().isEmpty())
- return;
-
- Object obj = ((IStructuredSelection) evt.getSelection())
- .getFirstElement();
- if (obj instanceof User) {
- selectedUser = (User) obj;
- okPressed();
- }
- }
- }
-
- class MySelectionChangedListener implements ISelectionChangedListener {
- @Override
- public void selectionChanged(SelectionChangedEvent event) {
- if (event.getSelection().isEmpty()) {
- selectedUser = null;
- return;
- }
- Object obj = ((IStructuredSelection) event.getSelection())
- .getFirstElement();
- if (obj instanceof Group) {
- selectedUser = (Group) obj;
- }
- }
- }
-
- private class MyUserTableViewer extends LdifUsersTable {
- private static final long serialVersionUID = 8467999509931900367L;
-
- private final String[] knownProps = { LdapAttrs.uid.name(),
- LdapAttrs.cn.name(), LdapAttrs.DN };
-
- private Button showSystemRoleBtn;
- private Button showUserBtn;
-
- public MyUserTableViewer(Composite parent, int style) {
- super(parent, style);
- }
-
- protected void populateStaticFilters(Composite staticFilterCmp) {
- staticFilterCmp.setLayout(new GridLayout());
- showSystemRoleBtn = new Button(staticFilterCmp, SWT.CHECK);
- showSystemRoleBtn.setText("Show system roles ");
-
- showUserBtn = new Button(staticFilterCmp, SWT.CHECK);
- showUserBtn.setText("Show users ");
-
- SelectionListener sl = new SelectionAdapter() {
- private static final long serialVersionUID = -7033424592697691676L;
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- refresh();
- }
- };
-
- showSystemRoleBtn.addSelectionListener(sl);
- showUserBtn.addSelectionListener(sl);
- }
-
- @Override
- protected List<User> listFilteredElements(String filter) {
- Role[] roles;
- try {
- StringBuilder builder = new StringBuilder();
-
- StringBuilder filterBuilder = new StringBuilder();
- if (notNull(filter))
- for (String prop : knownProps) {
- filterBuilder.append("(");
- filterBuilder.append(prop);
- filterBuilder.append("=*");
- filterBuilder.append(filter);
- filterBuilder.append("*)");
- }
-
- String typeStr = "(" + LdapAttrs.objectClass.name() + "="
- + LdapObjs.groupOfNames.name() + ")";
- if ((showUserBtn.getSelection()))
- typeStr = "(|(" + LdapAttrs.objectClass.name() + "="
- + LdapObjs.inetOrgPerson.name() + ")" + typeStr
- + ")";
-
- if (!showSystemRoleBtn.getSelection())
- typeStr = "(& " + typeStr + "(!(" + LdapAttrs.DN + "=*"
- + CmsConstants.SYSTEM_ROLES_BASEDN + ")))";
-
- if (filterBuilder.length() > 1) {
- builder.append("(&" + typeStr);
- builder.append("(|");
- builder.append(filterBuilder.toString());
- builder.append("))");
- } else {
- builder.append(typeStr);
- }
- roles = userAdmin.getRoles(builder.toString());
- } catch (InvalidSyntaxException e) {
- throw new EclipseUiException(
- "Unable to get roles with filter: " + filter, e);
- }
- List<User> users = new ArrayList<User>();
- for (Role role : roles)
- if (!users.contains(role))
- users.add((User) role);
- return users;
- }
- }
-
- private boolean notNull(String string) {
- if (string == null)
- return false;
- else
- return !"".equals(string.trim());
- }
-}
+++ /dev/null
-package org.argeo.cms.swt.useradmin;
-
-import org.argeo.api.cms.CmsConstants;
-import org.argeo.cms.auth.UserAdminUtils;
-import org.eclipse.jface.resource.JFaceResources;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.service.useradmin.Role;
-import org.osgi.service.useradmin.User;
-
-/** Centralize label providers for the group table */
-class UserLP extends ColumnLabelProvider {
- private static final long serialVersionUID = -4645930210988368571L;
-
- final static String COL_ICON = "colID.icon";
- final static String COL_DN = "colID.dn";
- final static String COL_DISPLAY_NAME = "colID.displayName";
- final static String COL_DOMAIN = "colID.domain";
-
- final String currType;
-
- // private Font italic;
- private Font bold;
-
- UserLP(String colId) {
- this.currType = colId;
- }
-
- @Override
- public Font getFont(Object element) {
- // Current user as bold
- if (UserAdminUtils.isCurrentUser(((User) element))) {
- if (bold == null)
- bold = JFaceResources.getFontRegistry().defaultFontDescriptor().setStyle(SWT.BOLD)
- .createFont(Display.getCurrent());
- return bold;
- }
- return null;
- }
-
- @Override
- public Image getImage(Object element) {
- if (COL_ICON.equals(currType)) {
- User user = (User) element;
- String dn = user.getName();
- if (dn.endsWith(CmsConstants.SYSTEM_ROLES_BASEDN))
- return UsersImages.ICON_ROLE;
- else if (user.getType() == Role.GROUP)
- return UsersImages.ICON_GROUP;
- else
- return UsersImages.ICON_USER;
- } else
- return null;
- }
-
- @Override
- public String getText(Object element) {
- User user = (User) element;
- return getText(user);
-
- }
-
- public String getText(User user) {
- if (COL_DN.equals(currType))
- return user.getName();
- else if (COL_DISPLAY_NAME.equals(currType))
- return UserAdminUtils.getCommonName(user);
- else if (COL_DOMAIN.equals(currType))
- return UserAdminUtils.getDomainName(user);
- else
- return "";
- }
-}
+++ /dev/null
-package org.argeo.cms.swt.useradmin;
-
-import org.argeo.cms.ui.theme.CmsImages;
-import org.eclipse.swt.graphics.Image;
-
-/** Specific users icons. */
-public class UsersImages {
- private final static String PREFIX = "icons/";
-
- public final static Image ICON_USER = CmsImages.createImg(PREFIX + "person.png");
- public final static Image ICON_GROUP = CmsImages.createImg(PREFIX + "group.png");
- public final static Image ICON_ROLE = CmsImages.createImg(PREFIX + "role.gif");
- public final static Image ICON_CHANGE_PASSWORD = CmsImages.createImg(PREFIX + "security.gif");
-}
+++ /dev/null
-/** SWT/JFace users management components. */
-package org.argeo.cms.swt.useradmin;
\ No newline at end of file
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.ux.widgets.DataPart;
import org.argeo.cms.ux.widgets.DataView;
+import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Composite;
protected final SelectionListener selectionListener;
@SuppressWarnings("unchecked")
- public AbstractSwtView(Composite parent, int style, DataPart<INPUT, TYPE> dataPart) {
- super(parent, style);
+ public AbstractSwtView(Composite parent, DataPart<INPUT, TYPE> dataPart) {
+ super(parent, SWT.NONE);
setLayout(CmsSwtUtils.noSpaceGridLayout());
this.dataPart = dataPart;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.Selected;
import org.argeo.cms.swt.dialogs.LightweightDialog;
+import org.argeo.cms.ux.widgets.CmsDialog;
import org.argeo.cms.ux.widgets.GuidedForm;
import org.argeo.cms.ux.widgets.GuidedForm.Page;
import org.argeo.eclipse.ui.EclipseUiUtils;
Button cancelButton = new Button(messageArea, SWT.FLAT);
cancelButton.setText(CmsMsg.cancel.lead());
cancelButton.setLayoutData(new GridData(SWT.END, SWT.TOP, false, false, 1, 3));
- cancelButton.addSelectionListener((Selected) (e) -> closeShell(CANCEL));
+ cancelButton.addSelectionListener((Selected) (e) -> closeShell(CmsDialog.CANCEL));
message = new Label(messageArea, SWT.WRAP);
message.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 2));
updateMessage();
protected void finishPressed() {
if (guidedForm.performFinish())
- closeShell(OK);
+ closeShell(CmsDialog.OK);
}
private static void setSwitchingFormData(Composite composite) {
private CmsSwtTheme theme;
public SwtTableView(Composite parent, int style, TabularPart<INPUT, T> tabularPart) {
- super(parent, style, tabularPart);
+ super(parent, tabularPart);
theme = CmsSwtUtils.getCmsTheme(parent);
- table = new Table(this, SWT.VIRTUAL | SWT.BORDER);
+ table = new Table(this, SWT.VIRTUAL | style);
table.setLinesVisible(true);
table.setLayoutData(CmsSwtUtils.fillAll());
protected void refreshItem(TableItem item) {
int row = getTable().indexOf(item);
+ T data = tabularPart.getData(row);
for (int i = 0; i < tabularPart.getColumnCount(); i++) {
Column<T> column = tabularPart.getColumn(i);
- T data = tabularPart.getData(row);
item.setData(data);
String text = data != null ? column.getText(data) : "";
if (text != null)
}
}
+ @Override
+ public void notifyItemCountChange() {
+ table.setItemCount(tabularPart.getItemCount());
+ }
+
protected Table getTable() {
return table;
}
import java.util.List;
+import org.argeo.api.cms.CmsLog;
import org.argeo.api.cms.ux.CmsIcon;
import org.argeo.cms.swt.CmsSwtTheme;
import org.argeo.cms.swt.CmsSwtUtils;
+import org.argeo.cms.ux.widgets.Column;
import org.argeo.cms.ux.widgets.HierarchicalPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
/** View of a {@link HierarchicalPart} based on a {@link Tree}. */
public class SwtTreeView<T> extends AbstractSwtView<T, T> {
+ private final static CmsLog log = CmsLog.getLog(SwtTreeView.class);
+
private static final long serialVersionUID = -6247710601465713047L;
private final Tree tree;
private CmsSwtTheme theme;
public SwtTreeView(Composite parent, int style, HierarchicalPart<T> hierarchicalPart) {
- super(parent, style, hierarchicalPart);
+ super(parent, hierarchicalPart);
theme = CmsSwtUtils.getCmsTheme(parent);
- tree = new Tree(this, SWT.BORDER);
+ tree = new Tree(this, style);
tree.setLayoutData(CmsSwtUtils.fillAll());
this.hierarchicalPart = hierarchicalPart;
List<T> rootItems = hierarchicalPart.getChildren(hierarchicalPart.getInput());
for (T child : rootItems) {
- addTreeItem(null, child);
+ try {
+ addTreeItem(null, child);
+ } catch (Exception e) {
+ if (log.isTraceEnabled())
+ log.error("Cannot retrieve child", e);
+ }
}
tree.addListener(SWT.Expand, event -> {
protected TreeItem addTreeItem(TreeItem parent, T data) {
TreeItem item = parent == null ? new TreeItem(tree, SWT.NONE) : new TreeItem(parent, SWT.NONE);
item.setData(data);
- String txt = hierarchicalPart.getText(data);
- if (txt != null)
- item.setText(hierarchicalPart.getText(data));
- CmsIcon icon = hierarchicalPart.getIcon(data);
- if (icon != null) {
- Image image = theme.getSmallIcon(icon);
- item.setImage(image);
+ for (int i = 0; i < hierarchicalPart.getColumnCount(); i++) {
+ Column<T> column = hierarchicalPart.getColumn(i);
+ String txt = column.getText(data);
+ if (txt != null)
+ item.setText(txt);
+ CmsIcon icon = column.getIcon(data);
+ if (icon != null) {
+ Image image = theme.getSmallIcon(icon);
+ item.setImage(image);
+ }
}
- // TODO optimize
+ // TODO optimise
List<T> grandChildren = hierarchicalPart.getChildren(data);
if (grandChildren.size() != 0)
new TreeItem(item, SWT.NONE);
return item;
}
+ @Override
+ public void notifyItemCountChange() {
+ // TODO what to update ?
+
+ }
+
protected Tree getTree() {
return tree;
}
+++ /dev/null
-package org.argeo.cms.ui.theme;
-
-import java.net.URL;
-
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-
-public class CmsImages {
- private static BundleContext themeBc = FrameworkUtil.getBundle(CmsImages.class).getBundleContext();
-
- final public static String ICONS_BASE = "icons/";
- final public static String TYPES_BASE = ICONS_BASE + "types/";
- final public static String ACTIONS_BASE = ICONS_BASE + "actions/";
-
- public static Image createIcon(String name) {
- return createImg(CmsImages.ICONS_BASE + name);
- }
-
- public static Image createAction(String name) {
- return createImg(CmsImages.ACTIONS_BASE + name);
- }
-
- public static Image createType(String name) {
- return createImg(CmsImages.TYPES_BASE + name);
- }
-
- public static Image createImg(String name) {
- return CmsImages.createDesc(name).createImage(Display.getDefault());
- }
-
- public static ImageDescriptor createDesc(String name) {
- return createDesc(themeBc, name);
- }
-
- public static ImageDescriptor createDesc(BundleContext bc, String name) {
- URL url = bc.getBundle().getResource(name);
- if (url == null)
- return ImageDescriptor.getMissingImageDescriptor();
- return ImageDescriptor.createFromURL(url);
- }
-
- public static Image createImg(BundleContext bc, String name) {
- return createDesc(bc, name).createImage(Display.getDefault());
- }
-
-}
+++ /dev/null
-/** Argeo CMS core theme images. */
-package org.argeo.cms.ui.theme;
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.dialogs;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.argeo.api.cms.CmsLog;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * Generic error dialog to be used in try/catch blocks.
- *
- * @deprecated Use CMS dialogs instead.
- */
-@Deprecated
-public class ErrorFeedback extends TitleAreaDialog {
- private static final long serialVersionUID = -8918084784628179044L;
-
- private final static CmsLog log = CmsLog.getLog(ErrorFeedback.class);
-
- private final String message;
- private final Throwable exception;
-
- public static void show(String message, Throwable e) {
- // rethrow ThreaDeath in order to make sure that RAP will properly clean
- // up the UI thread
- if (e instanceof ThreadDeath)
- throw (ThreadDeath) e;
-
- new ErrorFeedback(newShell(), message, e).open();
- }
-
- public static void show(String message) {
- new ErrorFeedback(newShell(), message, null).open();
- }
-
- private static Shell newShell() {
- return new Shell(getDisplay(), SWT.NO_TRIM);
- }
-
- /** Tries to find a display */
- private static Display getDisplay() {
- try {
- Display display = Display.getCurrent();
- if (display != null)
- return display;
- else
- return Display.getDefault();
- } catch (Exception e) {
- return Display.getCurrent();
- }
- }
-
- public ErrorFeedback(Shell parentShell, String message, Throwable e) {
- super(parentShell);
- setShellStyle(SWT.NO_TRIM);
- this.message = message;
- this.exception = e;
- log.error(message, e);
- }
-
- protected Point getInitialSize() {
- if (exception != null)
- return new Point(800, 600);
- else
- return new Point(400, 300);
- }
-
- @Override
- protected Control createDialogArea(Composite parent) {
- Composite dialogarea = (Composite) super.createDialogArea(parent);
- dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- Composite composite = new Composite(dialogarea, SWT.NONE);
- composite.setLayout(new GridLayout(2, false));
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- setMessage(message != null ? message + (exception != null ? ": " + exception.getMessage() : "")
- : exception != null ? exception.getMessage() : "Unkown Error", IMessageProvider.ERROR);
-
- if (exception != null) {
- Text stack = new Text(composite, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
- stack.setEditable(false);
- stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- StringWriter sw = new StringWriter();
- exception.printStackTrace(new PrintWriter(sw));
- stack.setText(sw.toString());
- }
-
- parent.pack();
- return composite;
- }
-
- protected void configureShell(Shell shell) {
- super.configureShell(shell);
- shell.setText("Error");
- }
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.dialogs;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.argeo.api.cms.CmsLog;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ShellAdapter;
-import org.eclipse.swt.events.ShellEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * Generic lightweight dialog, not based on JFace.
- *
- * @deprecated Use CMS dialogs instead.
- */
-@Deprecated
-public class FeedbackDialog extends LightweightDialog {
- private final static CmsLog log = CmsLog.getLog(FeedbackDialog.class);
-
- private String message;
- private Throwable exception;
-
-// private Shell parentShell;
- private Shell shell;
-
- public static void show(String message, Throwable e) {
- // rethrow ThreaDeath in order to make sure that RAP will properly clean
- // up the UI thread
- if (e instanceof ThreadDeath)
- throw (ThreadDeath) e;
-
- new FeedbackDialog(getDisplay().getActiveShell(), message, e).open();
- }
-
- public static void show(String message) {
- new FeedbackDialog(getDisplay().getActiveShell(), message, null).open();
- }
-
- /** Tries to find a display */
- private static Display getDisplay() {
- try {
- Display display = Display.getCurrent();
- if (display != null)
- return display;
- else
- return Display.getDefault();
- } catch (Exception e) {
- return Display.getCurrent();
- }
- }
-
- public FeedbackDialog(Shell parentShell, String message, Throwable e) {
- super(parentShell);
- this.message = message;
- this.exception = e;
- log.error(message, e);
- }
-
- public int open() {
- if (shell != null)
- throw new EclipseUiException("There is already a shell");
- shell = new Shell(getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP);
- shell.setLayout(new GridLayout());
- // shell.setText("Error");
- shell.setSize(getInitialSize());
- createDialogArea(shell);
- // shell.pack();
- // shell.layout();
-
- Rectangle shellBounds = Display.getCurrent().getBounds();// RAP
- Point dialogSize = shell.getSize();
- int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
- int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
- shell.setLocation(x, y);
-
- shell.addShellListener(new ShellAdapter() {
- private static final long serialVersionUID = -2701270481953688763L;
-
- @Override
- public void shellDeactivated(ShellEvent e) {
- closeShell();
- }
- });
-
- shell.open();
- return OK;
- }
-
- protected void closeShell() {
- shell.close();
- shell.dispose();
- shell = null;
- }
-
- protected Point getInitialSize() {
- // if (exception != null)
- // return new Point(800, 600);
- // else
- return new Point(400, 300);
- }
-
- protected Control createDialogArea(Composite parent) {
- Composite dialogarea = new Composite(parent, SWT.NONE);
- dialogarea.setLayout(new GridLayout());
- // Composite dialogarea = (Composite) super.createDialogArea(parent);
- dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- Label messageLbl = new Label(dialogarea, SWT.NONE);
- if (message != null)
- messageLbl.setText(message);
- else if (exception != null)
- messageLbl.setText(exception.getLocalizedMessage());
-
- Composite composite = new Composite(dialogarea, SWT.NONE);
- composite.setLayout(new GridLayout(2, false));
- composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
-
- if (exception != null) {
- Text stack = new Text(composite, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
- stack.setEditable(false);
- stack.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- StringWriter sw = new StringWriter();
- exception.printStackTrace(new PrintWriter(sw));
- stack.setText(sw.toString());
- }
-
- // parent.pack();
- return composite;
- }
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.dialogs;
-
-import org.argeo.api.cms.CmsLog;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.FocusEvent;
-import org.eclipse.swt.events.FocusListener;
-import org.eclipse.swt.events.ShellAdapter;
-import org.eclipse.swt.events.ShellEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-
-/** Generic lightweight dialog, not based on JFace. */
-@Deprecated
-public class LightweightDialog {
- private final static CmsLog log = CmsLog.getLog(LightweightDialog.class);
-
- // must be the same value as org.eclipse.jface.window.Window#OK
- public final static int OK = 0;
- // must be the same value as org.eclipse.jface.window.Window#CANCEL
- public final static int CANCEL = 1;
-
- private Shell parentShell;
- private Shell backgroundShell;
- private Shell foregoundShell;
-
- private Integer returnCode = null;
- private boolean block = true;
-
- private String title;
-
- /** Tries to find a display */
- private static Display getDisplay() {
- try {
- Display display = Display.getCurrent();
- if (display != null)
- return display;
- else
- return Display.getDefault();
- } catch (Exception e) {
- return Display.getCurrent();
- }
- }
-
- public LightweightDialog(Shell parentShell) {
- this.parentShell = parentShell;
- }
-
- public int open() {
- if (foregoundShell != null)
- throw new EclipseUiException("There is already a shell");
- backgroundShell = new Shell(parentShell, SWT.ON_TOP);
- backgroundShell.setFullScreen(true);
- // if (parentShell != null) {
- // backgroundShell.setBounds(parentShell.getBounds());
- // } else
- // backgroundShell.setMaximized(true);
- backgroundShell.setAlpha(128);
- backgroundShell.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLACK));
- foregoundShell = new Shell(backgroundShell, SWT.NO_TRIM | SWT.ON_TOP);
- if (title != null)
- setTitle(title);
- foregoundShell.setLayout(new GridLayout());
- foregoundShell.setSize(getInitialSize());
- createDialogArea(foregoundShell);
- // shell.pack();
- // shell.layout();
-
- Rectangle shellBounds = parentShell != null ? parentShell.getBounds() : Display.getCurrent().getBounds();// RAP
- Point dialogSize = foregoundShell.getSize();
- int x = shellBounds.x + (shellBounds.width - dialogSize.x) / 2;
- int y = shellBounds.y + (shellBounds.height - dialogSize.y) / 2;
- foregoundShell.setLocation(x, y);
-
- foregoundShell.addShellListener(new ShellAdapter() {
- private static final long serialVersionUID = -2701270481953688763L;
-
- @Override
- public void shellDeactivated(ShellEvent e) {
- if (hasChildShells())
- return;
- if (returnCode == null)// not yet closed
- closeShell(CANCEL);
- }
-
- @Override
- public void shellClosed(ShellEvent e) {
- notifyClose();
- }
-
- });
-
- backgroundShell.open();
- foregoundShell.open();
- // after the foreground shell has been opened
- backgroundShell.addFocusListener(new FocusListener() {
- private static final long serialVersionUID = 3137408447474661070L;
-
- @Override
- public void focusLost(FocusEvent event) {
- }
-
- @Override
- public void focusGained(FocusEvent event) {
- if (hasChildShells())
- return;
- if (returnCode == null)// not yet closed
- closeShell(CANCEL);
- }
- });
-
- if (block) {
- block();
- }
- if (returnCode == null)
- returnCode = OK;
- return returnCode;
- }
-
- public void block() {
- try {
- runEventLoop(foregoundShell);
- } catch (ThreadDeath t) {
- returnCode = CANCEL;
- if (log.isTraceEnabled())
- log.error("Thread death, canceling dialog", t);
- } catch (Throwable t) {
- returnCode = CANCEL;
- log.error("Cannot open blocking lightweight dialog", t);
- }
- }
-
- private boolean hasChildShells() {
- if (foregoundShell == null)
- return false;
- return foregoundShell.getShells().length != 0;
- }
-
- // public synchronized int openAndWait() {
- // open();
- // while (returnCode == null)
- // try {
- // wait(100);
- // } catch (InterruptedException e) {
- // // silent
- // }
- // return returnCode;
- // }
-
- private synchronized void notifyClose() {
- if (returnCode == null)
- returnCode = CANCEL;
- notifyAll();
- }
-
- protected void closeShell(int returnCode) {
- this.returnCode = returnCode;
- if (CANCEL == returnCode)
- onCancel();
- if (foregoundShell != null && !foregoundShell.isDisposed()) {
- foregoundShell.close();
- foregoundShell.dispose();
- foregoundShell = null;
- }
-
- if (backgroundShell != null && !backgroundShell.isDisposed()) {
- backgroundShell.close();
- backgroundShell.dispose();
- }
- }
-
- protected Point getInitialSize() {
- // if (exception != null)
- // return new Point(800, 600);
- // else
- return new Point(600, 400);
- }
-
- protected Control createDialogArea(Composite parent) {
- Composite dialogarea = new Composite(parent, SWT.NONE);
- dialogarea.setLayout(new GridLayout());
- dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- return dialogarea;
- }
-
- protected Shell getBackgroundShell() {
- return backgroundShell;
- }
-
- protected Shell getForegoundShell() {
- return foregoundShell;
- }
-
- public void setBlockOnOpen(boolean shouldBlock) {
- block = shouldBlock;
- }
-
- public void pack() {
- foregoundShell.pack();
- }
-
- private void runEventLoop(Shell loopShell) {
- Display display;
- if (foregoundShell == null) {
- display = Display.getCurrent();
- } else {
- display = loopShell.getDisplay();
- }
-
- while (loopShell != null && !loopShell.isDisposed()) {
- try {
- if (!display.readAndDispatch()) {
- display.sleep();
- }
- } catch (UnsupportedOperationException e) {
- throw e;
- } catch (Throwable e) {
- handleException(e);
- }
- }
- if (!display.isDisposed())
- display.update();
- }
-
- protected void handleException(Throwable t) {
- if (t instanceof ThreadDeath) {
- // Don't catch ThreadDeath as this is a normal occurrence when
- // the thread dies
- throw (ThreadDeath) t;
- }
- // Try to keep running.
- t.printStackTrace();
- }
-
- /** @return false, if the dialog should not be closed. */
- protected boolean onCancel() {
- return true;
- }
-
- public void setTitle(String title) {
- this.title = title;
- if (title != null && getForegoundShell() != null)
- getForegoundShell().setText(title);
- }
-
- public Integer getReturnCode() {
- return returnCode;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.dialogs;
-
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.eclipse.jface.dialogs.IMessageProvider;
-import org.eclipse.jface.dialogs.TitleAreaDialog;
-import org.eclipse.jface.window.Window;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.Text;
-
-/**
- * Dialog to retrieve a single value.
- *
- * @deprecated Use CMS dialogs instead.
- */
-@Deprecated
-public class SingleValue extends TitleAreaDialog {
- private static final long serialVersionUID = 2843538207460082349L;
-
- private Text valueT;
- private String value;
- private final String title, message, label;
- private final Boolean multiline;
-
- public static String ask(String label, String message) {
- SingleValue svd = new SingleValue(label, message);
- if (svd.open() == Window.OK)
- return svd.getString();
- else
- return null;
- }
-
- public static Long askLong(String label, String message) {
- SingleValue svd = new SingleValue(label, message);
- if (svd.open() == Window.OK)
- return svd.getLong();
- else
- return null;
- }
-
- public static Double askDouble(String label, String message) {
- SingleValue svd = new SingleValue(label, message);
- if (svd.open() == Window.OK)
- return svd.getDouble();
- else
- return null;
- }
-
- public SingleValue(String label, String message) {
- this(Display.getDefault().getActiveShell(), label, message, label, false);
- }
-
- public SingleValue(Shell parentShell, String title, String message, String label, Boolean multiline) {
- super(parentShell);
- this.title = title;
- this.message = message;
- this.label = label;
- this.multiline = multiline;
- }
-
- protected Point getInitialSize() {
- if (multiline)
- return new Point(450, 350);
-
- else
- return new Point(400, 270);
- }
-
- protected Control createDialogArea(Composite parent) {
- Composite dialogarea = (Composite) super.createDialogArea(parent);
- dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
- Composite composite = new Composite(dialogarea, SWT.NONE);
- composite.setLayoutData(EclipseUiUtils.fillAll());
- GridLayout layout = new GridLayout(2, false);
- layout.marginWidth = layout.marginHeight = 20;
- composite.setLayout(layout);
-
- valueT = createLT(composite, label);
-
- setMessage(message, IMessageProvider.NONE);
-
- parent.pack();
- valueT.setFocus();
- return composite;
- }
-
- @Override
- protected void okPressed() {
- value = valueT.getText();
- super.okPressed();
- }
-
- /** Creates label and text. */
- protected Text createLT(Composite parent, String label) {
- new Label(parent, SWT.NONE).setText(label);
- Text text;
- if (multiline) {
- text = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.MULTI);
- text.setLayoutData(EclipseUiUtils.fillAll());
- } else {
- text = new Text(parent, SWT.LEAD | SWT.BORDER | SWT.SINGLE);
- text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true));
- }
- return text;
- }
-
- protected void configureShell(Shell shell) {
- super.configureShell(shell);
- shell.setText(title);
- }
-
- public String getString() {
- return value;
- }
-
- public Long getLong() {
- return Long.valueOf(getString());
- }
-
- public Double getDouble() {
- return Double.valueOf(getString());
- }
-}
+++ /dev/null
-/** Generic SWT/JFace dialogs. */
-package org.argeo.eclipse.ui.dialogs;
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.parts;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.argeo.eclipse.ui.ColumnDefinition;
-import org.argeo.eclipse.ui.EclipseUiException;
-import org.argeo.eclipse.ui.EclipseUiUtils;
-import org.argeo.eclipse.ui.util.ViewerUtils;
-import org.eclipse.jface.layout.TableColumnLayout;
-import org.eclipse.jface.viewers.CheckboxTableViewer;
-import org.eclipse.jface.viewers.ColumnLabelProvider;
-import org.eclipse.jface.viewers.ColumnWeightData;
-import org.eclipse.jface.viewers.IStructuredContentProvider;
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.Viewer;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.ModifyEvent;
-import org.eclipse.swt.events.ModifyListener;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Link;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.Text;
-import org.osgi.service.useradmin.User;
-
-/**
- * Generic composite that display a filter and a table viewer to display users
- * (can also be groups)
- *
- * Warning: this class does not extends <code>TableViewer</code>. Use the
- * getTableViewer method to access it.
- *
- */
-public abstract class LdifUsersTable extends Composite {
- private static final long serialVersionUID = -7385959046279360420L;
-
- // Context
- // private UserAdmin userAdmin;
-
- // Configuration
- private List<ColumnDefinition> columnDefs = new ArrayList<ColumnDefinition>();
- private boolean hasFilter;
- private boolean preventTableLayout = false;
- private boolean hasSelectionColumn;
- private int tableStyle;
-
- // Local UI Objects
- private TableViewer usersViewer;
- private Text filterTxt;
-
- /* EXPOSED METHODS */
-
- /**
- * @param parent
- * @param style
- */
- public LdifUsersTable(Composite parent, int style) {
- super(parent, SWT.NO_FOCUS);
- this.tableStyle = style;
- }
-
- // TODO workaround the bug of the table layout in the Form
- public LdifUsersTable(Composite parent, int style, boolean preventTableLayout) {
- super(parent, SWT.NO_FOCUS);
- this.tableStyle = style;
- this.preventTableLayout = preventTableLayout;
- }
-
- /** This must be called before the call to populate method */
- public void setColumnDefinitions(List<ColumnDefinition> columnDefinitions) {
- this.columnDefs = columnDefinitions;
- }
-
- /**
- *
- * @param addFilter
- * choose to add a field to filter results or not
- * @param addSelection
- * choose to add a column to select some of the displayed results or
- * not
- */
- public void populate(boolean addFilter, boolean addSelection) {
- // initialization
- Composite parent = this;
- hasFilter = addFilter;
- hasSelectionColumn = addSelection;
-
- // Main Layout
- GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
- layout.verticalSpacing = 5;
- this.setLayout(layout);
- if (hasFilter)
- createFilterPart(parent);
-
- Composite tableComp = new Composite(parent, SWT.NO_FOCUS);
- tableComp.setLayoutData(EclipseUiUtils.fillAll());
- usersViewer = createTableViewer(tableComp);
- usersViewer.setContentProvider(new UsersContentProvider());
- }
-
- /**
- *
- * @param showMore
- * display static filters on creation
- * @param addSelection
- * choose to add a column to select some of the displayed results or
- * not
- */
- public void populateWithStaticFilters(boolean showMore, boolean addSelection) {
- // initialization
- Composite parent = this;
- hasFilter = true;
- hasSelectionColumn = addSelection;
-
- // Main Layout
- GridLayout layout = EclipseUiUtils.noSpaceGridLayout();
- layout.verticalSpacing = 5;
- this.setLayout(layout);
- createStaticFilterPart(parent, showMore);
-
- Composite tableComp = new Composite(parent, SWT.NO_FOCUS);
- tableComp.setLayoutData(EclipseUiUtils.fillAll());
- usersViewer = createTableViewer(tableComp);
- usersViewer.setContentProvider(new UsersContentProvider());
- }
-
- /** Enable access to the selected users or groups */
- public List<User> getSelectedUsers() {
- if (hasSelectionColumn) {
- Object[] elements = ((CheckboxTableViewer) usersViewer).getCheckedElements();
-
- List<User> result = new ArrayList<User>();
- for (Object obj : elements) {
- result.add((User) obj);
- }
- return result;
- } else
- throw new EclipseUiException(
- "Unvalid request: no selection column " + "has been created for the current table");
- }
-
- /** Returns the User table viewer, typically to add doubleclick listener */
- public TableViewer getTableViewer() {
- return usersViewer;
- }
-
- /**
- * Force the refresh of the underlying table using the current filter string if
- * relevant
- */
- public void refresh() {
- String filter = hasFilter ? filterTxt.getText().trim() : null;
- if ("".equals(filter))
- filter = null;
- refreshFilteredList(filter);
- }
-
- /** Effective repository request: caller must implement this method */
- abstract protected List<User> listFilteredElements(String filter);
-
- // protected List<User> listFilteredElements(String filter) {
- // List<User> users = new ArrayList<User>();
- // try {
- // Role[] roles = userAdmin.getRoles(filter);
- // // Display all users and groups
- // for (Role role : roles)
- // users.add((User) role);
- // } catch (InvalidSyntaxException e) {
- // throw new EclipseUiException("Unable to get roles with filter: "
- // + filter, e);
- // }
- // return users;
- // }
-
- /* GENERIC COMPOSITE METHODS */
- @Override
- public boolean setFocus() {
- if (hasFilter)
- return filterTxt.setFocus();
- else
- return usersViewer.getTable().setFocus();
- }
-
- @Override
- public void dispose() {
- super.dispose();
- }
-
- /* LOCAL CLASSES AND METHODS */
- // Will be usefull to rather use a virtual table viewer
- private void refreshFilteredList(String filter) {
- List<User> users = listFilteredElements(filter);
- usersViewer.setInput(users.toArray());
- }
-
- private class UsersContentProvider implements IStructuredContentProvider {
- private static final long serialVersionUID = 1L;
-
- public Object[] getElements(Object inputElement) {
- return (Object[]) inputElement;
- }
-
- public void dispose() {
- }
-
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
- }
- }
-
- /* MANAGE FILTER */
- private void createFilterPart(Composite parent) {
- // Text Area for the filter
- filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
- filterTxt.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
- filterTxt.addModifyListener(new ModifyListener() {
- private static final long serialVersionUID = 1L;
-
- public void modifyText(ModifyEvent event) {
- refreshFilteredList(filterTxt.getText());
- }
- });
- }
-
- private void createStaticFilterPart(Composite parent, boolean showMore) {
- Composite filterComp = new Composite(parent, SWT.NO_FOCUS);
- filterComp.setLayout(new GridLayout(2, false));
- filterComp.setLayoutData(EclipseUiUtils.fillWidth());
- // generic search
- filterTxt = new Text(filterComp, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
- filterTxt.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
- // filterTxt.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL |
- // GridData.HORIZONTAL_ALIGN_FILL));
- filterTxt.addModifyListener(new ModifyListener() {
- private static final long serialVersionUID = 1L;
-
- public void modifyText(ModifyEvent event) {
- refreshFilteredList(filterTxt.getText());
- }
- });
-
- // add static filter abilities
- Link moreLk = new Link(filterComp, SWT.NONE);
- Composite staticFilterCmp = new Composite(filterComp, SWT.NO_FOCUS);
- staticFilterCmp.setLayoutData(EclipseUiUtils.fillWidth(2));
- populateStaticFilters(staticFilterCmp);
-
- MoreLinkListener listener = new MoreLinkListener(moreLk, staticFilterCmp, showMore);
- // initialise the layout
- listener.refresh();
- moreLk.addSelectionListener(listener);
- }
-
- /** Overwrite to add static filters */
- protected void populateStaticFilters(Composite staticFilterCmp) {
- }
-
- // private void addMoreSL(final Link more) {
- // more.addSelectionListener( }
-
- private class MoreLinkListener extends SelectionAdapter {
- private static final long serialVersionUID = -524987616510893463L;
- private boolean isShown;
- private final Composite staticFilterCmp;
- private final Link moreLk;
-
- public MoreLinkListener(Link moreLk, Composite staticFilterCmp, boolean isShown) {
- this.moreLk = moreLk;
- this.staticFilterCmp = staticFilterCmp;
- this.isShown = isShown;
- }
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- isShown = !isShown;
- refresh();
- }
-
- public void refresh() {
- GridData gd = (GridData) staticFilterCmp.getLayoutData();
- if (isShown) {
- moreLk.setText("<a> Less... </a>");
- gd.heightHint = SWT.DEFAULT;
- } else {
- moreLk.setText("<a> More... </a>");
- gd.heightHint = 0;
- }
- forceLayout();
- }
- }
-
- private void forceLayout() {
- LdifUsersTable.this.getParent().layout(true, true);
- }
-
- private TableViewer createTableViewer(final Composite parent) {
-
- int style = tableStyle | SWT.H_SCROLL | SWT.V_SCROLL;
- if (hasSelectionColumn)
- style = style | SWT.CHECK;
- Table table = new Table(parent, style);
- TableColumnLayout layout = new TableColumnLayout();
-
- // TODO the table layout does not works with the scrolled form
-
- if (preventTableLayout) {
- parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
- table.setLayoutData(EclipseUiUtils.fillAll());
- } else
- parent.setLayout(layout);
-
- TableViewer viewer;
- if (hasSelectionColumn)
- viewer = new CheckboxTableViewer(table);
- else
- viewer = new TableViewer(table);
- table.setLinesVisible(true);
- table.setHeaderVisible(true);
-
- TableViewerColumn column;
- // int offset = 0;
- if (hasSelectionColumn) {
- // offset = 1;
- column = ViewerUtils.createTableViewerColumn(viewer, "", SWT.NONE, 25);
- column.setLabelProvider(new ColumnLabelProvider() {
- private static final long serialVersionUID = 1L;
-
- @Override
- public String getText(Object element) {
- return null;
- }
- });
- layout.setColumnData(column.getColumn(), new ColumnWeightData(25, 25, false));
-
- SelectionAdapter selectionAdapter = new SelectionAdapter() {
- private static final long serialVersionUID = 1L;
-
- boolean allSelected = false;
-
- @Override
- public void widgetSelected(SelectionEvent e) {
- allSelected = !allSelected;
- ((CheckboxTableViewer) usersViewer).setAllChecked(allSelected);
- }
- };
- column.getColumn().addSelectionListener(selectionAdapter);
- }
-
- // NodeViewerComparator comparator = new NodeViewerComparator();
- // TODO enable the sort by click on the header
- // int i = offset;
- for (ColumnDefinition colDef : columnDefs)
- createTableColumn(viewer, layout, colDef);
-
- // column = ViewerUtils.createTableViewerColumn(viewer,
- // colDef.getHeaderLabel(), SWT.NONE, colDef.getColumnSize());
- // column.setLabelProvider(new CLProvider(colDef.getPropertyName()));
- // column.getColumn().addSelectionListener(
- // JcrUiUtils.getNodeSelectionAdapter(i,
- // colDef.getPropertyType(), colDef.getPropertyName(),
- // comparator, viewer));
- // i++;
- // }
-
- // IMPORTANT: initialize comparator before setting it
- // JcrColumnDefinition firstCol = colDefs.get(0);
- // comparator.setColumn(firstCol.getPropertyType(),
- // firstCol.getPropertyName());
- // viewer.setComparator(comparator);
-
- return viewer;
- }
-
- /** Default creation of a column for a user table */
- private TableViewerColumn createTableColumn(TableViewer tableViewer, TableColumnLayout layout,
- ColumnDefinition columnDef) {
-
- boolean resizable = true;
- TableViewerColumn tvc = new TableViewerColumn(tableViewer, SWT.NONE);
- TableColumn column = tvc.getColumn();
-
- column.setText(columnDef.getLabel());
- column.setWidth(columnDef.getMinWidth());
- column.setResizable(resizable);
-
- ColumnLabelProvider lp = columnDef.getLabelProvider();
- // add a reference to the display to enable font management
- // if (lp instanceof UserAdminAbstractLP)
- // ((UserAdminAbstractLP) lp).setDisplay(tableViewer.getTable()
- // .getDisplay());
- tvc.setLabelProvider(lp);
-
- layout.setColumnData(column, new ColumnWeightData(columnDef.getWeight(), columnDef.getMinWidth(), resizable));
-
- return tvc;
- }
-}
+++ /dev/null
-/** Generic SWT/JFace composites. */
-package org.argeo.eclipse.ui.parts;
\ No newline at end of file
+++ /dev/null
-package org.argeo.eclipse.ui.util;
-
-import org.eclipse.jface.viewers.TableViewer;
-import org.eclipse.jface.viewers.TableViewerColumn;
-import org.eclipse.jface.viewers.TreeViewer;
-import org.eclipse.jface.viewers.TreeViewerColumn;
-import org.eclipse.swt.widgets.Table;
-import org.eclipse.swt.widgets.TableColumn;
-import org.eclipse.swt.widgets.TreeColumn;
-
-/**
- * Centralise useful methods to manage JFace Table, Tree and TreeColumn viewers.
- */
-public class ViewerUtils {
-
- /**
- * Creates a basic column for the given table. For the time being, we do not
- * support movable columns.
- */
- public static TableColumn createColumn(Table parent, String name, int style, int width) {
- TableColumn result = new TableColumn(parent, style);
- result.setText(name);
- result.setWidth(width);
- result.setResizable(true);
- return result;
- }
-
- /**
- * Creates a TableViewerColumn for the given viewer. For the time being, we do
- * not support movable columns.
- */
- public static TableViewerColumn createTableViewerColumn(TableViewer parent, String name, int style, int width) {
- TableViewerColumn tvc = new TableViewerColumn(parent, style);
- TableColumn column = tvc.getColumn();
- column.setText(name);
- column.setWidth(width);
- column.setResizable(true);
- return tvc;
- }
-
- // public static TableViewerColumn createTableViewerColumn(TableViewer parent,
- // Localized name, int style, int width) {
- // return createTableViewerColumn(parent, name.lead(), style, width);
- // }
-
- /**
- * Creates a TreeViewerColumn for the given viewer. For the time being, we do
- * not support movable columns.
- */
- public static TreeViewerColumn createTreeViewerColumn(TreeViewer parent, String name, int style, int width) {
- TreeViewerColumn tvc = new TreeViewerColumn(parent, style);
- TreeColumn column = tvc.getColumn();
- column.setText(name);
- column.setWidth(width);
- column.setResizable(true);
- return tvc;
- }
-}
+++ /dev/null
-/** Generic SWT/JFace JCR helpers. */
-package org.argeo.eclipse.ui.util;
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" configuration-policy="optional" name="CMS Admin RAP">
- <implementation class="org.argeo.cms.e4.rap.CmsE4AdminApp"/>
- <service>
- <provide interface="org.eclipse.rap.rwt.application.ApplicationConfiguration"/>
- <property name="contextName" type="String" value="cms"/>
- </service>
-</scr:component>
-Bundle-ActivationPolicy: lazy
-Service-Component: OSGI-INF/cms-admin-rap.xml
-
Import-Package: \
org.argeo.api.acr, \
org.eclipse.swt,\
org.eclipse.e4.ui.workbench,\
org.eclipse.rap.rwt.client,\
org.eclipse.nebula.widgets.richtext;resolution:=optional,\
+org.eclipse.*;resolution:=optional,\
*
+++ /dev/null
-package org.argeo.cms.e4.rap;
-
-import org.eclipse.rap.rwt.application.Application;
-
-/**
- * Access to canonical views of the core CMS concepts, useful for devleopers and
- * operators.
- */
-public class CmsE4AdminApp extends AbstractRapE4App {
- @Override
- protected void addEntryPoints(Application application) {
- addE4EntryPoint(application, "/devops", "org.argeo.cms.e4/e4xmi/cms-devops.e4xmi",
- customise("Argeo CMS DevOps"));
- }
-
-}
import org.argeo.api.cms.ux.CmsImageManager;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.api.cms.ux.UxContext;
-import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.SimpleSwtUxContext;
import org.argeo.cms.swt.acr.AcrSwtImageManager;
import java.util.Enumeration;
-import org.apache.commons.io.FilenameUtils;
import org.argeo.api.cms.CmsLog;
import org.eclipse.rap.rwt.application.Application;
import org.osgi.framework.Bundle;
String p = paths.nextElement();
if (p.endsWith(".e4xmi")) {
String e4xmiPath = bundle.getSymbolicName() + '/' + p;
- String name = '/' + FilenameUtils.removeExtension(FilenameUtils.getName(p));
+ // FIXME deal with base name
+ String name=null;// = '/' + FilenameUtils.removeExtension(FilenameUtils.getName(p));
addE4EntryPoint(application, name, e4xmiPath, getBaseProperties());
if (log.isDebugEnabled())
log.debug("Registered " + e4xmiPath + " as " + getContextName() + name);
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.cms.swt.rap.cli</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-[
-{
- "name":"java.lang.Boolean",
- "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.ClassLoader",
- "methods":[
- {"name":"getPlatformClassLoader","parameterTypes":[] },
- {"name":"loadClass","parameterTypes":["java.lang.String"] }
- ]
-},
-{
- "name":"jdk.internal.loader.ClassLoaders$PlatformClassLoader"
-},
-{
- "name":"org.graalvm.jniutils.JNIExceptionWrapperEntryPoints",
- "methods":[{"name":"getClassName","parameterTypes":["java.lang.Class"] }]
-},
-{
- "name":"sun.management.VMManagementImpl",
- "fields":[
- {"name":"compTimeMonitoringSupport"},
- {"name":"currentThreadCpuTimeSupport"},
- {"name":"objectMonitorUsageSupport"},
- {"name":"otherThreadCpuTimeSupport"},
- {"name":"remoteDiagnosticCommandsSupport"},
- {"name":"synchronizerUsageSupport"},
- {"name":"threadAllocatedMemorySupport"},
- {"name":"threadContentionMonitoringSupport"}
- ]
-}
-]
+++ /dev/null
-[
- {
- "type":"agent-extracted",
- "classes":[
- ]
- }
-]
-
+++ /dev/null
-[
- {
- "interfaces":["javax.servlet.http.HttpServletRequest"]}
- ,
- {
- "interfaces":["javax.servlet.http.HttpServletResponse"]}
-
-]
+++ /dev/null
-[
-{
- "name":"[B"
-},
-{
- "name":"[Ljava.lang.String;"
-},
-{
- "name":"[Lorg.eclipse.swt.widgets.TableColumn;"
-},
-{
- "name":"[Lorg.eclipse.swt.widgets.TreeColumn;"
-},
-{
- "name":"[Lsun.security.pkcs.SignerInfo;"
-},
-{
- "name":"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"java.lang.Boolean",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Byte",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Class"
-},
-{
- "name":"java.lang.Double",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Float",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Integer",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Long",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.Object",
- "queriedMethods":[
- {"name":"equals","parameterTypes":["java.lang.Object"] },
- {"name":"hashCode","parameterTypes":[] },
- {"name":"toString","parameterTypes":[] }
- ]
-},
-{
- "name":"java.lang.Short",
- "queriedMethods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
-},
-{
- "name":"java.lang.String"
-},
-{
- "name":"java.lang.management.ManagementFactory",
- "methods":[{"name":"getRuntimeMXBean","parameterTypes":[] }]
-},
-{
- "name":"java.lang.management.RuntimeMXBean",
- "methods":[{"name":"getUptime","parameterTypes":[] }]
-},
-{
- "name":"java.security.AlgorithmParametersSpi"
-},
-{
- "name":"java.security.SecureRandomParameters"
-},
-{
- "name":"java.util.Date"
-},
-{
- "name":"javax.security.auth.login.Configuration$Parameters"
-},
-{
- "name":"javax.security.auth.x500.X500Principal",
- "fields":[{"name":"thisX500Name"}],
- "queriedMethods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }]
-},
-{
- "name":"javax.servlet.ServletRequest",
- "queriedMethods":[
- {"name":"getAsyncContext","parameterTypes":[] },
- {"name":"getAttribute","parameterTypes":["java.lang.String"] },
- {"name":"getAttributeNames","parameterTypes":[] },
- {"name":"getCharacterEncoding","parameterTypes":[] },
- {"name":"getContentLength","parameterTypes":[] },
- {"name":"getContentLengthLong","parameterTypes":[] },
- {"name":"getContentType","parameterTypes":[] },
- {"name":"getDispatcherType","parameterTypes":[] },
- {"name":"getInputStream","parameterTypes":[] },
- {"name":"getLocalAddr","parameterTypes":[] },
- {"name":"getLocalName","parameterTypes":[] },
- {"name":"getLocalPort","parameterTypes":[] },
- {"name":"getLocale","parameterTypes":[] },
- {"name":"getLocales","parameterTypes":[] },
- {"name":"getParameter","parameterTypes":["java.lang.String"] },
- {"name":"getParameterMap","parameterTypes":[] },
- {"name":"getParameterNames","parameterTypes":[] },
- {"name":"getParameterValues","parameterTypes":["java.lang.String"] },
- {"name":"getProtocol","parameterTypes":[] },
- {"name":"getReader","parameterTypes":[] },
- {"name":"getRealPath","parameterTypes":["java.lang.String"] },
- {"name":"getRemoteAddr","parameterTypes":[] },
- {"name":"getRemoteHost","parameterTypes":[] },
- {"name":"getRemotePort","parameterTypes":[] },
- {"name":"getRequestDispatcher","parameterTypes":["java.lang.String"] },
- {"name":"getScheme","parameterTypes":[] },
- {"name":"getServerName","parameterTypes":[] },
- {"name":"getServerPort","parameterTypes":[] },
- {"name":"getServletContext","parameterTypes":[] },
- {"name":"isAsyncStarted","parameterTypes":[] },
- {"name":"isAsyncSupported","parameterTypes":[] },
- {"name":"isSecure","parameterTypes":[] },
- {"name":"removeAttribute","parameterTypes":["java.lang.String"] },
- {"name":"setAttribute","parameterTypes":["java.lang.String","java.lang.Object"] },
- {"name":"setCharacterEncoding","parameterTypes":["java.lang.String"] },
- {"name":"startAsync","parameterTypes":[] },
- {"name":"startAsync","parameterTypes":["javax.servlet.ServletRequest","javax.servlet.ServletResponse"] }
- ]
-},
-{
- "name":"javax.servlet.ServletResponse"
-},
-{
- "name":"javax.servlet.http.HttpServletRequest",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.reflect.InvocationHandler"] }],
- "queriedMethods":[
- {"name":"authenticate","parameterTypes":["javax.servlet.http.HttpServletResponse"] },
- {"name":"changeSessionId","parameterTypes":[] },
- {"name":"getAuthType","parameterTypes":[] },
- {"name":"getContextPath","parameterTypes":[] },
- {"name":"getCookies","parameterTypes":[] },
- {"name":"getDateHeader","parameterTypes":["java.lang.String"] },
- {"name":"getHeader","parameterTypes":["java.lang.String"] },
- {"name":"getHeaderNames","parameterTypes":[] },
- {"name":"getHeaders","parameterTypes":["java.lang.String"] },
- {"name":"getHttpServletMapping","parameterTypes":[] },
- {"name":"getIntHeader","parameterTypes":["java.lang.String"] },
- {"name":"getMethod","parameterTypes":[] },
- {"name":"getPart","parameterTypes":["java.lang.String"] },
- {"name":"getParts","parameterTypes":[] },
- {"name":"getPathInfo","parameterTypes":[] },
- {"name":"getPathTranslated","parameterTypes":[] },
- {"name":"getQueryString","parameterTypes":[] },
- {"name":"getRemoteUser","parameterTypes":[] },
- {"name":"getRequestURI","parameterTypes":[] },
- {"name":"getRequestURL","parameterTypes":[] },
- {"name":"getRequestedSessionId","parameterTypes":[] },
- {"name":"getServletPath","parameterTypes":[] },
- {"name":"getSession","parameterTypes":[] },
- {"name":"getSession","parameterTypes":["boolean"] },
- {"name":"getTrailerFields","parameterTypes":[] },
- {"name":"getUserPrincipal","parameterTypes":[] },
- {"name":"isRequestedSessionIdFromCookie","parameterTypes":[] },
- {"name":"isRequestedSessionIdFromURL","parameterTypes":[] },
- {"name":"isRequestedSessionIdFromUrl","parameterTypes":[] },
- {"name":"isRequestedSessionIdValid","parameterTypes":[] },
- {"name":"isTrailerFieldsReady","parameterTypes":[] },
- {"name":"isUserInRole","parameterTypes":["java.lang.String"] },
- {"name":"login","parameterTypes":["java.lang.String","java.lang.String"] },
- {"name":"logout","parameterTypes":[] },
- {"name":"newPushBuilder","parameterTypes":[] },
- {"name":"upgrade","parameterTypes":["java.lang.Class"] }
- ]
-},
-{
- "name":"javax.servlet.http.HttpServletResponse"
-},
-{
- "name":"org.apache.xerces.impl.dv.dtd.DTDDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.dtd.XML11DTDDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.xs.ExtendedSchemaDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.dv.xs.SchemaDVFactoryImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.impl.xs.XSMessageFormatter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.apache.xerces.parsers.XIncludeAwareParserConfiguration",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.AnonymousLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.DataAdminLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.IdentLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.RemoteSessionLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.argeo.cms.auth.UserAdminLoginModule",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.jetty.servlet.DefaultServlet",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.jetty.util.TypeUtil",
- "methods":[
- {"name":"getClassLoaderLocation","parameterTypes":["java.lang.Class"] },
- {"name":"getCodeSourceLocation","parameterTypes":["java.lang.Class"] },
- {"name":"getModuleLocation","parameterTypes":["java.lang.Class"] },
- {"name":"getSystemClassLoaderLocation","parameterTypes":["java.lang.Class"] }
- ]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.client.BrowserNavigationImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.client.ClientInfoImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.client.ExitConfirmationImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.client.StartupParametersImpl",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.client.WebClientMessages",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.lifecycle.RWTLifeCycle",
- "methods":[{"name":"<init>","parameterTypes":["org.eclipse.rap.rwt.internal.application.ApplicationContextImpl"] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.lifecycle.RequestCounter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.remote.RemoteObjectRegistry",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.serverpush.ServerPushManager",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.rap.rwt.internal.textsize.ProbeResultStore",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.SWT",
- "allDeclaredFields":true
-},
-{
- "name":"org.eclipse.swt.graphics.Color",
- "methods":[{"name":"<init>","parameterTypes":["int"] }]
-},
-{
- "name":"org.eclipse.swt.graphics.Font",
- "methods":[{"name":"<init>","parameterTypes":["org.eclipse.swt.graphics.FontData"] }]
-},
-{
- "name":"org.eclipse.swt.internal.image.GIFFileFormat",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.image.JPEGFileFormat",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.image.PNGFileFormat",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.image.WinBMPFileFormat",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.image.WinICOFileFormat",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.IdGenerator",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.displaykit.DisplayLCA",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.scrollbarkit.ScrollBarThemeAdapter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.shellkit.ShellThemeAdapter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.tablekit.TableThemeAdapter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"org.eclipse.swt.internal.widgets.treekit.TreeThemeAdapter",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.ConfigFile$Spi",
- "methods":[{"name":"<init>","parameterTypes":["javax.security.auth.login.Configuration$Parameters"] }]
-},
-{
- "name":"sun.security.provider.DRBG",
- "methods":[{"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
-},
-{
- "name":"sun.security.provider.DSAKeyFactory",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.DSAParameters",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.NativePRNG",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.SHA",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.SHA2$SHA256",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.provider.X509Factory",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.rsa.RSAKeyFactory$Legacy",
- "methods":[{"name":"<init>","parameterTypes":[] }]
-},
-{
- "name":"sun.security.util.ObjectIdentifier"
-},
-{
- "name":"sun.security.x509.AuthorityKeyIdentifierExtension",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
-},
-{
- "name":"sun.security.x509.BasicConstraintsExtension",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
-},
-{
- "name":"sun.security.x509.CertificateExtensions"
-},
-{
- "name":"sun.security.x509.ExtendedKeyUsageExtension",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
-},
-{
- "name":"sun.security.x509.KeyUsageExtension",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
-},
-{
- "name":"sun.security.x509.SubjectKeyIdentifierExtension",
- "methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
-}
-]
+++ /dev/null
-{
- "resources":{
- "includes":[
- {
- "pattern":"\\QMETA-INF/MANIFEST.MF\\E"
- },
- {
- "pattern":"\\QMETA-INF/services/javax.xml.parsers.DocumentBuilderFactory\\E"
- },
- {
- "pattern":"\\QMETA-INF/services/javax.xml.validation.SchemaFactory\\E"
- },
- {
- "pattern":"\\QMETA-INF/services/org.eclipse.jetty.http.HttpFieldPreEncoder\\E"
- },
- {
- "pattern":"\\Qclient.files\\E"
- },
- {
- "pattern":"\\Qclient.js\\E"
- },
- {
- "pattern":"\\Qjetty-dir.css\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/DSMLv2.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/SVG.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/XForms-11-Schema.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/XMLSchema.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/cr.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/docbook.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/schema-for-xslt20.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xlink.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xml-events-attribs-1.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/acr/schemas/xml.xsd\\E"
- },
- {
- "pattern":"\\Qorg/argeo/cms/internal/runtime/jaas.cfg\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/jetty/http/encoding.properties\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/jetty/http/mime.properties\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/jetty/version/build.properties\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/nebula/widgets/grid/internal/gridkit/Grid.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/nebula/widgets/grid/internal/gridkit/Grid.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/nebula/widgets/grid/internal/gridkit/Grid.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/service/rwt-index.html\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/dropdownkit/DropDown.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/dropdownkit/DropDown.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/dropdownkit/DropDown.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/fileuploadkit/FileUpload.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/fileuploadkit/FileUpload.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/rap/rwt/internal/widgets/fileuploadkit/FileUpload.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/browser/browserkit/Browser.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/browser/browserkit/Browser.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/browser/browserkit/Browser.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ccombokit/CCombo.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ccombokit/CCombo.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ccombokit/CCombo.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/clabelkit/CLabel.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/clabelkit/CLabel.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/clabelkit/CLabel.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ctabfolderkit/CTabFolder.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ctabfolderkit/CTabFolder.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/ctabfolderkit/CTabFolder.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/custom/scrolledcompositekit/ScrolledComposite.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/buttonkit/Button.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/buttonkit/Button.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/buttonkit/Button.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/combokit/Combo.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/combokit/Combo.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/combokit/Combo.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/compositekit/Composite.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/compositekit/Composite.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/compositekit/Composite.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/controlkit/Control.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/controlkit/Control.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/coolbarkit/CoolBar.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/coolbarkit/CoolBar.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/coolbarkit/CoolBar.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/datetimekit/DateTime.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/datetimekit/DateTime.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/datetimekit/DateTime.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/expandbarkit/ExpandBar.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/expandbarkit/ExpandBar.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/expandbarkit/ExpandBar.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/groupkit/Group.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/groupkit/Group.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/groupkit/Group.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/labelkit/Label.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/labelkit/Label.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/labelkit/Label.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/linkkit/Link.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/linkkit/Link.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/linkkit/Link.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/listkit/List.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/listkit/List.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/listkit/List.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/menukit/Menu.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/menukit/Menu.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/menukit/Menu.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/progressbarkit/ProgressBar.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/progressbarkit/ProgressBar.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/progressbarkit/ProgressBar.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sashkit/Sash.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sashkit/Sash.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sashkit/Sash.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scalekit/Scale.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scalekit/Scale.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scalekit/Scale.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scrollbarkit/ScrollBar.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scrollbarkit/ScrollBar.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/scrollbarkit/ScrollBar.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/shellkit/Shell.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/shellkit/Shell.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/shellkit/Shell.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sliderkit/Slider.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sliderkit/Slider.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/sliderkit/Slider.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/spinnerkit/Spinner.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/spinnerkit/Spinner.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/spinnerkit/Spinner.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tabfolderkit/TabFolder.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tabfolderkit/TabFolder.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tabfolderkit/TabFolder.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tablekit/Table.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tablekit/Table.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tablekit/Table.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/textkit/Text.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/textkit/Text.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/textkit/Text.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/toolbarkit/ToolBar.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/toolbarkit/ToolBar.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/toolbarkit/ToolBar.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tooltipkit/ToolTip.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tooltipkit/ToolTip.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/tooltipkit/ToolTip.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/treekit/Tree.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/treekit/Tree.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/treekit/Tree.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/widgetkit/Widget.appearances.js\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/widgetkit/Widget.default.css\\E"
- },
- {
- "pattern":"\\Qorg/eclipse/swt/internal/widgets/widgetkit/Widget.theme.xml\\E"
- },
- {
- "pattern":"\\Qorg/slf4j/impl/StaticLoggerBinder.class\\E"
- },
- {
- "pattern":"\\Qresource/static/html/blank.html\\E"
- },
- {
- "pattern":"\\Qresource/static/image/blank.gif\\E"
- },
- {
- "pattern":"\\Qresource/theme/default.css\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/chevron-left-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/chevron-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/chevron-right-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/chevron-right.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/tooltip-down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/tooltip-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/tooltip-right.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/arrows/tooltip-up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/arrow-down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/arrow-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/arrow-right.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/arrow-up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-grayed-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-grayed.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-selected-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-selected.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-unselected-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/check-unselected.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/radio-selected-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/radio-selected.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/radio-unselected-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/button/radio-unselected.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/lastMonth-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/lastMonth.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/lastYear-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/lastYear.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/nextMonth-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/nextMonth.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/nextYear-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/calendar/nextYear.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ccombo/down-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ccombo/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/column/sort-indicator-down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/column/sort-indicator-up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/combo/down-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/combo/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/close.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/close_hover.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/ctabfolder-dropdown-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/ctabfolder-dropdown-left-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/ctabfolder-dropdown-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/ctabfolder-dropdown.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/maximize.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/minimize.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/ctabfolder/restore.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/cursors/alias.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/cursors/copy.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/cursors/move.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/cursors/nodrop.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/cursors/up_arrow.cur\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/datetime/down-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/datetime/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/datetime/up-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/datetime/up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/dialog/error.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/dialog/information.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/dialog/question.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/dialog/warning.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/display/browser_bg.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/display/loading.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/expanditem/expanditem-collapse-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/expanditem/expanditem-collapse.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/expanditem/expanditem-expand-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/expanditem/expanditem-expand.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/menu/arrow-left.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/menu/arrow-right.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/menu/checkbox.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/menu/radiobutton.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/progressbar/progressbar-background.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/sash/sash-handle-horizontal.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/sash/sash-handle-vertical.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scale/h_line.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scale/v_line.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scrollbar/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scrollbar/left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scrollbar/right.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scrollbar/scrollbar-background.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/scrollbar/up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/slider/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/slider/left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/slider/right.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/slider/slider-background.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/slider/up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/spinner/down-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/spinner/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/spinner/up-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/spinner/up.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/text/clear.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/text/find.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/toolbar/down.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tooltip/error.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tooltip/information.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tooltip/warning.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/loading.gif\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-collapsed-hover-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-collapsed-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-collapsed-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-collapsed.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-expanded-hover-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-expanded-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-expanded-left.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/tree/tree-expanded.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-close-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-close.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-max-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-max.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-min-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-min.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-restore-hover.png\\E"
- },
- {
- "pattern":"\\Qresource/widget/rap/window/shell-restore.png\\E"
- }
- ]},
- "bundles":[
- {
- "name":"javax.servlet.LocalStrings",
- "locales":[""]
- },
- {
- "name":"javax.servlet.http.LocalStrings",
- "locales":[""]
- },
- {
- "name":"org.apache.xerces.impl.xpath.regex.message",
- "locales":[
- "",
- "en"
- ]
- },
- {
- "name":"org.eclipse.rap.rwt.internal.RWTMessages",
- "locales":[""]
- },
- {
- "name":"sun.security.util.Resources",
- "classNames":["sun.security.util.Resources"]
- }
- ]
-}
+++ /dev/null
-{
- "types":[
- ],
- "lambdaCapturingTypes":[
- ]
-}
+++ /dev/null
-Import-Package: \
-org.eclipse.jetty.util.component;version="[9.4,12)";resolution:=optional,\
-org.eclipse.jetty.http;version="[9.4,12)";resolution:=optional,\
-org.eclipse.jetty.io;version="[9.4,12)";resolution:=optional,\
-org.eclipse.jetty.security;version="[9.4,12)";resolution:=optional,\
-org.eclipse.jetty.server.handler;version="[9.4,12)";resolution:=optional,\
-org.eclipse.jetty.*;version="[9.4,12)";resolution:=optional,\
-*
\ No newline at end of file
+++ /dev/null
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
+++ /dev/null
-package org.argeo.cms.swt.rap.cli;
-
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.argeo.api.acr.spi.ProvidedRepository;
-import org.argeo.api.cli.CommandsCli;
-import org.argeo.api.cli.DescribedCommand;
-import org.argeo.api.cms.CmsApp;
-import org.argeo.api.cms.CmsContext;
-import org.argeo.api.cms.CmsState;
-import org.argeo.cms.jetty.CmsJettyServer;
-import org.argeo.cms.runtime.StaticCms;
-import org.argeo.cms.swt.app.CmsUserApp;
-import org.argeo.cms.web.CmsWebApp;
-import org.argeo.util.register.Component;
-import org.argeo.util.register.ComponentRegister;
-import org.eclipse.rap.rwt.application.ApplicationConfiguration;
-
-public class CmsRapCli extends CommandsCli {
-
- public CmsRapCli(String commandName) {
- super(commandName);
- addCommand("user", new Launch());
- }
-
- @Override
- public String getDescription() {
- return "Argeo CMS utilities.";
- }
-
- public static void main(String[] args) {
- mainImpl(new CmsRapCli("web"), args);
- }
-
- static class Launch implements DescribedCommand<String> {
- private Option dataOption;
- private Option uiOption;
-
- @Override
- public Options getOptions() {
- Options options = new Options();
- dataOption = Option.builder().longOpt("data").hasArg().required()
- .desc("path to the writable data area (mandatory)").build();
- uiOption = Option.builder().longOpt("ui").desc("open a user interface").build();
- options.addOption(dataOption);
- options.addOption(uiOption);
- return options;
- }
-
- @Override
- public String apply(List<String> args) {
- CommandLine cl = toCommandLine(args);
- String dataPath = cl.getOptionValue(dataOption);
- boolean ui = cl.hasOption(uiOption);
-
- Path instancePath = Paths.get(dataPath);
- System.setProperty("osgi.instance.area", instancePath.toUri().toString());
- System.setProperty("argeo.http.port", "0");
-
- StaticCms staticCms = new StaticCms() {
- @Override
- protected void addComponents(ComponentRegister register) {
- if (ui) {
- CmsUserApp cmsApp = new CmsUserApp();
- Component<CmsUserApp> cmsAppC = new Component.Builder<>(cmsApp) //
- .addType(CmsApp.class) //
- .addType(CmsUserApp.class) //
- .addDependency(register.getSingleton(CmsContext.class), cmsApp::setCmsContext, null) //
- .addDependency(register.getSingleton(ProvidedRepository.class),
- cmsApp::setContentRepository, null) //
- .build(register);
-
- CmsWebApp cmsWebApp = new CmsWebApp();
- Component<CmsWebApp> cmsWebAppC = new Component.Builder<>(cmsWebApp) //
- .addType(ApplicationConfiguration.class) //
- .addType(CmsWebApp.class) //
- .addDependency(cmsAppC.getType(CmsApp.class), cmsWebApp::setCmsApp, null) //
- .build(register);
-
- RapJettyServer rwtRunner = new RapJettyServer();
- Component<RapJettyServer> rwtRunnerC = new Component.Builder<>(rwtRunner) //
- .addActivation(rwtRunner::start) //
- .addDeactivation(rwtRunner::stop) //
- .addType(CmsJettyServer.class) //
- .addDependency(register.getSingleton(CmsState.class), rwtRunner::setCmsState, null) //
- .addDependency(cmsWebAppC.getType(CmsWebApp.class), rwtRunner::setCmsWebApp, null) //
- .build(register);
- }
- }
-
- };
- Runtime.getRuntime().addShutdownHook(new Thread(() -> staticCms.stop(), "Static CMS Shutdown"));
- staticCms.start();
-
- long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
- System.out.println("Static CMS available in " + jvmUptime + " ms.");
-
- if (ui) {
- try {
- // open browser in app mode
- Thread.sleep(2000);// wait for RWT to be ready
- String browserCommand = "google-chrome --app=http://localhost:"
- + staticCms.getComponentRegister().getObject(CmsJettyServer.class).getHttpPort() + "/data";
- Runtime.getRuntime().exec(browserCommand);
- } catch (InterruptedException | IOException e) {
- e.printStackTrace();
- }
- }
-
- staticCms.waitForStop();
-
- return null;
- }
-
- @Override
- public String getDescription() {
- return "Launch a static CMS.";
- }
-
- }
-}
+++ /dev/null
-package org.argeo.cms.swt.rap.cli;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.ServletException;
-
-import org.argeo.cms.jetty.CmsJettyServer;
-import org.argeo.cms.web.CmsWebApp;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.rap.rwt.application.ApplicationRunner;
-import org.eclipse.rap.rwt.engine.RWTServlet;
-
-public class RapJettyServer extends CmsJettyServer {
- private CmsWebApp cmsWebApp;
-
- @Override
- protected void addServlets(ServletContextHandler servletContextHandler) throws ServletException {
- // rwt-resources requires a file system
- try {
- Path tempDir = Files.createTempDirectory("argeo-rwtRunner");
- servletContextHandler.setBaseResource(Resource.newResource(tempDir.resolve("www").toString()));
- } catch (IOException e) {
- throw new IllegalStateException("Cannot create temporary directory", e);
- }
- servletContextHandler.addEventListener(new ServletContextListener() {
- ApplicationRunner applicationRunner;
-
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- applicationRunner = new ApplicationRunner(cmsWebApp, sce.getServletContext());
- applicationRunner.start();
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- applicationRunner.stop();
- }
- });
- for (String uiName : cmsWebApp.getCmsApp().getUiNames())
- servletContextHandler.addServlet(new ServletHolder(new RWTServlet()), "/" + uiName);
-
- // Required to serve rwt-resources. It is important that this is last.
- ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
- servletContextHandler.addServlet(holderPwd, "/");
-
- }
-
- public void setCmsWebApp(CmsWebApp cmsWebApp) {
- this.cmsWebApp = cmsWebApp;
- }
-
-}
+++ /dev/null
-package org.argeo.cms.swt.rap.cli;
-
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Objects;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-import org.argeo.minidesktop.MiniDesktopManager;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.servlet.DefaultServlet;
-import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.thread.QueuedThreadPool;
-import org.eclipse.rap.rwt.application.ApplicationConfiguration;
-import org.eclipse.rap.rwt.application.ApplicationRunner;
-import org.eclipse.rap.rwt.application.EntryPoint;
-import org.eclipse.rap.rwt.application.Application.OperationMode;
-import org.eclipse.rap.rwt.engine.RWTServlet;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Label;
-
-/** A minimal RWT runner based on embedded Jetty. */
-public class RwtRunner {
-
- private final Server server;
- private final ServerConnector serverConnector;
- private Path tempDir;
-
- private ApplicationConfiguration applicationConfiguration;
-
- public RwtRunner() {
- server = new Server(new QueuedThreadPool(10, 1));
- serverConnector = new ServerConnector(server);
- serverConnector.setPort(0);
- server.setConnectors(new Connector[] { serverConnector });
- }
-
- protected Control createUi(Composite parent, Object context) {
- return new Label(parent, 0);
- }
-
- public void init() {
- Objects.requireNonNull(applicationConfiguration);
-
- ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
- context.setContextPath("/");
- server.setHandler(context);
-
- String entryPoint = "app";
-
- // rwt-resources requires a file system
- try {
- tempDir = Files.createTempDirectory("argeo-rwtRunner");
- context.setBaseResource(Resource.newResource(tempDir.resolve("www").toString()));
- } catch (IOException e) {
- throw new IllegalStateException("Cannot create temporary directory", e);
- }
- context.addEventListener(new ServletContextListener() {
- ApplicationRunner applicationRunner;
-
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- applicationRunner = new ApplicationRunner(applicationConfiguration, sce.getServletContext());
- applicationRunner.start();
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent sce) {
- applicationRunner.stop();
- }
- });
-
- context.addServlet(new ServletHolder(new RWTServlet()), "/" + entryPoint);
-
- // Required to serve rwt-resources. It is important that this is last.
- ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
- context.addServlet(holderPwd, "/");
-
- try {
- server.start();
- } catch (Exception e) {
- throw new IllegalStateException("Cannot start Jetty server", e);
- }
- Runtime.getRuntime().addShutdownHook(new Thread(() -> destroy(), "Jetty shutdown"));
-
- long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
- System.out.println("RWT App available in " + jvmUptime + " ms, on port " + getEffectivePort());
- }
-
- public void destroy() {
- try {
- serverConnector.close();
- server.stop();
- // TODO delete temp dir
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public Integer getEffectivePort() {
- return serverConnector.getLocalPort();
- }
-
- public void waitFor() throws InterruptedException {
- server.join();
- }
-
- public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
- this.applicationConfiguration = applicationConfiguration;
- }
-
- public static void main(String[] args) throws Exception {
- RwtRunner rwtRunner = new RwtRunner();
-
- String entryPoint = "app";
- ApplicationConfiguration applicationConfiguration = (application) -> {
- application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
- application.addEntryPoint("/" + entryPoint, () -> new EntryPoint() {
- @Override
- public int createUI() {
- MiniDesktopManager miniDesktopManager = new MiniDesktopManager(false, false);
- miniDesktopManager.init();
- miniDesktopManager.run();
- return 0;
- }
- }, null);
- };
-
- rwtRunner.setApplicationConfiguration(applicationConfiguration);
- rwtRunner.init();
-
- // open browser in app mode
- Thread.sleep(2000);// wait for RWT to be ready
- Runtime.getRuntime().exec("google-chrome --app=http://localhost:" + rwtRunner.getEffectivePort() + "/app");
-
- rwtRunner.waitFor();
- }
-}
import org.argeo.api.cms.ux.CmsTheme;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.cms.swt.CmsSwtUtils;
-import org.argeo.util.LangUtils;
+import org.argeo.cms.util.LangUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.application.Application;
import org.eclipse.rap.rwt.application.Application.OperationMode;
import org.argeo.api.cms.CmsSession;
import org.argeo.api.cms.ux.CmsImageManager;
import org.argeo.api.cms.ux.CmsView;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.LocaleUtils;
-import org.argeo.cms.auth.CurrentUser;
import org.argeo.cms.auth.RemoteAuthCallbackHandler;
import org.argeo.cms.servlet.ServletHttpRequest;
import org.argeo.cms.servlet.ServletHttpResponse;
}
} else if (e instanceof ThreadDeath) {
throw (ThreadDeath) e;
- } else if (e instanceof Error) {
- log.error("Unexpected error in event loop, shutting down...", e);
- break eventLoop;
+// } else if (e instanceof Error) {
+// log.error("Unexpected error in event loop, shutting down...", e);
+// break eventLoop;
} else {
log.error("Unexpected exception in event loop, ignoring it. " + e.getMessage());
continue eventLoop;
<children xsi:type="advanced:Perspective" xmi:id="_oI_oICnCEei1F8sdBz8Mpw" elementId="org.argeo.cms.e4.rcp.perspective.cmsadmin" label="CMS Admin">
<children xsi:type="basic:PartSashContainer" xmi:id="_qc16ECnCEei1F8sdBz8Mpw" elementId="org.argeo.cms.e4.rcp.partsashcontainer.0" horizontal="true">
<children xsi:type="basic:PartStack" xmi:id="_RE87kDsXEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.rcp.partstack.1">
- <children xsi:type="basic:Part" xmi:id="_V1WvgDsXEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.rcp.part.files" contributionURI="bundleclass://org.argeo.cms.e4/org.argeo.cms.e4.files.NodeFsBrowserView" label="Files"/>
+ <children xsi:type="basic:Part" xmi:id="_V1WvgDsXEeiUntFYWh-hFg" elementId="org.argeo.cms.e4.rcp.part.files" contributionURI="bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.files.NodeFsBrowserView" label="Files"/>
<children xsi:type="basic:Part" xmi:id="_vOqDQCnCEei1F8sdBz8Mpw" elementId="org.argeo.cms.e4.rcp.part.jcr" containerData="4000" contributionURI="bundleclass://org.argeo.cms.jcr.e4/org.argeo.cms.e4.jcr.JcrBrowserView" label="JCR"/>
</children>
<children xsi:type="basic:PartStack" xmi:id="_0eRiwCnCEei1F8sdBz8Mpw" elementId="org.argeo.cms.e4.rcp.partstack.0" containerData="6000">
Import-Package: !org.eclipse.core.runtime,\
org.eclipse.swt,\
+org.eclipse.*;resolution:=optional,\
*
import org.argeo.api.cms.ux.CmsImageManager;
import org.argeo.api.cms.ux.CmsView;
import org.argeo.api.cms.ux.UxContext;
-import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.swt.CmsException;
+import org.argeo.cms.CurrentUser;
import org.argeo.cms.swt.CmsSwtUtils;
import org.argeo.cms.swt.SimpleSwtUxContext;
import org.argeo.cms.swt.auth.CmsLoginShell;
@Override
public void authChange(LoginContext loginContext) {
if (loginContext == null)
- throw new CmsException("Login context cannot be null");
+ throw new IllegalStateException("Login context cannot be null");
// logout previous login context
// if (this.loginContext != null)
// try {
@Override
public void logout() {
if (loginContext == null)
- throw new CmsException("Login context should not bet null");
+ throw new IllegalStateException("Login context should not bet null");
try {
CurrentUser.logoutCmsSession(loginContext.getSubject());
loginContext.logout();
} catch (LoginException e) {
- throw new CmsException("Cannot log out", e);
+ throw new IllegalStateException("Cannot log out", e);
}
}
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17"/>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>org.argeo.cms.swt.rcp.cli</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.ManifestBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- <buildCommand>
- <name>org.eclipse.pde.SchemaBuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.pde.PluginNature</nature>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
+++ /dev/null
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- .
+++ /dev/null
-package org.argeo.cms.swt.rcp.cli;
-
-import java.lang.management.ManagementFactory;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.concurrent.ForkJoinPool;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.Options;
-import org.argeo.api.acr.spi.ProvidedRepository;
-import org.argeo.api.cli.CommandsCli;
-import org.argeo.api.cli.DescribedCommand;
-import org.argeo.api.cms.CmsApp;
-import org.argeo.cms.runtime.StaticCms;
-import org.argeo.cms.swt.app.CmsUserApp;
-import org.argeo.cms.ui.rcp.CmsRcpDisplayFactory;
-import org.argeo.util.register.Component;
-import org.argeo.util.register.ComponentRegister;
-
-public class CmsCli extends CommandsCli {
-
- public CmsCli(String commandName) {
- super(commandName);
- addCommand("static", new Launch());
- }
-
- @Override
- public String getDescription() {
- return "Argeo CMS utilities.";
- }
-
- static class Launch implements DescribedCommand<String> {
- private Option dataOption;
- private Option uiOption;
-
- @Override
- public Options getOptions() {
- Options options = new Options();
- dataOption = Option.builder().longOpt("data").hasArg().required()
- .desc("path to the writable data area (mandatory)").build();
- uiOption = Option.builder().longOpt("ui").desc("open a user interface").build();
- options.addOption(dataOption);
- options.addOption(uiOption);
- return options;
- }
-
- @Override
- public String apply(List<String> args) {
- CommandLine cl = toCommandLine(args);
- String dataPath = cl.getOptionValue(dataOption);
- boolean ui = cl.hasOption(uiOption);
-
- Path instancePath = Paths.get(dataPath);
- System.setProperty("osgi.instance.area", instancePath.toUri().toString());
-
- StaticCms staticCms = new StaticCms() {
- @Override
- protected void addComponents(ComponentRegister register) {
- if (ui) {
- Component<? extends ProvidedRepository> contentRepositoryC = register
- .find(ProvidedRepository.class, null).first();
- CmsUserApp cmsApp = new CmsUserApp();
- Component<CmsUserApp> cmsAppC = new Component.Builder<>(cmsApp) //
- .addType(CmsApp.class) //
- .addType(CmsUserApp.class) //
- .addDependency(contentRepositoryC.getType(ProvidedRepository.class),
- cmsApp::setContentRepository, null) //
- .build(register);
-
- CmsRcpDisplayFactory displayFactory = new CmsRcpDisplayFactory();
- Component<CmsRcpDisplayFactory> displayFactoryC = new Component.Builder<>(displayFactory) //
- .addActivation(displayFactory::init) //
- .addDeactivation(displayFactory::destroy) //
- .build(register);
-
- }
- }
-
- @Override
- protected void postActivation(ComponentRegister register) {
- if (ui) {
- Component<? extends CmsUserApp> cmsAppC = register.find(CmsUserApp.class, null).first();
- CmsRcpDisplayFactory.openCmsApp(cmsAppC.get(), "data", (e) -> {
- // asynchronous in order to avoid deadlock in UI thread
- ForkJoinPool.commonPool().execute(() -> stop());
- });
- }
- }
-
- };
- Runtime.getRuntime().addShutdownHook(new Thread(() -> staticCms.stop(), "Static CMS Shutdown"));
- staticCms.start();
-
- long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
- System.out.println("Static CMS available in " + jvmUptime + " ms.");
-
- staticCms.waitForStop();
-
- return null;
- }
-
- @Override
- public String getDescription() {
- return "Launch a static CMS.";
- }
-
- }
-}
<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="CMS RCP Display Factory">
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="true" name="CMS RCP Display Factory">
<implementation class="org.argeo.cms.ui.rcp.CmsRcpDisplayFactory"/>
</scr:component>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" immediate="true" name="CMS RCP Servlet Factory">
+ <implementation class="org.argeo.cms.ui.rcp.CmsRcpHttpLauncher"/>
+ <reference bind="setHttpServer" cardinality="1..1" interface="com.sun.net.httpserver.HttpServer" name="HttpServer" policy="static"/>
+ <reference bind="addCmsApp" cardinality="0..n" interface="org.argeo.api.cms.CmsApp" name="CmsApp" policy="dynamic" unbind="removeCmsApp"/>
+</scr:component>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="init" deactivate="destroy" name="CMS RCP Servlet Factory">
- <implementation class="org.argeo.cms.ui.rcp.servlet.CmsRcpServletFactory"/>
- <reference bind="addCmsApp" cardinality="0..n" interface="org.argeo.api.cms.CmsApp" name="CmsApp" policy="dynamic" unbind="removeCmsApp"/>
- <reference bind="setHttpServer" cardinality="1..1" interface="com.sun.net.httpserver.HttpServer" name="HttpServer" policy="static"/>
-</scr:component>
+Bundle-SymbolicName: org.argeo.cms.swt.rcp;singleton=true
Import-Package:\
org.argeo.cms.auth,\
Service-Component:\
OSGI-INF/cmsRcpDisplayFactory.xml,\
-OSGI-INF/cmsRcpServletFactory.xml
+OSGI-INF/cmsRcpHttpLauncher.xml
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
- OSGI-INF/cmsRcpServletFactory.xml
+ OSGI-INF/cmsRcpHttpLauncher.xml
source.. = src/
package org.argeo.cms.ui.rcp;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
import java.nio.file.Path;
import org.argeo.api.cms.CmsApp;
-import org.argeo.util.OS;
+import org.argeo.cms.util.OS;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Display;
/** Creates the SWT {@link Display} in a dedicated thread. */
public class CmsRcpDisplayFactory {
+ private final static Logger logger = System.getLogger(CmsRcpDisplayFactory.class.getName());
+
/** File name in a run directory */
private final static String ARGEO_RCP_URL = "argeo.rcp.url";
@Override
public void run() {
- display = Display.getDefault();
- display.setRuntimeExceptionHandler((e) -> e.printStackTrace());
- display.setErrorHandler((e) -> e.printStackTrace());
-
-// for (String contextName : cmsApps.keySet()) {
-// openCmsApp(contextName);
-// }
-
- while (!shutdown) {
- if (!display.readAndDispatch())
- display.sleep();
+ try {
+ display = Display.getDefault();
+ display.setRuntimeExceptionHandler((e) -> e.printStackTrace());
+ display.setErrorHandler((e) -> e.printStackTrace());
+
+ while (!shutdown) {
+ if (!display.readAndDispatch())
+ display.sleep();
+ }
+ display.dispose();
+ display = null;
+ } catch (UnsatisfiedLinkError e) {
+ logger.log(Level.ERROR,
+ "Cannot load SWT, probably because the OSGi framework has been refresh. Restart the application.",
+ e);
}
- display.dispose();
- display = null;
}
}
--- /dev/null
+package org.argeo.cms.ui.rcp;
+
+import static java.lang.System.Logger.Level.DEBUG;
+
+import java.io.IOException;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
+import java.net.DatagramSocket;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.argeo.api.cms.CmsApp;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+
+/** Publishes one {@link CmsRcpServlet} per {@link CmsApp}. */
+public class CmsRcpHttpLauncher {
+ private final static Logger logger = System.getLogger(CmsRcpHttpLauncher.class.getName());
+ private CompletableFuture<HttpServer> httpServer = new CompletableFuture<>();
+
+ public void init() {
+
+ }
+
+ public void destroy() {
+ Path runFile = CmsRcpDisplayFactory.getUrlRunFile();
+ try {
+ if (Files.exists(runFile)) {
+ Files.delete(runFile);
+ }
+ } catch (IOException e) {
+ logger.log(Level.ERROR, "Cannot delete " + runFile, e);
+ }
+ }
+
+ public void addCmsApp(CmsApp cmsApp, Map<String, String> properties) {
+ final String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
+ if (contextName != null) {
+ httpServer.thenAcceptAsync((httpServer) -> {
+ httpServer.createContext("/" + contextName, new HttpHandler() {
+
+ @Override
+ public void handle(HttpExchange exchange) throws IOException {
+ String path = exchange.getRequestURI().getPath();
+ String uiName = path != null ? path.substring(path.lastIndexOf('/') + 1) : "";
+ CmsRcpDisplayFactory.openCmsApp(cmsApp, uiName, null);
+ exchange.sendResponseHeaders(200, -1);
+ logger.log(Level.DEBUG, "Opened RCP UI " + uiName + " of CMS App /" + contextName);
+ }
+ });
+ }).exceptionally(e -> {
+ logger.log(Level.ERROR, "Cannot register RCO app " + contextName, e);
+ return null;
+ });
+ logger.log(Level.DEBUG, "Registered RCP CMS APP /" + contextName);
+ }
+ }
+
+ public void removeCmsApp(CmsApp cmsApp, Map<String, String> properties) {
+ String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
+ if (contextName != null) {
+ httpServer.thenAcceptAsync((httpServer) -> {
+ httpServer.removeContext("/" + contextName);
+ });
+ }
+ }
+
+ public void setHttpServer(HttpServer httpServer) {
+ Integer httpPort = httpServer.getAddress().getPort();
+ String baseUrl = "http://localhost:" + httpPort + "/";
+ Path runFile = CmsRcpDisplayFactory.getUrlRunFile();
+ try {
+ if (!Files.exists(runFile)) {
+ Files.createDirectories(runFile.getParent());
+ // TODO give read permission only to the owner
+ Files.createFile(runFile);
+ } else {
+ URI uri = URI.create(Files.readString(runFile));
+ if (!httpPort.equals(uri.getPort()))
+ if (!isPortAvailable(uri.getPort())) {
+ throw new IllegalStateException("Another CMS is running on " + runFile);
+ } else {
+ logger.log(Level.WARNING,
+ "Run file " + runFile + " found but port of " + uri + " is available. Overwriting...");
+ }
+ }
+ Files.writeString(runFile, baseUrl, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new RuntimeException("Cannot write run file to " + runFile, e);
+ }
+ logger.log(DEBUG, "RCP available under " + baseUrl + ", written to " + runFile);
+ this.httpServer.complete(httpServer);
+ }
+
+ protected boolean isPortAvailable(int port) {
+ ServerSocket ss = null;
+ DatagramSocket ds = null;
+ try {
+ ss = new ServerSocket(port);
+ ss.setReuseAddress(true);
+ ds = new DatagramSocket(port);
+ ds.setReuseAddress(true);
+ return true;
+ } catch (IOException e) {
+ } finally {
+ if (ds != null) {
+ ds.close();
+ }
+
+ if (ss != null) {
+ try {
+ ss.close();
+ } catch (IOException e) {
+ /* should not be thrown */
+ }
+ }
+ }
+
+ return false;
+ }
+}
+++ /dev/null
-package org.argeo.cms.ui.rcp.servlet;
-
-import java.io.IOException;
-import java.lang.System.Logger;
-import java.lang.System.Logger.Level;
-import java.util.Objects;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.api.cms.CmsApp;
-import org.argeo.cms.ui.rcp.CmsRcpDisplayFactory;
-
-/** Open the related app when called. */
-public class CmsRcpServlet extends HttpServlet {
- private static final long serialVersionUID = -3944472431354848923L;
- private final static Logger logger = System.getLogger(CmsRcpServlet.class.getName());
-
- private CmsApp cmsApp;
-
- public CmsRcpServlet(CmsApp cmsApp) {
- Objects.requireNonNull(cmsApp);
- this.cmsApp = cmsApp;
- }
-
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String path = req.getPathInfo();
- String uiName = path != null ? path.substring(path.lastIndexOf('/') + 1) : "";
- CmsRcpDisplayFactory.openCmsApp(cmsApp, uiName, null);
- logger.log(Level.DEBUG, "Opened RCP UI " + uiName + " of CMS App " + req.getServletPath());
- }
-
-}
+++ /dev/null
-package org.argeo.cms.ui.rcp.servlet;
-
-import static java.lang.System.Logger.Level.DEBUG;
-
-import java.io.IOException;
-import java.lang.System.Logger;
-import java.lang.System.Logger.Level;
-import java.net.DatagramSocket;
-import java.net.ServerSocket;
-import java.net.URI;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Map;
-
-import org.argeo.api.cms.CmsApp;
-import org.argeo.cms.ui.rcp.CmsRcpDisplayFactory;
-
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-import com.sun.net.httpserver.HttpServer;
-
-/** Publishes one {@link CmsRcpServlet} per {@link CmsApp}. */
-public class CmsRcpServletFactory {
- private final static Logger logger = System.getLogger(CmsRcpServletFactory.class.getName());
- private HttpServer httpServer;
-// private BundleContext bundleContext = FrameworkUtil.getBundle(CmsRcpServletFactory.class).getBundleContext();
-//
-// private Map<String, ServiceRegistration<Servlet>> registrations = Collections.synchronizedMap(new HashMap<>());
-
- public void init() {
-
- }
-
- public void destroy() {
- Path runFile = CmsRcpDisplayFactory.getUrlRunFile();
- try {
- if (Files.exists(runFile)) {
- Files.delete(runFile);
- }
- } catch (IOException e) {
- logger.log(Level.ERROR, "Cannot delete " + runFile, e);
- }
- }
-
- public void addCmsApp(CmsApp cmsApp, Map<String, String> properties) {
- final String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
- if (contextName != null) {
- httpServer.createContext("/" + contextName, new HttpHandler() {
-
- @Override
- public void handle(HttpExchange exchange) throws IOException {
- String path = exchange.getRequestURI().getPath();
- String uiName = path != null ? path.substring(path.lastIndexOf('/') + 1) : "";
- CmsRcpDisplayFactory.openCmsApp(cmsApp, uiName, null);
- exchange.sendResponseHeaders(200, -1);
- logger.log(Level.DEBUG, "Opened RCP UI " + uiName + " of CMS App /" + contextName);
- }
- });
- logger.log(Level.DEBUG, "Registered RCP CMS APP /" + contextName);
-// CmsRcpServlet servlet = new CmsRcpServlet(cmsApp);
-// Hashtable<String, String> serviceProperties = new Hashtable<>();
-// serviceProperties.put("osgi.http.whiteboard.servlet.pattern", "/" + contextName + "/*");
-// ServiceRegistration<Servlet> sr = bundleContext.registerService(Servlet.class, servlet, serviceProperties);
-// registrations.put(contextName, sr);
- }
- }
-
- public void removeCmsApp(CmsApp cmsApp, Map<String, String> properties) {
- String contextName = properties.get(CmsApp.CONTEXT_NAME_PROPERTY);
- if (contextName != null) {
- httpServer.removeContext("/" + contextName);
-// ServiceRegistration<Servlet> sr = registrations.get(contextName);
-// sr.unregister();
- }
- }
-
- public void setHttpServer(HttpServer httpServer) {
- this.httpServer = httpServer;
- Integer httpPort = httpServer.getAddress().getPort();
- String baseUrl = "http://localhost:" + httpPort + "/";
- Path runFile = CmsRcpDisplayFactory.getUrlRunFile();
- try {
- if (!Files.exists(runFile)) {
- Files.createDirectories(runFile.getParent());
- // TODO give read permission only to the owner
- Files.createFile(runFile);
- } else {
- URI uri = URI.create(Files.readString(runFile));
- if (!httpPort.equals(uri.getPort()))
- if (!isPortAvailable(uri.getPort())) {
- throw new IllegalStateException("Another CMS is running on " + runFile);
- } else {
- logger.log(Level.WARNING,
- "Run file " + runFile + " found but port of " + uri + " is available. Overwriting...");
- }
- }
- Files.writeString(runFile, baseUrl, StandardCharsets.UTF_8);
- } catch (IOException e) {
- throw new RuntimeException("Cannot write run file to " + runFile, e);
- }
- logger.log(DEBUG, "RCP available under " + baseUrl + ", written to " + runFile);
- }
-
- protected boolean isPortAvailable(int port) {
- ServerSocket ss = null;
- DatagramSocket ds = null;
- try {
- ss = new ServerSocket(port);
- ss.setReuseAddress(true);
- ds = new DatagramSocket(port);
- ds.setReuseAddress(true);
- return true;
- } catch (IOException e) {
- } finally {
- if (ds != null) {
- ds.close();
- }
-
- if (ss != null) {
- try {
- ss.close();
- } catch (IOException e) {
- /* should not be thrown */
- }
- }
- }
-
- return false;
- }
-}
import java.util.Map;
import java.util.TreeMap;
-import org.apache.commons.io.IOUtils;
+import org.argeo.cms.util.StreamUtils;
import org.eclipse.rap.rwt.service.ResourceManager;
public class RcpResourceManager implements ResourceManager {
- private Map<String, byte[]> register = Collections
- .synchronizedMap(new TreeMap<String, byte[]>());
+ private Map<String, byte[]> register = Collections.synchronizedMap(new TreeMap<String, byte[]>());
@Override
public void register(String name, InputStream in) {
try {
- register.put(name, IOUtils.toByteArray(in));
+ register.put(name, StreamUtils.toByteArray(in));
} catch (IOException e) {
throw new RuntimeException("Cannot register " + name, e);
}