HardeningSchemaFactory.java
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.xml;
import java.util.function.UnaryOperator;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import javax.xml.validation.ValidatorHandler;
import org.xml.sax.SAXException;
/**
* {@link SchemaFactory} wrapper that rewrites every Source-taking entry point through {@link XmlFactories#harden(Source)} and applies provider-specific
* decoration to every {@link Validator} and {@link ValidatorHandler} that the produced {@link Schema} hands out.
*
* <p>Three layers cooperate:</p>
* <ol>
* <li>{@link HardeningSchemaFactory} rewrites the Source on every {@code newSchema(Source[])} entry point.</li>
* <li>{@link HardeningSchema} applies the provider-specific hardener to every Validator/ValidatorHandler the inner Schema produces (e.g. Xerces re-installs
* its {@code LSResourceResolver} and {@code SecurityManager} since it does not propagate them through Schema).</li>
* <li>{@link HardeningValidator} rewrites the Source on every {@link Validator#validate(Source)} call.</li>
* </ol>
*/
final class HardeningSchemaFactory extends DelegatingSchemaFactory {
private final UnaryOperator<Validator> validatorHardener;
private final UnaryOperator<ValidatorHandler> handlerHardener;
HardeningSchemaFactory(final SchemaFactory delegate) {
this(delegate, UnaryOperator.identity(), UnaryOperator.identity());
}
HardeningSchemaFactory(final SchemaFactory delegate, final UnaryOperator<Validator> validatorHardener,
final UnaryOperator<ValidatorHandler> handlerHardener) {
super(delegate);
this.validatorHardener = validatorHardener;
this.handlerHardener = handlerHardener;
}
@Override
public Schema newSchema() throws SAXException {
return new HardeningSchema(super.newSchema(), validatorHardener, handlerHardener);
}
@Override
public Schema newSchema(final Source[] schemas) throws SAXException {
return new HardeningSchema(super.newSchema(harden(schemas)), validatorHardener, handlerHardener);
}
private static Source[] harden(final Source[] schemas) throws SAXException {
final Source[] hardened = new Source[schemas.length];
try {
for (int i = 0; i < schemas.length; i++) {
hardened[i] = XmlFactories.harden(schemas[i]);
}
} catch (final TransformerConfigurationException e) {
throw new SAXException("Failed to harden schema source", e);
}
return hardened;
}
}