org.jboss.resteasy.plugins.providers.jaxb.SecureUnmarshaller Maven / Gradle / Ivy
package org.jboss.resteasy.plugins.providers.jaxb;
import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.UnmarshallerHandler;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import jakarta.xml.bind.attachment.AttachmentUnmarshaller;
import org.jboss.resteasy.plugins.providers.jaxb.i18n.Messages;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
/**
*
* @author Ron Sigal
*
* @version $Revision: 1.1 $
* Created Feb 1, 2012
*/
public class SecureUnmarshaller implements Unmarshaller {
private static class SAXParserProvider {
private static final Map saxParserProviders = Collections
.synchronizedMap(new WeakHashMap<>());
private final SAXParserFactory[] factories = new SAXParserFactory[8];
private SAXParserProvider() {
//NOOP
}
public static SAXParserProvider getInstance() {
final SecurityManager sm = System.getSecurityManager();
ClassLoader tccl = null;
if (sm == null) {
tccl = Thread.currentThread().getContextClassLoader();
} else {
try {
tccl = AccessController.doPrivileged(new PrivilegedExceptionAction() {
public ClassLoader run() throws Exception {
return Thread.currentThread().getContextClassLoader();
}
});
} catch (PrivilegedActionException e) {
throw new SecurityException(e);
}
}
SAXParserProvider spp;
spp = saxParserProviders.get(tccl);
if (spp == null) {
spp = new SAXParserProvider();
SAXParserProvider s = saxParserProviders.putIfAbsent(tccl, spp);
if (s != null)
spp = s;
}
return spp;
}
public SAXParser getParser(boolean disableExternalEntities, boolean enableSecureProcessingFeature, boolean disableDTDs)
throws ParserConfigurationException, SAXException {
int index = (disableExternalEntities ? 1 : 0) | (enableSecureProcessingFeature ? 1 << 1 : 0)
| (disableDTDs ? 1 << 2 : 0);
SAXParserFactory f = factories[index];
if (f == null) {
// Get the current context class loader
final ClassLoader current = SecurityActions.getContextClassLoader();
try {
// Set the current context class loader to the class loader for this type
SecurityActions.setContextClassLoader();
f = SAXParserFactory.newInstance();
configureParserFactory(f, disableExternalEntities, enableSecureProcessingFeature, disableDTDs);
} finally {
// Reset the current context class loader
SecurityActions.setContextClassLoader(current);
}
factories[index] = f;
}
SAXParser sp = f.newSAXParser();
configParser(sp, disableExternalEntities);
return sp;
}
}
private Unmarshaller delegate;
boolean disableExternalEntities;
boolean enableSecureProcessingFeature;
boolean disableDTDs;
public SecureUnmarshaller(final Unmarshaller delegate, final boolean disableExternalEntities,
final boolean enableSecureProcessingFeature, final boolean disableDTDs) {
this.delegate = delegate;
this.disableExternalEntities = disableExternalEntities;
this.enableSecureProcessingFeature = enableSecureProcessingFeature;
this.disableDTDs = disableDTDs;
}
@SuppressWarnings("unchecked")
public A getAdapter(Class type) {
return delegate.getAdapter(type);
}
public AttachmentUnmarshaller getAttachmentUnmarshaller() {
return delegate.getAttachmentUnmarshaller();
}
public ValidationEventHandler getEventHandler() throws JAXBException {
return delegate.getEventHandler();
}
public Listener getListener() {
return delegate.getListener();
}
public Object getProperty(String name) throws PropertyException {
return delegate.getProperty(name);
}
public Schema getSchema() {
return delegate.getSchema();
}
public UnmarshallerHandler getUnmarshallerHandler() {
return delegate.getUnmarshallerHandler();
}
/**
* @deprecated This method is deprecated as of JAXB 2.0 - please use the new
* {@link #getSchema()} API.
*/
@Deprecated
public boolean isValidating() throws JAXBException {
return delegate.isValidating();
}
@SuppressWarnings("unchecked")
public void setAdapter(XmlAdapter adapter) {
delegate.setAdapter(adapter);
}
@SuppressWarnings("unchecked")
public void setAdapter(Class type, A adapter) {
delegate.setAdapter(adapter);
}
public void setAttachmentUnmarshaller(AttachmentUnmarshaller au) {
delegate.setAttachmentUnmarshaller(au);
}
public void setEventHandler(ValidationEventHandler handler) throws JAXBException {
delegate.setEventHandler(handler);
}
public void setListener(Listener listener) {
delegate.setListener(listener);
}
public void setProperty(String name, Object value) throws PropertyException {
delegate.setProperty(name, value);
}
public void setSchema(Schema schema) {
delegate.setSchema(schema);
}
/**
* @deprecated since JAXB2.0, please see {@link #getSchema()}
*/
@Deprecated
public void setValidating(boolean validating) throws JAXBException {
delegate.setValidating(validating);
}
public Object unmarshal(File f) throws JAXBException {
throw new UnsupportedOperationException(Messages.MESSAGES.unexpectedUse("File"));
}
/**
* Turns off expansion of external entities.
*/
public Object unmarshal(InputStream is) throws JAXBException {
return unmarshal(new InputSource(is));
}
public Object unmarshal(Reader reader) throws JAXBException {
throw new UnsupportedOperationException(Messages.MESSAGES.unexpectedUse("Reader"));
}
public Object unmarshal(URL url) throws JAXBException {
throw new UnsupportedOperationException(Messages.MESSAGES.unexpectedUse("URL"));
}
/**
* Turns off expansion of external entities.
*/
public Object unmarshal(InputSource source) throws JAXBException {
try {
SAXParser sp = SAXParserProvider.getInstance().getParser(disableExternalEntities, enableSecureProcessingFeature,
disableDTDs);
XMLReader xmlReader = sp.getXMLReader();
final SAXSource saxSource = new SAXSource(xmlReader, source);
if (System.getSecurityManager() == null) {
return delegate.unmarshal(saxSource);
} else {
return AccessController.doPrivileged(new PrivilegedExceptionAction