| /* |
| * Copyright (c) 1998, 2020 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| package org.eclipse.persistence.sdo.helper; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import javax.xml.transform.Source; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.sax.SAXSource; |
| import javax.xml.transform.stream.StreamSource; |
| |
| import org.eclipse.persistence.exceptions.SDOException; |
| import org.xml.sax.InputSource; |
| |
| /** |
| * <p><b>Purpose</b>: Allow the contained schema resolver to resolve a schema based on a given namespace and schema location, and |
| * return either the resolved schema source or null, depending on whether the schema had been processed previously. |
| * <p><b>Responsibilities</b>:<ul> |
| * <li> Allow the contained schema resolver to return the referenced Schema given the source schema and namespace and |
| * schemaLocation values from an import or include |
| * <li> Keep track of previously processed schemas to avoid multiple processing and infinite looping |
| * </ul> |
| * |
| * @see org.eclipse.persistence.sdo.helper.SchemaResolver |
| * @see org.eclipse.persistence.sdo.helper.DefaultSchemaResolver |
| */ |
| public class SchemaResolverWrapper { |
| private SchemaResolver schemaResolver; |
| private List<String> systemIdList; |
| |
| /** |
| * This constructor sets schemaResolver to the given value. |
| * |
| * @param resolver the SchemaResolver implementation that will be used to resolve |
| * imports/includes from a give source schema. |
| */ |
| public SchemaResolverWrapper(SchemaResolver resolver) { |
| schemaResolver = resolver; |
| systemIdList = new ArrayList<String>(); |
| } |
| |
| /** |
| * Resolve the Source if only a system ID is specified. |
| */ |
| public Source resolveSchema(Source sourceXSD) { |
| Source resolvedSchemaSource = null; |
| if(sourceXSD instanceof StreamSource) { |
| StreamSource streamSource = (StreamSource) sourceXSD; |
| if(null == streamSource.getInputStream() && null == streamSource.getReader()) { |
| resolvedSchemaSource = resolveSchema(streamSource.getPublicId(), streamSource.getSystemId()); |
| } |
| } else if(sourceXSD instanceof SAXSource) { |
| SAXSource saxSource = (SAXSource) sourceXSD; |
| InputSource inputSource = saxSource.getInputSource(); |
| if(null == inputSource) { |
| resolvedSchemaSource = resolveSchema(saxSource.getSystemId()); |
| } else if(null == inputSource.getByteStream() && null == inputSource.getCharacterStream()){ |
| resolvedSchemaSource = resolveSchema(inputSource.getPublicId(), inputSource.getSystemId()); |
| } |
| } else if(sourceXSD instanceof DOMSource) { |
| DOMSource domSource = (DOMSource) sourceXSD; |
| if(null == domSource.getNode()) { |
| resolvedSchemaSource = resolveSchema(domSource.getSystemId()); |
| } |
| } else if(null != sourceXSD.getSystemId()) { |
| resolvedSchemaSource = resolveSchema(sourceXSD.getSystemId()); |
| } |
| if(resolvedSchemaSource != null) { |
| return resolvedSchemaSource; |
| } |
| return sourceXSD; |
| } |
| |
| |
| /** |
| * Allow the SchemaResolver implementation to attempt to return the referenced Schema based on |
| * given source schema, namespace and schemaLocation values from an import or include. If the |
| * resolver fails, this method will attempt to resolve the schema |
| * |
| * @param sourceXSD The Source object of the source schema |
| * @param namespace The namespace portion of the import/include |
| * @param schemaLocation The schemaLocation portion of the import/include |
| * @return Source for the referenced Schema or null if processing the referenced |
| * schema should be skipped |
| */ |
| public Source resolveSchema(Source sourceXSD, String namespace, String schemaLocation) { |
| // Add sourceXSD's SystemId to the processed schema list to avoid re-processing |
| addSchemaToList(sourceXSD.getSystemId()); |
| |
| Source schemaSource = schemaResolver.resolveSchema(sourceXSD, namespace, schemaLocation); |
| if (schemaSource != null) { |
| String sysId = schemaSource.getSystemId(); |
| if (shouldProcessSchema(sysId)) { |
| return schemaSource; |
| } |
| } |
| return null; |
| } |
| |
| public Source resolveSchema(String systemId) { |
| return resolveSchema(null, systemId); |
| } |
| |
| public Source resolveSchema(String publicId, String systemId) { |
| if(!addSchemaToList(systemId)) { |
| return null; |
| } |
| try { |
| InputSource inputSource = schemaResolver.resolveEntity(publicId, systemId); |
| if(inputSource != null) { |
| return new SAXSource(inputSource); |
| } |
| } catch(Exception ex) { |
| throw SDOException.errorResolvingSchema(ex); |
| } |
| return null; |
| } |
| |
| /** |
| * Indicates if the schema represented by the given systemId (schema URL string) should be processed. |
| * If systemId exists in the list, it should not be processed; otherwise, it will be added to the |
| * list and true returned to indicate processing is required. |
| * |
| * @param systemId a String that conforms to the URI syntax |
| * @return true if systemId is null or does not exist in the list of previously processed schemas, |
| * false otherwise |
| */ |
| private boolean shouldProcessSchema(String systemId) { |
| if (systemId == null) { |
| return true; |
| } |
| return addSchemaToList(systemId); |
| } |
| |
| /** |
| * Add the given SystemId to the list of processed schemas, if it isn't already in the list. |
| * |
| * @param systemId a String that conforms to the URI syntax |
| * @return true if systemId was added to the list (hence the associated schema should be processed), |
| * false if the id was not added to the list or systemId is null. |
| */ |
| private boolean addSchemaToList(String systemId) { |
| if (systemId == null || systemIdList.contains(systemId)) { |
| return false; |
| } |
| systemIdList.add(systemId); |
| return true; |
| } |
| |
| /** |
| * Return the SchemaResolver for this wrapper instance. |
| * |
| * @return |
| */ |
| public SchemaResolver getSchemaResolver() { |
| return schemaResolver; |
| } |
| } |