Java tutorial
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the Common Development and Distribution License, Version 1.0 * only (the "License"). You may not use this file except in compliance with the License. * * You can obtain a copy of the license at license/ESCIDOC.LICENSE or http://www.escidoc.de/license. See the License for * the specific language governing permissions and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each file and include the License file at * license/ESCIDOC.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by * brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2006-2011 Fachinformationszentrum Karlsruhe Gesellschaft fuer wissenschaftlich-technische Information mbH * and Max-Planck-Gesellschaft zur Foerderung der Wissenschaft e.V. All rights reserved. Use is subject to license * terms. */ package de.escidoc.core.common.util.xml; import com.ctc.wstx.exc.WstxParsingException; import de.escidoc.core.common.business.Constants; import de.escidoc.core.common.business.fedora.resources.ResourceType; import de.escidoc.core.common.exceptions.application.invalid.InvalidXmlException; import de.escidoc.core.common.exceptions.application.invalid.XmlCorruptedException; import de.escidoc.core.common.exceptions.application.invalid.XmlSchemaValidationException; import de.escidoc.core.common.exceptions.application.missing.MissingAttributeValueException; import de.escidoc.core.common.exceptions.system.EncodingSystemException; import de.escidoc.core.common.exceptions.system.WebserverSystemException; import de.escidoc.core.common.exceptions.system.XmlParserSystemException; import de.escidoc.core.common.util.configuration.EscidocConfiguration; import de.escidoc.core.common.util.stax.StaxParser; import de.escidoc.core.common.util.stax.handler.TaskParamHandler; import de.escidoc.core.common.util.string.StringUtility; import de.escidoc.core.common.util.xml.cache.SchemasCache; import de.escidoc.core.common.util.xml.stax.StaxAttributeEscapingWriterFactory; import de.escidoc.core.common.util.xml.stax.StaxTextEscapingWriterFactory; import de.escidoc.core.common.util.xml.stax.events.AbstractElement; import de.escidoc.core.common.util.xml.stax.events.StartElement; import de.escidoc.core.common.util.xml.stax.handler.CheckRootElementStaxHandler; import de.escidoc.core.common.util.xml.stax.handler.DefaultHandler; import de.escidoc.core.common.util.xml.transformer.PoolableTransformerFactory; import org.apache.commons.pool.impl.StackKeyedObjectPool; import org.codehaus.stax2.XMLOutputFactory2; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.XMLUnit; import org.escidoc.core.utils.io.Charsets; import org.escidoc.core.utils.io.IOUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import javax.naming.directory.NoSuchAttributeException; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import javax.xml.transform.Transformer; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.Validator; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Helper class to support Xml stuff in eSciDoc.<br> This class provides the validation of XML data using specified * schemas.<br> The schemas are specified by providing their schema URIs from that {@code Schema} objects are * created. These {@code Schema} objects are thread-safe and are cached to prevent unnecessary recreation. * * @author Torsten Tetteroo */ @Service("common.xml.XmlUtility") public final class XmlUtility { @Autowired @Qualifier("common.xml.SchemasCache") private SchemasCache schemasCache; private static final Logger LOGGER = LoggerFactory.getLogger(XmlUtility.class); /** * Pattern used to detect Object type is in resource type format, e.g. http://escidoc.de/core/01/resources/OrganizationalUnit */ public static final Pattern PATTERN_RESOURCE_OBJECT_TYPE = Pattern .compile('^' + Constants.RESOURCES_NS_URI + ".*$"); /** * The UTF-8 character encoding used in eSciDoc. */ public static final String CHARACTER_ENCODING = "UTF-8"; /** * The Mime-Type for XML. */ public static final String MIME_TYPE_XML = "text/xml"; /** * The XML version. */ private static final String XML_VERSION = "1.0"; /** * Head of document. */ public static final String DOCUMENT_START = "<?xml version=\"" + XML_VERSION + "\" encoding=\"" + CHARACTER_ENCODING + "\"?>\n"; /** * CDATA start. */ public static final String CDATA_START = "<![CDATA["; /** * CDATA end. */ public static final String CDATA_END = "]]>"; private static final String AMPERSAND = "&"; private static final String ESC_AMPERSAND = "&"; private static final String LESS_THAN = "<"; private static final String ESC_LESS_THAN = "<"; private static final String GREATER_THAN = ">"; private static final String ESC_GREATER_THAN = ">"; private static final String APOS = "'"; private static final String ESC_APOS = "'"; private static final String QUOT = "\""; private static final String ESC_QUOT = """; private static final Pattern PATTERN_ESCAPE_NEEDED = Pattern .compile(AMPERSAND + '|' + LESS_THAN + '|' + GREATER_THAN + '|' + QUOT + '|' + APOS); private static final Pattern PATTERN_UNESCAPE_NEEDED = Pattern.compile( ESC_AMPERSAND + '|' + ESC_LESS_THAN + '|' + ESC_GREATER_THAN + '|' + ESC_QUOT + '|' + ESC_APOS); private static final Pattern PATTERN_AMPERSAND = Pattern.compile('(' + AMPERSAND + ')'); private static final Pattern PATTERN_LESS_THAN = Pattern.compile('(' + LESS_THAN + ')'); private static final Pattern PATTERN_GREATER_THAN = Pattern.compile('(' + GREATER_THAN + ')'); private static final Pattern PATTERN_QUOT = Pattern.compile('(' + QUOT + ')'); private static final Pattern PATTERN_APOS = Pattern.compile('(' + APOS + ')'); private static final Pattern PATTERN_ESC_AMPERSAND = Pattern.compile('(' + ESC_AMPERSAND + ')'); private static final Pattern PATTERN_ESC_LESS_THAN = Pattern.compile('(' + ESC_LESS_THAN + ')'); private static final Pattern PATTERN_ESC_GREATER_THAN = Pattern.compile('(' + ESC_GREATER_THAN + ')'); private static final Pattern PATTERN_ESC_QUOT = Pattern.compile('(' + ESC_QUOT + ')'); private static final Pattern PATTERN_ESC_APOS = Pattern.compile('(' + ESC_APOS + ')'); private static String containerRestSchemaLocation; private static String relationsSchemaLocation; private static String itemRestSchemaLocation; private static String organizationalUnitRestSchemaLocation; private static String filterSchemaLocationRest; private static String organizationalUnitListRestSchemaLocation; private static String organizationalUnitPathListRestSchemaLocation; private static String organizationalUnitRefListRestSchemaLocation; private static String pdpRequestsSchemaLocation; private static String tmeRequestsSchemaLocation; private static String containersFilterRestSchemaLocation; private static String semanticStoreQuerySchemaLocation; private static String containerMembersFilterRestSchemaLocation; private static String contextRestSchemaLocation; private static String contentRelationRestSchemaLocation; private static String contentModelRestSchemaLocation; private static String setDefinitionRestSchemaLocation; private static String contextsFilterSchemaLocationRest; private static String contextMembersFilterSchemaLocationRest; private static String xmlSchemaSchemaLocation; private static String updatePasswordTaskParamSchemaLocation; private static String revokeGrantTaskParamSchemaLocation; private static String revokeGrantsTaskParamSchemaLocation; private static String membersTaskParamSchemaLocation; private static String assignPidTaskParamSchemaLocation; private static String idSetTaskParamSchemaLocation; private static String deleteObjectsParamSchemaLocation; private static String relationTaskParamSchemaLocation; private static String statusTaskParamSchemaLocation; private static String optimiticLockingTaskParamSchemaLocation; private static String reindexTaskParamSchemaLocation; private static String stagingFileSchemaLocation; private static String statisticDataSchemaLocation; private static String aggregationDefinitionRestSchemaLocation; private static String reportDefinitionRestSchemaLocation; private static String reportRestSchemaLocation; private static String scopeRestSchemaLocation; private static String reportParametersRestSchemaLocation; private static String preprocessingInformationSchemaLocation; private static String stylesheetDefinition; public static final String CDATA_END_QUOTED = "]]>"; public static final String NAME_ACTIVE = "active"; public static final String NAME_VALUE = "value"; public static final String NAME_TYPE = "type"; public static final String NAME_ASSIGNED_ON = "assigned-on"; public static final String NAME_COMPONENT = "component"; public static final String NAME_COMPONENTS = "components"; public static final String NAME_CREATED_BY = "created-by"; public static final String NAME_CREATION_DATE = "creation-date"; public static final String NAME_SPECIFICATION = "specification"; public static final String NAME_LOCK_OWNER = "lock-owner"; public static final String NAME_MEMBER = "member"; public static final String NAME_MODIFIED_BY = "modified-by"; public static final String NAME_CONTAINER_REF = "container-ref"; public static final String NAME_CONTENT_CATEGORY = "content-category"; public static final String NAME_ITEM_REF = "item-ref"; /** * The name of the last modification date attribute. */ public static final String NAME_LAST_MODIFICATION_DATE = "last-modification-date"; public static final String NAME_LATEST_RELEASE_NUMBER = "latest-release-number"; public static final String NAME_LATEST_VERSION_MODIFIED_BY = "latest-version-modified-by"; public static final String NAME_LATEST_VERSION_NUMBER = "latest-version-number"; public static final String NAME_LATEST_VERSION_STATUS = "latest-version-status"; public static final String NAME_LATEST_VERSION_VALID_STATUS = "latest-version-valid-status"; public static final String NAME_PUBLIC_STATUS = "public-status"; public static final String NAME_VALID_STATUS = "valid-status"; public static final String NAME_STATUS = "status"; public static final String NAME_VISIBILITY = "visibility"; public static final String NAME_ITEM = "item"; public static final String NAME_CONTEXT = "context"; public static final String NAME_CONTAINER = "container"; public static final String NAME_CONTENT_MODEL = "content-model"; public static final String NAME_CONTENT_RELATION = "content-relation"; public static final String NAME_USER_ACCOUNT = "user-account"; public static final String NAME_USER_GROUP = "user-group"; public static final String NAME_SET_DEFINITION = "set-definition"; public static final String NAME_ROLE = "role"; public static final String NAME_USER_ID = "userId"; public static final String NAME_GROUP_ID = "groupId"; public static final String NAME_ROLE_ID = "roleId"; public static final String NAME_OBJECT_ID = "objectId"; public static final String NAME_REVOCATION_DATE_FROM = "revocationDateFrom"; public static final String NAME_REVOCATION_DATE_TO = "revocationDateTo"; public static final String NAME_GRANTED_DATE_FROM = "grantedDateFrom"; public static final String NAME_GRANTED_DATE_TO = "grantedDateTo"; public static final String NAME_CREATOR_ID = "creatorId"; public static final String NAME_REVOKER_ID = "revokerId"; // Names of Statistic-Manager Resources public static final String NAME_STATISTIC_DATA = "statistic-data"; public static final String NAME_SCOPE = "scope"; public static final String NAME_AGGREGATION_DEFINITION = "aggregation-definition"; public static final String NAME_REPORT = "report"; public static final String NAME_REPORT_DEFINITION = "report-definition"; public static final String NAME_PREPROCESSING_INFORMATION = "preprocessing-information"; // ///////////////////////////////////////// public static final String NAME_OBJECT = "object"; public static final String NAME_ATTRIBUTES = "attributes"; public static final String NAME_ATTRIBUTE = "attribute"; private static final String NAME_OBJID = "objid"; public static final String NAME_NAME = "name"; public static final String NAME_PARAM = "param"; public static final String NAME_PID = "pid"; public static final String NAME_EXTERNAL_ID = "external-id"; public static final String NAME_PROPERTIES = "properties"; public static final String NAME_MDRECORDS = "md-records"; public static final String NAME_MDRECORD = "md-record"; private static final String NAME_RESOURCES = "resources"; public static final String NAME_ID = "id"; public static final String NAME_EMAIL = "email"; public static final String NAME_FILTER = "filter"; public static final String NAME_FORMAT = "format"; public static final String NAME_LOGIN_NAME = "login-name"; public static final String NAME_HANDLE = "handle"; private static final String NAME_HREF = "href"; public static final String NAME_DESCRIPTION = "description"; public static final String NAME_GENRE = "genre"; public static final String NAME_GRANT = "grant"; public static final String NAME_ORGANIZATIONAL_UNIT = "organizational-unit"; private static final String NAME_PARENT_OBJECTS = "parent-objects"; public static final String NAME_PARENTS = "parents"; public static final String NAME_PARENT = "parent"; private static final String NAME_CHILD_OBJECTS = "child-objects"; private static final String NAME_PATH_LIST = "path-list"; public static final String NAME_PREDECESSORS = "predecessors"; public static final String NAME_PREDECESSOR = "predecessor"; private static final String NAME_SUCCESSORS = "successors"; public static final String NAME_ORDER_BY = "order-by"; public static final String NAME_SORTING = "sorting"; public static final String NAME_LIMIT = "limit"; public static final String NAME_OFFSET = "offset"; public static final String NAME_UNSECURED_ACTION = "unsecured-action"; public static final String NAME_UNSECURED_ACTIONS = "unsecured-actions"; public static final String XPATH_USER_ACCOUNT_ORGANIZATIONAL_UNIT = "/user-account/properties/organizational-units/organizational-unit"; private static final String BASE_AA = "/aa/"; private static final String BASE_SM = "/statistic/"; private static final String BASE_OUM = "/oum/"; public static final String BASE_OM = "/ir/"; public static final String BASE_ORGANIZATIONAL_UNIT = BASE_OUM + NAME_ORGANIZATIONAL_UNIT + '/'; private static final String BASE_USER_ACCOUNT = BASE_AA + NAME_USER_ACCOUNT + '/'; private static final String BASE_USER_GROUP = BASE_AA + NAME_USER_GROUP + '/'; private static final String BASE_SET_DEFINITION = "/oai/" + NAME_SET_DEFINITION + '/'; public static final String BASE_ROLE = BASE_AA + NAME_ROLE + '/'; public static final String BASE_LOGIN = BASE_AA + "login" + '/'; private static final String BASE_SCOPE = BASE_SM + NAME_SCOPE + '/'; private static final String BASE_AGGREGATION_DEFINITION = BASE_SM + NAME_AGGREGATION_DEFINITION + '/'; private static final String BASE_REPORT_DEFINITION = BASE_SM + NAME_REPORT_DEFINITION + '/'; private static final Map<String, String> REST_SCHEMA_LOCATIONS = new HashMap<String, String>(); public static final String XPATH_USER_ACCOUNT_PROPERTIES = '/' + NAME_USER_ACCOUNT + '/' + NAME_PROPERTIES; /** * The thread-safe compiled Pattern used to extract the object id from an provided URI/Fedora id, e.g. from * <info:fedora/escidoc:1> or from http://www.escidoc.de/some/path/escidoc:1 */ private static final Pattern PATTERN_GET_ID_FROM_URI_OR_FEDORA_ID = Pattern.compile(".*/([^/>]+)>{0,1}"); /** * The thread-safe compiled pattern to extract an object id from an XML representation of a resource, either by * getting it from the attribute objid or extracting it from the attribute ...:href. */ private static final Pattern PATTERN_OBJID_FROM_XML = Pattern.compile("(.*?objid=\"|.*?:href=\".*/)(.*?)\".*"); /** * The thread-safe compiled pattern to extract a title from an XML representation of a resource. */ private static final Pattern PATTERN_NAME_FROM_XML = Pattern.compile( ".*?<.*?:" + NAME_NAME + ">(.*?)</.*?:" + NAME_NAME + ">.*", Pattern.DOTALL | Pattern.MULTILINE); private static final Pattern PATTERN_ID_WITHOUT_VERSION = Pattern.compile("([a-zA-Z]+:[a-zA-Z0-9]+):[0-9]+"); private static final Pattern PATTERN_VERSION_NUMBER = Pattern.compile("[a-zA-Z]+:[a-zA-Z0-9]+:([0-9]+)"); private static final String ERR_MSG_MISSING_ATTRIBUTE = "Missing attribute"; private static final StackKeyedObjectPool TRANSFORMER_POOL = new StackKeyedObjectPool( new PoolableTransformerFactory()); /** * Protected constructor to prevent instantiation outside of the Spring-context. */ protected XmlUtility() { } /** * Simple proxy method that can decide about the resource type and return the matching schema location. * * @param type The type of the resource. * @return Returns the location of the appropriate schema * @throws WebserverSystemException Thrown if retrieve of SchemaLocation failed. */ public static String getSchemaLocationForResource(final ResourceType type) throws WebserverSystemException { final String schemaLocation; switch (type) { case ITEM: schemaLocation = getItemSchemaLocation(); break; case CONTAINER: schemaLocation = getContainerSchemaLocation(); break; case CONTEXT: schemaLocation = getContextSchemaLocation(); break; case OU: schemaLocation = getOrganizationalUnitSchemaLocation(); break; case CONTENT_RELATION: schemaLocation = getContentRelationSchemaLocation(); break; case CONTENT_MODEL: schemaLocation = getContentModelSchemaLocation(); break; default: throw new WebserverSystemException("Unknown schema location for resoure type " + type); } return schemaLocation; } /** * Gets the organizational unit href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the provided organizational unit id. */ public static String getOrganizationalUnitHref(final String organizationalUnitId) { return BASE_ORGANIZATIONAL_UNIT + organizationalUnitId; } /** * Gets the container md records href for the provided organizational unit id. * * @param organizationalUnitId The id of organizational unit. * @return Returns the href for the md records of the provided organizational unit id. */ public static String getOrganizationalUnitMdRecordsHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_MDRECORDS; } /** * Gets the container properties href for the provided organizational unit id and name. * * @param organizationalUnitId The id of organizational unit. * @param name The name of the md record. * @return Returns the href for the md record of the provided organizational unit id and name. */ public static String getOrganizationalUnitMdRecordHref(final String organizationalUnitId, final String name) { return getOrganizationalUnitMdRecordsHref(organizationalUnitId) + '/' + NAME_MDRECORD + '/' + name; } /** * Gets the container href for the provided container id. * <p/> * Use the getHref() methods of the resource objects itself (Container). * * @param containerId The id of the container. * @return Returns the href for the provided container id. */ @Deprecated public static String getContainerHref(final String containerId) { return Constants.CONTAINER_URL_BASE + containerId; } /** * Gets the container properties href for the provided container id. * * @param containerHref The href of container. * @return Returns the href for the properties of the provided container id. */ public static String getContainerMdRecordsHref(final String containerHref) { return containerHref + '/' + NAME_MDRECORDS; } /** * Gets the container properties href for the provided container id. * * @param containerHref The href of the container. * @return Returns the href for the properties of the provided container id. */ public static String getContainerPropertiesHref(final String containerHref) { return containerHref + '/' + NAME_PROPERTIES; } /** * Gets the item href for the provided item id. * * @param itemId The id of the container. * @return Returns the href for the provided container id. */ public static String getItemHref(final String itemId) { return Constants.ITEM_URL_BASE + itemId; } /** * Gets the item parents href for the provided item href. * * @param itemHref The href of the item. * @return Returns the href for the data of the provided item id. */ public static String getItemParentsHref(final String itemHref) { return itemHref + '/' + NAME_RESOURCES + "/parents"; } /** * Gets the content-relation href for the provided content-relation id. * * @param contentRelationId The id of the content-relation. * @return Returns the href for the provided content-relation id. */ public static String getContentRelationHref(final String contentRelationId) { return Constants.CONTENT_RELATION_URL_BASE + contentRelationId; } /** * Gets the context href for the provided container id. * * @param contextId The id of the context. * @return Returns the href for the provided context id. */ public static String getContextHref(final String contextId) { return Constants.CONTEXT_URL_BASE + contextId; } /** * Get the properties href for the provided context. * * @param contextId The id of the context. * @return Returns the href of the properties for the provided context id. */ public static String getContextPropertiesHref(final String contextId) { return getContextHref(contextId) + '/' + NAME_PROPERTIES; } /** * Gets the context resources href for the provided context id. * * @param contextId The id of the context. * @return Returns the href for the data of the provided context id. */ public static String getContextResourcesHref(final String contextId) { return getContextHref(contextId) + '/' + NAME_RESOURCES; } /** * Gets the content model href for the provided content model id. * * @param contentModelId The id of the content model. * @return Returns the href for the provided content model id. */ public static String getContentModelHref(final String contentModelId) { return Constants.CONTENT_MODEL_URL_BASE + contentModelId; } /** * Gets the organizational unit properties href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the properties of the provided organizational unit id. */ public static String getOrganizationalUnitPropertiesHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_PROPERTIES; } /** * Gets the organizational unit parent-ous href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the parent-ous of the provided organizational unit id. */ public static String getOrganizationalUnitParentsHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_PARENTS; } /** * Get href of organizational unit predecessor OUs for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the predecessor OUs of the provided organizational unit id. */ public static String getOrganizationalUnitPredecessorsHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_PREDECESSORS; } /** * Get href of organizational unit successors for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the successor OUs of the provided organizational unit id. */ public static String getOrganizationalUnitSuccessorsHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_SUCCESSORS; } /** * Gets the container resources href for the provided container id. * * @param containerHref The href of the container. * @return Returns the href for the data of the provided container id. */ public static String getContainerResourcesHref(final String containerHref) { return containerHref + '/' + NAME_RESOURCES; } /** * Gets the container parents href for the provided container id. * * @param containerHref The href of the container. * @return Returns the href for the data of the provided container id. */ public static String getContainerParentsHref(final String containerHref) { return containerHref + '/' + NAME_RESOURCES + "/parents"; } /** * Gets the organizational unit resources href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the data of the provided organizational unit id. */ public static String getOrganizationalUnitResourcesHref(final String organizationalUnitId) { return getOrganizationalUnitHref(organizationalUnitId) + '/' + NAME_RESOURCES; } /** * Gets the organizational unit virtual resource parents href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the data of the provided organizational unit id. */ public static String getOrganizationalUnitResourcesParentObjectsHref(final String organizationalUnitId) { return getOrganizationalUnitResourcesHref(organizationalUnitId) + '/' + NAME_PARENT_OBJECTS; } /** * Gets the organizational unit virtual resource children href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the data of the provided organizational unit id. */ public static String getOrganizationalUnitResourcesChildObjectsHref(final String organizationalUnitId) { return getOrganizationalUnitResourcesHref(organizationalUnitId) + '/' + NAME_CHILD_OBJECTS; } /** * Gets the organizational unit virtual resource path-list href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the data of the provided organizational unit id. */ public static String getOrganizationalUnitResourcesPathListHref(final String organizationalUnitId) { return getOrganizationalUnitResourcesHref(organizationalUnitId) + '/' + NAME_PATH_LIST; } /** * Gets the organizational unit virtual resource successors href for the provided organizational unit id. * * @param organizationalUnitId The id of the organizational unit. * @return Returns the href for the data of the provided organizational unit id. */ public static String getOrganizationalUnitResourcesSuccessorsHref(final String organizationalUnitId) { return getOrganizationalUnitResourcesHref(organizationalUnitId) + '/' + NAME_SUCCESSORS; } /** * Gets the user account href for the provided user account id. * * @param userAccountId The id of the user account. * @return Returns the href for the provided user account id. */ public static String getUserAccountHref(final String userAccountId) { return BASE_USER_ACCOUNT + userAccountId; } /** * Gets the user group href for the provided user group id. * * @param userGroupId The id of the user group. * @return Returns the href for the provided user group id. */ public static String getUserGroupHref(final String userGroupId) { return BASE_USER_GROUP + userGroupId; } /** * Gets the set definition href for the provided set definition id. * * @param setDefinitionId The id of the set definition. * @return Returns the href for the provided set definition id. */ public static String getSetDefinitionHref(final String setDefinitionId) { return BASE_SET_DEFINITION + setDefinitionId; } /** * Gets the user group member href for the provided user group member id. * * @param userGroupHref The href of the user group member. * @param userGroupMemberId The id of the user group member. * @return Returns the href for the provided user group member id. */ public static String getUserGroupMemberHref(final String userGroupHref, final String userGroupMemberId) { return userGroupHref + "/selectors/selector/" + userGroupMemberId; } /** * Get the href for current grants. * * @param userAccountId objid of user account * @return href for the provided grant with user account id */ public static String getCurrentGrantsHref(final String userAccountId) { return getUserAccountHref(userAccountId) + "/resources/current-grants"; } public static String getPreferencesHref(final String userAccountId) { return getUserAccountHref(userAccountId) + "/resources/preferences"; } public static String getAttributesHref(final String userAccountId) { return getUserAccountHref(userAccountId) + "/resources/attributes"; } public static String getUserGroupCurrentGrantsHref(final String userGroupId) { return getUserGroupHref(userGroupId) + "/resources/current-grants"; } public static String getUserAccountResourcesHref(final String userAccountId) { return getUserAccountHref(userAccountId) + "/resources"; } public static String getUserGroupResourcesHref(final String userGroupId) { return getUserGroupHref(userGroupId) + "/resources"; } public static String getUserAccountGrantsHref(final String userAccountId) { return getUserAccountHref(userAccountId) + "/resources/grants"; } public static String getUserGroupGrantsHref(final String userGroupId) { return getUserGroupHref(userGroupId) + "/resources/grants"; } /** * Get the href to the specified role grant of the specified user. * * @param userAccountId The account of the user account owning the grant. * @param grantId The id of the grant. * @return The href of the provided role grant. */ public static String getUserAccountGrantHref(final String userAccountId, final String grantId) { return getUserAccountGrantsHref(userAccountId) + "/grant/" + grantId; } /** * Get the href to the specified role grant of the specified user group. * * @param userGroupId id of the user group owning the grant * @param grantId id of the grant * @return The href of the provided role grant. */ public static String getUserGroupGrantHref(final String userGroupId, final String grantId) { return getUserGroupGrantsHref(userGroupId) + "/grant/" + grantId; } /** * Get the href to the specified role. * * @param roleId The id of the role. * @return Returns the href to the role with the specified id. */ public static String getRoleHref(final String roleId) { return BASE_ROLE + roleId; } /** * Get the href to the specified scope. * * @param scopeId The id of the role. * @return Returns the href to the role with the specified id. */ public static String getScopeHref(final String scopeId) { return BASE_SCOPE + scopeId; } /** * Get the href to the specified aggregation-definition. * * @param aggregationDefinitionId The id of the aggregationDefinition. * @return Returns the href to the aggregationDefinitionId with the specified id. */ public static String getAggregationDefinitionHref(final String aggregationDefinitionId) { return BASE_AGGREGATION_DEFINITION + aggregationDefinitionId; } /** * Get the href to the specified report-definition. * * @param reportDefinitionId The id of the reportDefinition. * @return Returns the href to the reportDefinitionId with the specified id. */ public static String getReportDefinitionHref(final String reportDefinitionId) { return BASE_REPORT_DEFINITION + reportDefinitionId; } /** * Adds a new element to the provided {@code XMLStreamWriter} object containing a {@code String} value. * * @param writer The {@code XMLStreamWriter} object to add the element to. * @param elementName The name of the new element. * @param elementContent The {@code String} that shall be set as the value of the new element. * @param namespaceUri The namespace URI of the new element. * @param createEmpty Flag indicating if a an empty element shall be created if the provided data is * {@code null} ( {@code true} ), or if the element shall not be created ( * {@code false} ). * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addElement(final XMLStreamWriter writer, final String elementName, final String elementContent, final String namespaceUri, final boolean createEmpty) throws XMLStreamException { if (elementContent == null) { if (createEmpty) { writer.writeEmptyElement(namespaceUri, elementName); } } else { writer.writeStartElement(namespaceUri, elementName); writer.writeCharacters(elementContent); writer.writeEndElement(); } } /** * Adds a new element to the provided {@code XMLStreamWriter} object containing a date value. * * @param writer The {@code XMLStreamWriter} object to add the element to. * @param elementName The name of the new element. * @param elementContent The {@code Date} that shall be set as the value of the new element. * @param namespaceUri The namespace URI of the new element. * @param createEmpty Flag indicating if a an empty element shall be created if the provided data is * {@code null} ( {@code true} ), or if the element shall not be created ( * {@code false} ). * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addElement(final XMLStreamWriter writer, final String elementName, final DateTime elementContent, final String namespaceUri, final boolean createEmpty) throws XMLStreamException { if (elementContent == null) { if (createEmpty) { writer.writeEmptyElement(namespaceUri, elementName); } } else { writer.writeStartElement(namespaceUri, elementName); writer.writeCharacters(elementContent.withZone(DateTimeZone.UTC).toString(Constants.TIMESTAMP_FORMAT)); writer.writeEndElement(); } } /** * Adds the "last-modification-date" attribute to the provided {@code XMLStreamWriter}.<br> The value of the * attribute is set to the value of the provided date.<br> If no date is provided, nothing is added. * * @param writer The {@code XMLStreamWriter} object to add the attribute to. * @param modifiedDate The date to set as the last modified date. * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addLastModificationDateAttribute(final XMLStreamWriter writer, final DateTime modifiedDate) throws XMLStreamException { if (modifiedDate == null) { return; } writer.writeAttribute("last-modification-date", modifiedDate.withZone(DateTimeZone.UTC).toString(Constants.TIMESTAMP_FORMAT)); } /** * Adds the provided object id to the {@code XMLStreamWriter} that has been provided.<br> The object id is * added as the attribute "objid". * * @param writer The {@code XMLStreamWriter} object to add the attribute to. * @param objId The object id to add. * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addObjectId(final XMLStreamWriter writer, final String objId) throws XMLStreamException { writer.writeAttribute("objid", objId); } /** * Adds a new element to the provided {@code XMLStreamWriter} containing a simple xlink with the provided * values. The new element is empty. * * @param writer The {@code XMLStreamWriter} object to add the element to. * @param elementName The name of the new element. * @param xlinkTitle The title of the xlink contained in the new element. * @param xlinkHref The href of the xlink contained in the new element. * @param namespaceUri The namespace URI of the new element. * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addReferencingElement(final XMLStreamWriter writer, final String elementName, final String xlinkTitle, final String xlinkHref, final String namespaceUri) throws XMLStreamException { writer.writeStartElement(namespaceUri, elementName); addXlinkAttributes(writer, xlinkTitle, xlinkHref); writer.writeEndElement(); } /** * Adds the xlink attributes to the provided {@code Element}.<br> The attribute "xlink:type" is set to * "simple", the attributes "xlink:title" and "xlink:href" to the respective provided values.<br> If the provided * title is {@code null}. the title attribute is skipped. * * @param writer The {@code XMLStreamWriter} object to add the attributes to. * @param xlinkTitle The title of the xlink. * @param xlinkHref The href of the xlink. * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addXlinkAttributes(final XMLStreamWriter writer, final String xlinkTitle, final String xlinkHref) throws XMLStreamException { writer.writeAttribute(Constants.XLINK_NS_URI, "type", "simple"); if (xlinkTitle != null) { writer.writeAttribute(Constants.XLINK_NS_URI, "title", xlinkTitle); } writer.writeAttribute(Constants.XLINK_NS_URI, "href", xlinkHref); } /** * Adds the "xml:base" attribute to the provided {@code XMLStreamWriter}.<br> The value of the attribute is set * to the value of the configuration property {@code escidoc.baseurl}. * * @param writer The {@code XMLStreamWriter} object to add the attribute to. * @throws IOException Thrown if the base url cannot be determined. * @throws XMLStreamException Thrown in case of an xml stream error. */ public static void addXmlBaseAttribute(final XMLStreamWriter writer) throws XMLStreamException { writer.writeAttribute(Constants.XML_NS_URI, "base", EscidocConfiguration.getInstance().get(EscidocConfiguration.ESCIDOC_CORE_BASEURL)); } /** * Gets the {@code Schema} from the cache.<br> If none exists for the provided schema URL, it is created and * put into the cache. * * @param schemaUri The schema URI * @return Returns the validator for the schema specified by the provided URL. * @throws IOException Thrown in case of an I/O error. * @throws WebserverSystemException Thrown if schema can not be parsed. */ public Schema getSchema(final String schemaUri) throws IOException, WebserverSystemException { return schemasCache.getSchema(schemaUri); } /** * Validates the provided XML data using the specified schema and creates a {@code ByteArrayInputStream} for * the data. * * @param xmlData The xml data. * @param schemaUri The URL identifying the schema that shall be used for validation. * @return Returns the xml data in a {@code ByteArrayInputStream}. * @throws XmlSchemaValidationException Thrown if data in not valid. * @throws XmlCorruptedException Thrown if the XML data cannot be parsed. * @throws WebserverSystemException Thrown in case of any other failure. */ public ByteArrayInputStream createValidatedByteArrayInputStream(final String xmlData, final String schemaUri) throws XmlCorruptedException, WebserverSystemException, XmlSchemaValidationException { final ByteArrayInputStream byteArrayInputStream = convertToByteArrayInputStream(xmlData); validate(byteArrayInputStream, schemaUri); return byteArrayInputStream; } /** * Validates the provided XML data using the specified schema.<br> The provided {@code ByteArrayInputStream} is * reset after validation. * * @param byteArrayInputStream The XML data to validate in an {@code ByteArrayInputStream}.<br> This input * stream is reset after the validation. * @param schemaUri The URL identifying the schema that shall be used for validation. * @throws XmlCorruptedException Thrown if the XML data cannot be parsed. * @throws XmlSchemaValidationException Thrown if both validation fail or only one validation is executed and fails * @throws WebserverSystemException Thrown in any other case. */ public void validate(final ByteArrayInputStream byteArrayInputStream, final String schemaUri) throws XmlCorruptedException, XmlSchemaValidationException, WebserverSystemException { try { final Validator validator = getSchema(schemaUri).newValidator(); validator.validate(new SAXSource(new InputSource(byteArrayInputStream))); } catch (final SAXParseException e) { final String errorMsg = "Error in line " + e.getLineNumber() + ", column " + e.getColumnNumber() + ". " + e.getMessage(); if (e.getMessage().startsWith("cvc")) { throw new XmlSchemaValidationException(errorMsg, e); } else { throw new XmlCorruptedException(errorMsg, e); } } catch (final Exception e) { throw new WebserverSystemException(e.getMessage(), e); } finally { if (byteArrayInputStream != null) { byteArrayInputStream.reset(); } } } /** * Checks, if the provided XML data has the provided root element, afterwards validates the provided XML data using * the specified schema. * * @param xmlData The XML data to validate. * @param schemaUri The URL identifying the schema that shall be used for validation. * @param root Check for this root element. * @throws XmlCorruptedException Thrown if the XML data cannot be parsed. * @throws XmlSchemaValidationException Thrown if both validation fail or only one validation is executed and fails * @throws WebserverSystemException Thrown in any other case. * @throws XmlParserSystemException Thrown if the expected root element raise an unexpected error. */ public void validate(final String xmlData, final String schemaUri, final String root) throws XmlCorruptedException, XmlSchemaValidationException, WebserverSystemException, XmlParserSystemException { if (root.length() > 0) { checkRootElement(xmlData, root); } validate(xmlData, schemaUri); } /** * Check if the root element has the expected element. * * @param xmlData The XML document which is to check. * @param expectedRoot The expected root element. * @throws XmlCorruptedException Thrown if the document has not the expected element. * @throws XmlParserSystemException Thrown if the expected root element raise an unexpected error. */ private static void checkRootElement(final String xmlData, final String expectedRoot) throws XmlCorruptedException, XmlParserSystemException { final StaxParser sp = new StaxParser(); final CheckRootElementStaxHandler checkRoot = new CheckRootElementStaxHandler(expectedRoot); sp.addHandler(checkRoot); try { sp.parse(xmlData); } catch (final InvalidXmlException e) { throw new XmlCorruptedException("Xml Document has wrong root element, expected '" + expectedRoot + "'.", e); } catch (final WstxParsingException e) { throw new XmlCorruptedException(e.getMessage(), e); } catch (final WebserverSystemException e) { // ignore, check was successful and parsing aborted } catch (final Exception e) { handleUnexpectedStaxParserException( "Check for root '" + expectedRoot + "' element raised unexpected exception! ", e); } } /** * Validates the provided XML data using the specified schema. * * @param xmlData The XML data to validate. * @param schemaUri The URL identifying the schema that shall be used for validation. * @throws XmlCorruptedException Thrown if the XML data cannot be parsed. * @throws XmlSchemaValidationException Thrown if both validation fail or only one validation is executed and fails * @throws WebserverSystemException Thrown in any other case. */ public void validate(final String xmlData, final String schemaUri) throws XmlCorruptedException, XmlSchemaValidationException, WebserverSystemException { validate(convertToByteArrayInputStream(xmlData), schemaUri); } /** * Validates the provided XML data using the specified resource type. * * @param xmlData The XML data to validate. * @param resourceType The resourceType whose schema will be used for validation validation. * @throws XmlCorruptedException Thrown if the XML data cannot be parsed. * @throws XmlSchemaValidationException # Thrown if both validation fail or only one validation is executed and * fails * @throws WebserverSystemException Thrown in any other case. */ public void validate(final String xmlData, final ResourceType resourceType) throws XmlCorruptedException, XmlSchemaValidationException, WebserverSystemException { validate(xmlData, getSchemaLocationForResource(resourceType)); } /** * Converts the provided String to a {@code ByteArrayInputStream}. * * @param str The string to get as {@code ByteArrayInputStream}. * @return Returns the {@code ByteArrayInputStream} for the provided string. */ public static ByteArrayInputStream convertToByteArrayInputStream(final String str) { try { return new ByteArrayInputStream(str.getBytes(CHARACTER_ENCODING)); } catch (final UnsupportedEncodingException e) { // this should not happen return new ByteArrayInputStream("".getBytes(Charsets.UTF8_CHARSET)); } } /** * Converts the provided String to a {@code ByteArrayOutputStream}. * * @param str The string to get as {@code ByteArrayOutputStream}. * @return Returns the {@code ByteArrayOutputStream} for the provided string. */ public static ByteArrayOutputStream convertToByteArrayOutputStream(final String str) { final ByteArrayOutputStream stream = new ByteArrayOutputStream(); try { stream.write(str.getBytes(CHARACTER_ENCODING)); } catch (final UnsupportedEncodingException e) { if (LOGGER.isWarnEnabled()) { LOGGER.warn("Error on writing to stream."); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Error on writing to stream.", e); } } catch (final IOException e) { if (LOGGER.isWarnEnabled()) { LOGGER.warn("Error on writing to stream."); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Error on writing to stream.", e); } } return stream; } /** * Get the objid from an URI/Fedora identifier, e.g. from <info:fedora/escidoc:1><br/> If the provided value * does not match the expected pattern, it is returned as provided. Otherwise, the objid is extracted from it and * returned. * * @param uri The value to get the objid from * @return Returns the extracted objid or the provided value. */ public static String getIdFromURI(final String uri) { if (uri == null) { return null; } final Matcher matcher = PATTERN_GET_ID_FROM_URI_OR_FEDORA_ID.matcher(uri); return matcher.find() ? matcher.group(1) : uri; } /** * Extracts the objid from the provided resource XML representation.<br/> Either the first occurence of objid="..." * is searched and the value is returned, or the first occurence of :href="..." is searched and from this value the * objid is extracted and returned. * * @param resourceXml The XML representation of the resource to get the objid from. * @return Returns the extracted objid or {@code null}. */ public static String getIdFromXml(final CharSequence resourceXml) { final Matcher matcher = PATTERN_OBJID_FROM_XML.matcher(resourceXml); return matcher.find() ? matcher.group(2) : null; } /** * Extracts the objid from the provided element.<br/> Either the id is fetched from the attribute objid of the * provided element. If this fails, it is extracted from the attribute href. If this fials, too, an exception is * thrown. * * @param element The element to get the objid from. * @return Returns the objid value. * @throws MissingAttributeValueException Thrown if neither an objid nor an href attribute exists. */ public static String getIdFromStartElement(final StartElement element) throws MissingAttributeValueException { try { return element.indexOfAttribute(null, NAME_OBJID) == -1 ? getIdFromURI(element.getAttributeValue(Constants.XLINK_NS_URI, NAME_HREF)) : element.getAttributeValue(null, NAME_OBJID); } catch (final NoSuchAttributeException e) { throwMissingAttributeValueException(element, NAME_OBJID + '|' + NAME_HREF); return null; } } /** * Remove version information from given objid. * * @param objid The objid. * @return The objid without version information. */ public static String getObjidWithoutVersion(final String objid) { String result = objid; final Matcher m = PATTERN_ID_WITHOUT_VERSION.matcher(objid); if (m.find()) { result = m.group(1); } return result; } /** * Extract version number from objid. * * @param objid The objid. * @return The number of version or null. */ public static String getVersionNumberFromObjid(final CharSequence objid) { String version = null; final Matcher m = PATTERN_VERSION_NUMBER.matcher(objid); if (m.find()) { version = m.group(1); } return version; } /** * Extracts the name from the provided resource XML representation.<br> The first occurence of * <...:name>...</...:name> is searched and the value is returned. * * @param resourceXml The XML representation of the resource to get the name from. * @return Returns the extracted name (trimmed) or {@code null}. */ public static String extractNameFromXml(final CharSequence resourceXml) { final Matcher matcher = PATTERN_NAME_FROM_XML.matcher(resourceXml); return matcher.find() ? matcher.group(1).trim() : null; } /** * Convert the given date into a XML compliant format in UTC. * * @param date date * @return normalized date string */ public static String normalizeDate(final Date date) { return new DateTime(date).withZone(DateTimeZone.UTC).toString(Constants.TIMESTAMP_FORMAT); } /** * Convert the given date string into a XML compliant format in UTC. * * @param date date string * @return normalized date string */ public static String normalizeDate(final String date) { return new DateTime(date).withZone(DateTimeZone.UTC).toString(Constants.TIMESTAMP_FORMAT); } /** * Parse the task parameter structure. * * @param param The parameter structure. * @return The handler holding the extracted values. * @throws EncodingSystemException If a wrong Encoding is detected. * @throws XmlCorruptedException If the given XML is not valid. */ public static TaskParamHandler parseTaskParam(final String param) throws XmlCorruptedException, EncodingSystemException { return parseTaskParam(param, true); } public static TaskParamHandler parseTaskParam(final String param, final boolean checkLastModificationDate) throws XmlCorruptedException, EncodingSystemException { final StaxParser staxParser = new StaxParser(); final TaskParamHandler result = new TaskParamHandler(staxParser); if (param != null) { result.setCheckLastModificationDate(checkLastModificationDate); final ByteArrayInputStream xmlDataIs; try { xmlDataIs = new ByteArrayInputStream(param.getBytes(CHARACTER_ENCODING)); } catch (final UnsupportedEncodingException e) { throw new EncodingSystemException(e.getMessage(), e); } final List<DefaultHandler> handlerChain = new ArrayList<DefaultHandler>(); handlerChain.add(result); staxParser.setHandlerChain(handlerChain); try { staxParser.parse(xmlDataIs); } catch (final Exception e) { throw new XmlCorruptedException(e.getMessage(), e); } staxParser.clearHandlerChain(); } return result; } /** * Retrieves the base url for XML schemas for internal validation (i.e. escidoc-core.selfurl + * escidoc-core.xsd-path.<br> * * @return Returns the base url. * @throws WebserverSystemException In case of an error. */ public static String getSchemaBaseUrl() { return EscidocConfiguration.getInstance().appendToSelfURL( EscidocConfiguration.getInstance().get(EscidocConfiguration.ESCIDOC_CORE_XSD_PATH) + '/'); } /** * Gets the stylesheet definition. * * @return Returns the stylesheet definition. This may be an empty string, if the xslt has not been defined with the * eSciDoc configuration property escidoc.xslt.std. * @throws WebserverSystemException In case of an error. */ public static String getStylesheetDefinition() { if (stylesheetDefinition == null) { String xslt = EscidocConfiguration.getInstance().get(EscidocConfiguration.ESCIDOC_CORE_XSLT_STD); if (xslt == null || xslt.isEmpty()) { // FIXME a non-existing values should be null and not an empty string stylesheetDefinition = ""; } else { // add baseurl, if xslt is not http or https protocol /* * taking base url from configuration is actually an hacking, because the servlet context is missing in the * deep of these methods. */ if (!(xslt.startsWith("http://") || xslt.startsWith("https://"))) { String baseurl = EscidocConfiguration.getInstance() .get(EscidocConfiguration.ESCIDOC_CORE_BASEURL); if (!baseurl.endsWith("/")) { baseurl += "/"; } if (xslt.startsWith("./")) { xslt = baseurl + xslt.substring(2, xslt.length()); } else if (xslt.startsWith("/")) { xslt = baseurl + xslt.substring(1, xslt.length()); } } stylesheetDefinition = "<?xml-stylesheet type=\"text/xsl\" href=\"" + xslt + "\"?>\n"; } } return stylesheetDefinition; } /** * @return Returns the adminDescriptorSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getAdminDescriptorSchemaLocation() { if (contextRestSchemaLocation == null) { final String subPath = "context/0.4/context.xsd"; contextRestSchemaLocation = getSchemaBaseUrl() + "rest/" + subPath; } return contextRestSchemaLocation; } /** * @return Returns the containerSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContainerSchemaLocation() { if (containerRestSchemaLocation == null) { containerRestSchemaLocation = getSchemaBaseUrl() + "rest/container" + Constants.CONTAINER_NS_URI_SCHEMA_VERSION + "/container.xsd"; } return containerRestSchemaLocation; } /** * @return Returns the Semantic Store Schema Location. * @throws WebserverSystemException In case of an error. */ public static String getSematicStoreQuerySchemaLocation() { if (semanticStoreQuerySchemaLocation == null) { semanticStoreQuerySchemaLocation = getSchemaBaseUrl() + "rest/common/0.4/semantic-store-query.xsd"; } return semanticStoreQuerySchemaLocation; } /** * @return Returns the containerMembersFilterSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContainerMembersFilterSchemaLocation() { if (containerMembersFilterRestSchemaLocation == null) { containerMembersFilterRestSchemaLocation = getSchemaBaseUrl() + "rest/container/0.3/filter-members.xsd"; } return containerMembersFilterRestSchemaLocation; } /** * @return Returns the containersFilterSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContainersFilterSchemaLocation() { if (containersFilterRestSchemaLocation == null) { containersFilterRestSchemaLocation = getSchemaBaseUrl() + "rest/container/0.3/filter-containers.xsd"; } return containersFilterRestSchemaLocation; } /** * @return Returns the content relation schema location. * @throws WebserverSystemException In case of an error. */ public static String getContentModelSchemaLocation() { if (contentModelRestSchemaLocation == null) { final String contentModelXsd = "content-model" + Constants.CONTENT_MODEL_NS_URI_SCHEMA_VERSION + "/content-model.xsd"; contentModelRestSchemaLocation = getSchemaBaseUrl() + "rest/" + contentModelXsd; } return contentModelRestSchemaLocation; } /** * @return Returns the contextSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContextSchemaLocation() { if (contextRestSchemaLocation == null) { final String contextXsd = "context" + Constants.CONTEXT_NS_URI_SCHEMA_VERSION + "/context.xsd"; contextRestSchemaLocation = getSchemaBaseUrl() + "rest/" + contextXsd; } return contextRestSchemaLocation; } /** * @return Returns the content relation schema location. * @throws WebserverSystemException In case of an error. */ public static String getContentRelationSchemaLocation() { if (contentRelationRestSchemaLocation == null) { final String contentRelationXsd = "content-relation" + Constants.CONTENT_RELATION_NS_URI_SCHEMA_VERSION + "/content-relation.xsd"; contentRelationRestSchemaLocation = getSchemaBaseUrl() + "rest/" + contentRelationXsd; } return contentRelationRestSchemaLocation; } /** * @return Returns the contextSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getSetDefinitionSchemaLocation() { if (setDefinitionRestSchemaLocation == null) { final String setDefinitionXsd = "set-definition/0.2/set-definition.xsd"; setDefinitionRestSchemaLocation = getSchemaBaseUrl() + "rest/" + setDefinitionXsd; } return setDefinitionRestSchemaLocation; } /** * @return Returns the contextsFilterSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContextsFilterSchemaLocation() { if (contextsFilterSchemaLocationRest == null) { contextsFilterSchemaLocationRest = getSchemaBaseUrl() + "rest/context/0.3/filter-contexts.xsd"; } return contextsFilterSchemaLocationRest; } /** * @return Returns the contextMembersFilterSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getContextMembersFilterSchemaLocation() { if (contextMembersFilterSchemaLocationRest == null) { contextMembersFilterSchemaLocationRest = getSchemaBaseUrl() + "rest/" + "context/0.3/filter-contexts.xsd"; } return contextMembersFilterSchemaLocationRest; } /** * @return Returns the grantsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getGrantsSchemaLocation() { return getSchemaLocation("user-account/0.5/grants.xsd"); } /** * @return Returns the preferencesSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getPreferencesSchemaLocation() { return getSchemaLocation("user-account/0.1/preferences.xsd"); } /** * @return Returns the preferencesSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getAttributesSchemaLocation() { return getSchemaLocation("user-account/0.1/attributes.xsd"); } /** * @return Returns the itemSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getItemSchemaLocation() { if (itemRestSchemaLocation == null) { itemRestSchemaLocation = getSchemaBaseUrl() + "rest/item" + Constants.ITEM_NS_URI_SCHEMA_VERSION + "/item.xsd"; } return itemRestSchemaLocation; } /** * @return Returns the relationsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getRelationsSchemaLocation() { if (relationsSchemaLocation == null) { relationsSchemaLocation = getSchemaBaseUrl() + "rest/common/0.3/relations.xsd"; } return relationsSchemaLocation; } /** * @return Returns the organizationalUnitSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getOrganizationalUnitSchemaLocation() { if (organizationalUnitRestSchemaLocation == null) { organizationalUnitRestSchemaLocation = getSchemaBaseUrl() + "rest/" + NAME_ORGANIZATIONAL_UNIT + Constants.ORGANIZATIONAL_UNIT_NS_URI_SCHEMA_VERSION + "/organizational-unit.xsd"; } return organizationalUnitRestSchemaLocation; } /** * @return Returns the organizationalUnitListSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getOrganizationalUnitListSchemaLocation() { if (organizationalUnitListRestSchemaLocation == null) { organizationalUnitListRestSchemaLocation = getSchemaBaseUrl() + "rest/" + NAME_ORGANIZATIONAL_UNIT + Constants.CONTAINER_LIST_NS_URI_SCHEMA_VERSION + "/organizational-unit-list.xsd"; } return organizationalUnitListRestSchemaLocation; } /** * @return Returns the organizationalUnitPathListSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getOrganizationalUnitPathListSchemaLocation() { if (organizationalUnitPathListRestSchemaLocation == null) { organizationalUnitPathListRestSchemaLocation = getSchemaBaseUrl() + "rest/organizational-unit/0.4/organizational-unit-path-list.xsd"; } return organizationalUnitPathListRestSchemaLocation; } /** * @return Returns the organizationalUnitRefListSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getOrganizationalUnitRefListSchemaLocation() { if (organizationalUnitRefListRestSchemaLocation == null) { organizationalUnitRefListRestSchemaLocation = getSchemaBaseUrl() + "rest/organizational-unit/0.4/organizational-unit-ref-list.xsd"; } return organizationalUnitRefListRestSchemaLocation; } /** * @return Returns the filterSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getFilterSchemaLocation() { if (filterSchemaLocationRest == null) { filterSchemaLocationRest = getSchemaBaseUrl() + "rest/common/0.4/filter.xsd"; } return filterSchemaLocationRest; } /** * @return Returns the pdpRequestsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getPdpRequestsSchemaLocation() { if (pdpRequestsSchemaLocation == null) { pdpRequestsSchemaLocation = getSchemaBaseUrl() + "rest/pdp/0.3/requests.xsd"; } return pdpRequestsSchemaLocation; } /** * @return Returns the roleSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getRoleSchemaLocation() { return getSchemaLocation("role/0.5/role.xsd"); } /** * @return Returns the stagingFileSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getStagingFileSchemaLocation() { if (stagingFileSchemaLocation == null) { stagingFileSchemaLocation = getSchemaBaseUrl() + "rest/staging-file/0.3/staging-file.xsd"; } return stagingFileSchemaLocation; } /** * @return Returns the tmeRequestsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getTmeRequestsSchemaLocation() { if (tmeRequestsSchemaLocation == null) { tmeRequestsSchemaLocation = getSchemaBaseUrl() + "tme/0.1/request.xsd"; } return tmeRequestsSchemaLocation; } /** * @return Returns the unsecuredActionsSchemaLocation dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ public static String getUnsecuredActionsSchemaLocation() { return getSchemaLocation("role/0.4/unsecured-actions.xsd"); } /** * @return Returns the userAccountSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getUserAccountSchemaLocation() { return getSchemaLocation( "user-account" + Constants.USER_ACCOUNT_NS_URI_SCHEMA_VERSION + "/user-account.xsd"); } /** * @return Returns the addSelectorsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getAddSelectorsSchemaLocation() { return getSchemaLocation("user-group/0.6/add-selectors.xsd"); } /** * @return Returns the removeSelectorsSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getRemoveSelectorsSchemaLocation() { return getSchemaLocation("user-group/0.6/remove-selectors.xsd"); } /** * @return Returns the userGroupSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getUserGroupSchemaLocation() { return getSchemaLocation("user-group/0.6/user-group.xsd"); } /** * @return Returns the statisticDataSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getStatisticDataSchemaLocation() { if (statisticDataSchemaLocation == null) { statisticDataSchemaLocation = getSchemaBaseUrl() + "rest/statistic-data/0.3/statistic-data.xsd"; } return statisticDataSchemaLocation; } /** * @return Returns the aggregationDefinitionSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getAggregationDefinitionSchemaLocation() { if (aggregationDefinitionRestSchemaLocation == null) { aggregationDefinitionRestSchemaLocation = getSchemaBaseUrl() + "rest/aggregation-definition" + Constants.AGGREGATION_DEFINITION_NS_URI_SCHEMA_VERSION + "/aggregation-definition.xsd"; } return aggregationDefinitionRestSchemaLocation; } /** * @return Returns the reportDefinitionSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getReportDefinitionSchemaLocation() { if (reportDefinitionRestSchemaLocation == null) { reportDefinitionRestSchemaLocation = getSchemaBaseUrl() + "rest/report-definition" + Constants.REPORT_DEFINITION_NS_URI_SCHEMA_VERSION + "/report-definition.xsd"; } return reportDefinitionRestSchemaLocation; } /** * @return Returns the scopeSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getScopeSchemaLocation() { if (scopeRestSchemaLocation == null) { scopeRestSchemaLocation = getSchemaBaseUrl() + "rest/scope" + Constants.SCOPE_NS_URI_SCHEMA_VERSION + "/scope.xsd"; } return scopeRestSchemaLocation; } /** * @return Returns the reportSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getReportSchemaLocation() { if (reportRestSchemaLocation == null) { reportRestSchemaLocation = getSchemaBaseUrl() + "rest/report" + Constants.REPORT_NS_URI_SCHEMA_VERSION + "/report.xsd"; } return reportRestSchemaLocation; } /** * @return Returns the ReportParametersSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getReportParametersSchemaLocation() { if (reportParametersRestSchemaLocation == null) { reportParametersRestSchemaLocation = getSchemaBaseUrl() + "rest/report" + Constants.REPORT_PARAMETERS_NS_URI_SCHEMA_VERSION + "/report-parameters.xsd"; } return reportParametersRestSchemaLocation; } /** * @return Returns the PreprocessingInformationSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getPreprocessingInformationSchemaLocation() { if (preprocessingInformationSchemaLocation == null) { preprocessingInformationSchemaLocation = getSchemaBaseUrl() + "rest/preprocessing-information" + Constants.PREPROCESSING_INFORMATION_NS_URI_SCHEMA_VERSION + "/preprocessing-information.xsd"; } return preprocessingInformationSchemaLocation; } /** * @return Returns the UpdatePasswordTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getUpdatePasswordTaskParamSchemaLocation() { if (updatePasswordTaskParamSchemaLocation == null) { updatePasswordTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/update-password-task-param.xsd"; } return updatePasswordTaskParamSchemaLocation; } /** * @return Returns the revoke-grant-task-param schema location. * @throws WebserverSystemException In case of an error. */ public static String getRevokeGrantTaskParamSchemaLocation() { if (revokeGrantTaskParamSchemaLocation == null) { revokeGrantTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/revoke-grant-task-param.xsd"; } return revokeGrantTaskParamSchemaLocation; } /** * @return Returns the revoke-grants-task-param schema location. * @throws WebserverSystemException In case of an error. */ public static String getRevokeGrantsTaskParamSchemaLocation() { if (revokeGrantsTaskParamSchemaLocation == null) { revokeGrantsTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/revoke-grants-task-param.xsd"; } return revokeGrantsTaskParamSchemaLocation; } /** * @return Returns the MembersTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getMembersTaskParamSchemaLocation() { if (membersTaskParamSchemaLocation == null) { membersTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/members-task-param.xsd"; } return membersTaskParamSchemaLocation; } /** * @return Returns the AssignPidTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getAssignPidTaskParamSchemaLocation() { if (assignPidTaskParamSchemaLocation == null) { assignPidTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/assign-pid-task-param.xsd"; } return assignPidTaskParamSchemaLocation; } /** * @return Returns the DeletionTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getIdSetTaskParamSchemaLocation() { if (idSetTaskParamSchemaLocation == null) { idSetTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/id-set-task-param.xsd"; } return idSetTaskParamSchemaLocation; } /** * @return Returns the DeleteObjectsTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getDeleteObjectsTaskParamSchemaLocation() { if (deleteObjectsParamSchemaLocation == null) { deleteObjectsParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/delete-objects-task-param.xsd"; } return deleteObjectsParamSchemaLocation; } /** * @return Returns the RelationTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getRelationTaskParamSchemaLocation() { if (relationTaskParamSchemaLocation == null) { relationTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/relation-task-param.xsd"; } return relationTaskParamSchemaLocation; } /** * @return Returns the StatusTaskParamSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getStatusTaskParamSchemaLocation() { if (statusTaskParamSchemaLocation == null) { statusTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/status-task-param.xsd"; } return statusTaskParamSchemaLocation; } /** * @return Returns the schema location of optimitic-locking-task-param schema. * @throws WebserverSystemException * In case of an error. */ public static String getOptimisticLockingTaskParamSchemaLocation() { if (optimiticLockingTaskParamSchemaLocation == null) { optimiticLockingTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/optimistic-locking-task-param.xsd"; } return optimiticLockingTaskParamSchemaLocation; } /** * @return Returns the schema location of reindex-task-param schema. * @throws WebserverSystemException In case of an error. */ public static String getReindexTaskParamSchemaLocation() { if (reindexTaskParamSchemaLocation == null) { reindexTaskParamSchemaLocation = getSchemaBaseUrl() + "rest/common/0.1/reindex-task-param.xsd"; } return reindexTaskParamSchemaLocation; } /** * @return Returns the xmlSchemaSchemaLocation. * @throws WebserverSystemException In case of an error. */ public static String getXmlSchemaSchemaLocation() { if (xmlSchemaSchemaLocation == null) { xmlSchemaSchemaLocation = getSchemaBaseUrl() + "common/0.2/xml-schema.xsd"; } return xmlSchemaSchemaLocation; } /** * @param commonPart The tailing part of a schema location, e.g. role/0.4/role.xsd. * @return Returns the complete schema location for the provided value dependent on UserContext flag isRestAccess. * @throws WebserverSystemException In case of an error. */ private static String getSchemaLocation(final String commonPart) { String result = REST_SCHEMA_LOCATIONS.get(commonPart); if (result == null) { result = getSchemaBaseUrl() + "rest/" + commonPart; REST_SCHEMA_LOCATIONS.put(commonPart, result); } return result; } /** * Replace forbidden characters in xml content with their escape sequence.<br/> This method escapes &, <, and > in * attributes and text content. In attributes, it additionally escapes " and '. * * @param xmlText The xml text. * @return The resulting text with escaped characters. */ public static String escapeForbiddenXmlCharacters(final String xmlText) { String result = xmlText; if (result != null && PATTERN_ESCAPE_NEEDED.matcher(result).find()) { result = PATTERN_AMPERSAND.matcher(result).replaceAll(ESC_AMPERSAND); result = PATTERN_LESS_THAN.matcher(result).replaceAll(ESC_LESS_THAN); result = PATTERN_GREATER_THAN.matcher(result).replaceAll(ESC_GREATER_THAN); result = PATTERN_QUOT.matcher(result).replaceAll(ESC_QUOT); result = PATTERN_APOS.matcher(result).replaceAll(ESC_APOS); } return result; } /** * Replace all escape sequences for forbidden charcters with their readable. * * @param xmlText The xml text with escape sequences. * @return The resulting text with unescaped characters. */ public static String unescapeForbiddenXmlCharacters(final String xmlText) { String result = xmlText; if (result != null && PATTERN_UNESCAPE_NEEDED.matcher(result).find()) { result = PATTERN_ESC_LESS_THAN.matcher(result).replaceAll(LESS_THAN); result = PATTERN_ESC_GREATER_THAN.matcher(result).replaceAll(GREATER_THAN); result = PATTERN_ESC_QUOT.matcher(result).replaceAll(QUOT); result = PATTERN_ESC_APOS.matcher(result).replaceAll(APOS); result = PATTERN_ESC_AMPERSAND.matcher(result).replaceAll(AMPERSAND); } return result; } /** * Throw a uniform escidoc system exception in case of an unexpected exception from the stax parser. * * @param message A handler specific message added to thrown exception message. * @param e The unexcepcted exception. * @throws XmlParserSystemException Thrown in case of an internal system error. */ public static void handleUnexpectedStaxParserException(final String message, final Exception e) throws XmlParserSystemException { final String text = message != null ? message + e.getMessage() : e.getMessage(); throw new XmlParserSystemException(text, e); } /** * FIXME Often this method is not used but get(ESCIDOC_CORE_BASEURL) directly. And/or there is no such method for * every other property!? * * @return Return the configured escidoc baseurl. * @throws WebserverSystemException If an error occurs accessing the escidoc configuration */ public static String getEscidocBaseUrl() { return EscidocConfiguration.getInstance().get(EscidocConfiguration.ESCIDOC_CORE_BASEURL); } /** * Gets an initilized {@code XMLOutputFactory2} instance.<br/> The returned instance is initialized as follows: * <ul> <li>If the provided parameter is set to {@code true}, IS_REPAIRING_NAMESPACES is set to true, i.e. the * created writers will automatically repair the namespaces, see {@code XMLOutputFactory} for details.</li> * <li>For writing escaped attribute values, the {@link StaxAttributeEscapingWriterFactory} is used<./li> <li>For * writing escaped text content, the {@link StaxTextEscapingWriterFactory} is used.</li> </ul> * * @param repairing Flag indicating if the factory shall create namespace repairing writers ({@code true}) or * non repairing writers ({@code false}). * @return Returns the initalized {@code XMLOutputFactory} instance. */ private static XMLOutputFactory getInitilizedXmlOutputFactory(final boolean repairing) { final XMLOutputFactory xmlof = XMLOutputFactory.newInstance(); xmlof.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, repairing); if (repairing) { xmlof.setProperty(XMLOutputFactory2.P_AUTOMATIC_NS_PREFIX, "ext"); } xmlof.setProperty(XMLOutputFactory2.P_ATTR_VALUE_ESCAPER, new StaxAttributeEscapingWriterFactory()); xmlof.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new StaxTextEscapingWriterFactory()); return xmlof; } /** * Creates an {@code XMLStreamWriter} for the provided {@code OutputStream}. * * @param out The {@code OutputStream} to get the writer for. * @return Returns the {@code XMLStreamWriter}. * @throws XMLStreamException Thrown in case of an error during creating the writer. */ public static XMLStreamWriter createXmlStreamWriter(final OutputStream out) throws XMLStreamException { return getInitilizedXmlOutputFactory(false).createXMLStreamWriter(out); } /** * Creates a namespace repairing {@code XMLStreamWriter} for the provided {@code OutputStream}. * * @param out The {@code OutputStream} to get the writer for. * @return Returns the {@code XMLStreamWriter}. * @throws XMLStreamException Thrown in case of an error during creating the writer. */ public static XMLStreamWriter createXmlStreamWriterNamespaceRepairing(final OutputStream out) throws XMLStreamException { return getInitilizedXmlOutputFactory(true).createXMLStreamWriter(out); } /** * Creates an {@code XMLStreamWriter} for the provided {@code OutputStream}. * * @param writer The {@code Writer} to get the writer for. * @return Returns the {@code XMLStreamWriter}. * @throws XMLStreamException Thrown in case of an error during creating the writer. */ public static XMLStreamWriter createXmlStreamWriter(final Writer writer) throws XMLStreamException { return getInitilizedXmlOutputFactory(false).createXMLStreamWriter(writer); } /** * Creates an {@code XMLEventWriter} for the provided {@code Writer}. * * @param writer The {@code Writer} to get the writer for. * @return Returns the {@code XMLEventWriter}. * @throws XMLStreamException Thrown in case of an error during creating the writer. */ public static XMLEventWriter createXmlEventWriter(final Writer writer) throws XMLStreamException { return getInitilizedXmlOutputFactory(false).createXMLEventWriter(writer); } /** * Throws an {@code MissingAttributeValueException}. * * @param element The element in that the attribute is missing. * @param attributeName The name of the missing attribute. * @throws MissingAttributeValueException Throws created exception. */ public static void throwMissingAttributeValueException(final AbstractElement element, final String attributeName) throws MissingAttributeValueException { throw new MissingAttributeValueException(StringUtility.format(ERR_MSG_MISSING_ATTRIBUTE, element.getPath(), attributeName, element.getLocationString())); } /** * Create the content of the DC datastream to store in Fedora. * * @param nsUri nsUri of the md record. Through this URI is the mapping schema selected. * @param mdRecordXml Xml representation of the md record to parse. * @param objID The objid of the Fedora object. A triple is created with this objid. * @return The content of the DC datastream or null if content is empty. * @throws WebserverSystemException If an error occurs. */ public static String createDC(final String nsUri, final String mdRecordXml, final String objID) throws WebserverSystemException { return createDC(nsUri, mdRecordXml, objID, null); } /** * Create the content of the DC datastream to store in Fedora. * * @param nsUri nsUri of the md record. Through this URI is the mapping schema selected. * @param mdRecordXml Xml representation of the md record to parse. * @param objID The objid of the Fedora object. A triple is created with this objid. * @param contentModelID The objid of the content-model. * @return The content of the DC datastream or null if content is empty. * @throws WebserverSystemException If an error occurs. */ public static String createDC(final String nsUri, final String mdRecordXml, final CharSequence objID, final String contentModelID) throws WebserverSystemException { String result = null; Transformer t = null; final String transformerKey = nsUri + ';' + contentModelID; try { t = (Transformer) TRANSFORMER_POOL.borrowObject(transformerKey); if (objID != null && objID.length() > 0) { t.setParameter("ID", objID); } else { t.clearParameters(); } final ByteArrayOutputStream out = new ByteArrayOutputStream(); t.transform(new StreamSource(new ByteArrayInputStream(mdRecordXml.getBytes(CHARACTER_ENCODING))), new StreamResult(out)); result = out.toString(CHARACTER_ENCODING).trim(); } catch (final Exception e) { throw new WebserverSystemException("Mapping of Metadata to DC failed.", e); } finally { try { TRANSFORMER_POOL.returnObject(transformerKey, t); } catch (final Exception e) { if (LOGGER.isWarnEnabled()) { LOGGER.warn("Returning transformer to pool failed."); } if (LOGGER.isDebugEnabled()) { LOGGER.debug("Returning transformer to pool failed.", e); } } } // check if result is empty if (result != null && result.length() == 0) { result = null; } return result; } public static boolean isIdentical(final byte[] xml1, final byte[] xml2) { if (xml1 == null) { return xml2 == null; } if (xml2 == null) { return xml1 == null; } return isIdentical(IOUtils.newStringFromBytes(xml1), IOUtils.newStringFromBytes(xml2)); } public static boolean isIdentical(final String xml1, final String xml2) { if (xml1 == null) { return xml2 == null; } if (xml2 == null) { return xml1 == null; } XMLUnit.setIgnoreComments(true); XMLUnit.setIgnoreAttributeOrder(true); XMLUnit.setIgnoreWhitespace(true); try { final Diff diff = XMLUnit.compareXML(xml1, xml2); return diff.identical(); } catch (SAXException e) { throw new RuntimeException("Error on comparing XML.", e); } catch (IOException e) { throw new RuntimeException("Error on comparing XML.", e); } } }