Merge pull request #239 from botunge/master
Make dependencies truly optionel and clean up android pom.
This commit is contained in:
commit
a2bf374470
|
@ -56,6 +56,12 @@
|
|||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-android</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.cobertura</groupId>
|
||||
<artifactId>cobertura</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
|
@ -74,7 +80,11 @@
|
|||
</dependency>
|
||||
|
||||
<!-- Android does not come with the Servlet API bundled, and MethodUtil
|
||||
requires it -->
|
||||
requires it.
|
||||
|
||||
We provide a dummy implementation of servlet api to reduce size
|
||||
and prevent from rewriting the BaseMethodBinding and friends.
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
|
@ -120,138 +130,134 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<artifactSet>
|
||||
<includes combine.children="append">
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>net.sourceforge.cobertura:cobertura</include>
|
||||
<!--
|
||||
<include>org.apache.commons:*</include>
|
||||
<include>org.apache.httpcomponents:*</include>
|
||||
<include>commons-codec:commons-codec</include>
|
||||
-->
|
||||
<include>javax.servlet:javax.servlet-api</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters combine.children="append">
|
||||
<!-- Make CoverageIgnore annotation available for android. -->
|
||||
<filter>
|
||||
<artifact>net.sourceforge.cobertura:cobertura</artifact>
|
||||
<includes>
|
||||
<include>net/sourceforge/cobertura/CoverageIgnore*</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<!-- Exclude server side stuff, except exceptions which are used clientside -->
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
|
||||
<excludes>
|
||||
<!-- Exclude test stuff which depends on httpservlet -->
|
||||
<exclude>ca/uhn/fhir/util/ITestingUiClientFactory</exclude>
|
||||
<!-- Exclude server side stuff. This could be made nicer if code was divided into shared, server and client -->
|
||||
<!--exclude>ca/uhn/fhir/rest/server/Add*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Apache*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Bundle*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/ETag*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Fifo*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Hard*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/IBundle*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/IDynamic*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Incoming*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/IPaging*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/IServerAdd*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Resource*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Rest*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Search*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/Simple*</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/audit/**</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/interceptor/**</exclude-->
|
||||
<!-- Exclude Phloc validator to make android libs small -->
|
||||
<exclude>ca/uhn/fhir/validation/schematron/SchematronBaseValidator*</exclude>
|
||||
<!-- Exclude Thymeleaf to make android libs small -->
|
||||
<exclude>ca/uhn/fhir/narrative/*Thymeleaf*</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
<executions>
|
||||
<!-- shaded jar -->
|
||||
<execution>
|
||||
<id>normal</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
<id>shaded</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<!-- dstu jar -->
|
||||
<execution>
|
||||
<id>dstu</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<shadedClassifierName>dstu</shadedClassifierName>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<!--
|
||||
<include>commons-codec:commons-codec</include>
|
||||
-->
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<!-- <include>javax.servlet:javax.servlet-api</include>-->
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<!-- <include>org.slf4j:slf4j*</include> -->
|
||||
<!--
|
||||
<include>org.apache.commons:*</include>
|
||||
<include>org.apache.httpcomponents:*</include>
|
||||
-->
|
||||
<include>org.glassfish:javax.json</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<filters>
|
||||
<!-- Exclude server side stuff, except exceptions which are used clientside -->
|
||||
<!--filters>
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</artifact>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
<exclude>ca/uhn/fhir/rest/server/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</filters-->
|
||||
</configuration>
|
||||
</execution>
|
||||
<!-- dstu2 jar -->
|
||||
<execution>
|
||||
<id>dstu2</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>true</createDependencyReducedPom>
|
||||
<createSourcesJar>true</createSourcesJar>
|
||||
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||
<shadedClassifierName>dstu2</shadedClassifierName>
|
||||
<artifactSet>
|
||||
<includes>
|
||||
<!--
|
||||
<include>commons-codec:commons-codec</include>
|
||||
-->
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
|
||||
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</include>
|
||||
<include>org.glassfish:javax.json</include>
|
||||
<include>org.codehaus.woodstox:woodstox-core-asl</include>
|
||||
<include>javax.xml.stream:stax-api</include>
|
||||
<!-- <include>javax.servlet:javax.servlet-api</include>-->
|
||||
<include>org.codehaus.woodstox:stax2-api</include>
|
||||
<!--
|
||||
<include>org.apache.commons:*</include>
|
||||
<include>org.apache.httpcomponents:*</include>
|
||||
-->
|
||||
<include>org.glassfish:javax.json</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>javax.xml.stream</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.xml.stream</shadedPattern>
|
||||
</relocation>
|
||||
<relocation>
|
||||
<pattern>javax.json</pattern>
|
||||
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
|
||||
</relocation>
|
||||
</relocations>
|
||||
<!-- Exclude server side stuff, except exceptions which are used clientside -->
|
||||
<!--filters>
|
||||
<filter>
|
||||
<artifact>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</artifact>
|
||||
<excludes>
|
||||
<exclude>ca/uhn/fhir/rest/server/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters-->
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
|
|
@ -132,6 +132,20 @@
|
|||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
|
|
|
@ -20,49 +20,37 @@ package ca.uhn.fhir.util;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import ca.uhn.fhir.util.reflection.IBeanUtils;
|
||||
|
||||
public class BeanUtils {
|
||||
|
||||
public static Method findAccessor(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName) throws NoSuchFieldException {
|
||||
BeanInfo info;
|
||||
try {
|
||||
info = Introspector.getBeanInfo(theClassToIntrospect);
|
||||
} catch (IntrospectionException e) {
|
||||
throw new NoSuchFieldException(e.getMessage());
|
||||
}
|
||||
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
|
||||
if (thePropertyName.equals(pd.getName())) {
|
||||
if (theTargetReturnType.isAssignableFrom(pd.getPropertyType())) {
|
||||
return pd.getReadMethod();
|
||||
}else {
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has an accessor for field " + thePropertyName + " but it does not return type " + theTargetReturnType);
|
||||
private static IBeanUtils beanUtils;
|
||||
|
||||
private static IBeanUtils getBeanUtils() {
|
||||
if (beanUtils == null) {
|
||||
try {
|
||||
beanUtils = (IBeanUtils) Class.forName("ca.uhn.fhir.util.reflection.JavaBeansBeanUtil").newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
try {
|
||||
beanUtils = (IBeanUtils) Class.forName("ca.uhn.fhir.util.reflection.JavaReflectBeanUtil")
|
||||
.newInstance();
|
||||
} catch (ReflectiveOperationException e1) {
|
||||
throw new RuntimeException("Could not resolve BeanUtil implementation");
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has no accessor for field " + thePropertyName);
|
||||
return beanUtils;
|
||||
}
|
||||
|
||||
public static Method findMutator(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName) throws NoSuchFieldException {
|
||||
BeanInfo info;
|
||||
try {
|
||||
info = Introspector.getBeanInfo(theClassToIntrospect);
|
||||
} catch (IntrospectionException e) {
|
||||
throw new NoSuchFieldException(e.getMessage());
|
||||
}
|
||||
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
|
||||
if (thePropertyName.equals(pd.getName())) {
|
||||
if (theTargetReturnType.isAssignableFrom(pd.getPropertyType())) {
|
||||
return pd.getWriteMethod();
|
||||
}else {
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has an mutator for field " + thePropertyName + " but it does not return type " + theTargetReturnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has no mutator for field " + thePropertyName);
|
||||
public static Method findAccessor(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName)
|
||||
throws NoSuchFieldException {
|
||||
return getBeanUtils().findAccessor(theClassToIntrospect, theTargetReturnType, thePropertyName);
|
||||
}
|
||||
|
||||
public static Method findMutator(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName)
|
||||
throws NoSuchFieldException {
|
||||
return getBeanUtils().findMutator(theClassToIntrospect, theTargetReturnType, thePropertyName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
|
@ -32,4 +34,16 @@ public class ObjectUtil {
|
|||
return object1.equals(object2);
|
||||
}
|
||||
|
||||
public static <T> T requireNonNull(T obj, String message) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException(message);
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static void requireNotEmpty(String str, String message) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,20 +21,15 @@ package ca.uhn.fhir.util;
|
|||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import javax.xml.stream.FactoryConfigurationError;
|
||||
import javax.xml.stream.XMLEventReader;
|
||||
|
@ -52,18 +47,15 @@ import org.codehaus.stax2.io.EscapingWriterFactory;
|
|||
import com.ctc.wstx.api.WstxInputProperties;
|
||||
import com.ctc.wstx.stax.WstxOutputFactory;
|
||||
|
||||
import ca.uhn.fhir.util.jar.DependencyLogFactory;
|
||||
import ca.uhn.fhir.util.jar.IDependencyLog;
|
||||
|
||||
/**
|
||||
* Utility methods for working with the StAX API.
|
||||
*
|
||||
* This class contains code adapted from the Apache Axiom project.
|
||||
*/
|
||||
public class XmlUtil {
|
||||
private static final Attributes.Name BUNDLE_SYMBOLIC_NAME = new Attributes.Name("Bundle-SymbolicName");
|
||||
private static final Attributes.Name BUNDLE_VENDOR = new Attributes.Name("Bundle-Vendor");
|
||||
private static final Attributes.Name BUNDLE_VERSION = new Attributes.Name("Bundle-Version");
|
||||
private static final Attributes.Name IMPLEMENTATION_TITLE = new Attributes.Name("Implementation-Title");
|
||||
private static final Attributes.Name IMPLEMENTATION_VENDOR = new Attributes.Name("Implementation-Vendor");
|
||||
private static final Attributes.Name IMPLEMENTATION_VERSION = new Attributes.Name("Implementation-Version");
|
||||
private static volatile boolean ourHaveLoggedStaxImplementation;
|
||||
private static volatile XMLInputFactory ourInputFactory;
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class);
|
||||
|
@ -1645,73 +1637,12 @@ public class XmlUtil {
|
|||
return outputFactory;
|
||||
}
|
||||
|
||||
private static URL getRootUrlForClass(Class<?> cls) {
|
||||
ClassLoader classLoader = cls.getClassLoader();
|
||||
String resource = cls.getName().replace('.', '/') + ".class";
|
||||
if (classLoader == null) {
|
||||
// A null class loader means the bootstrap class loader. In this case we use the
|
||||
// system class loader. This is safe since we can assume that the system class
|
||||
// loader uses parent first as delegation policy.
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
URL url = classLoader.getResource(resource);
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
String file = url.getFile();
|
||||
if (file.endsWith(resource)) {
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), url.getPort(), file.substring(0, file.length() - resource.length()));
|
||||
} catch (MalformedURLException ex) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void logStaxImplementation(Class<?> theClass) {
|
||||
try {
|
||||
URL rootUrl = getRootUrlForClass(theClass);
|
||||
if (rootUrl == null) {
|
||||
ourLog.info("Unable to determine location of StAX implementation containing class");
|
||||
} else {
|
||||
Manifest manifest;
|
||||
URL metaInfUrl = new URL(rootUrl, "META-INF/MANIFEST.MF");
|
||||
InputStream is = metaInfUrl.openStream();
|
||||
try {
|
||||
manifest = new Manifest(is);
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
Attributes attrs = manifest.getMainAttributes();
|
||||
String title = attrs.getValue(IMPLEMENTATION_TITLE);
|
||||
String symbolicName = attrs.getValue(BUNDLE_SYMBOLIC_NAME);
|
||||
if (symbolicName != null) {
|
||||
int i = symbolicName.indexOf(';');
|
||||
if (i != -1) {
|
||||
symbolicName = symbolicName.substring(0, i);
|
||||
}
|
||||
}
|
||||
String vendor = attrs.getValue(IMPLEMENTATION_VENDOR);
|
||||
if (vendor == null) {
|
||||
vendor = attrs.getValue(BUNDLE_VENDOR);
|
||||
}
|
||||
String version = attrs.getValue(IMPLEMENTATION_VERSION);
|
||||
if (version == null) {
|
||||
version = attrs.getValue(BUNDLE_VERSION);
|
||||
}
|
||||
if (ourLog.isDebugEnabled()) {
|
||||
ourLog.debug("FHIR XML procesing will use StAX implementation at {}\n Title: {}\n Symbolic name: {}\n Vendor: {}\n Version: {}", new Object[] { rootUrl, title, symbolicName, vendor, version } );
|
||||
} else {
|
||||
ourLog.info("FHIR XML procesing will use StAX implementation '{}' version '{}'", title, version);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
ourLog.info("Unable to determine StAX implementation: " + e.getMessage());
|
||||
} finally {
|
||||
ourHaveLoggedStaxImplementation = true;
|
||||
IDependencyLog logger = DependencyLogFactory.createJarLogger();
|
||||
if (logger != null) {
|
||||
logger.logStaxImplementation(theClass);
|
||||
}
|
||||
ourHaveLoggedStaxImplementation = true;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws FactoryConfigurationError, XMLStreamException {
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package ca.uhn.fhir.util.jar;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public class DependencyLogFactory {
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(DependencyLogFactory.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static IDependencyLog createJarLogger() {
|
||||
try {
|
||||
Class<IDependencyLog> clas = (Class<IDependencyLog>) Class.forName("ca.uhn.fhir.util.jar.DependencyLogImpl");
|
||||
return clas.newInstance();
|
||||
} catch (ReflectiveOperationException e) {
|
||||
ourLog.info("Could not log dependency.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package ca.uhn.fhir.util.jar;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import ca.uhn.fhir.util.XmlUtil;
|
||||
|
||||
public class DependencyLogImpl implements IDependencyLog {
|
||||
private static final Attributes.Name BUNDLE_SYMBOLIC_NAME = new Attributes.Name("Bundle-SymbolicName");
|
||||
private static final Attributes.Name BUNDLE_VENDOR = new Attributes.Name("Bundle-Vendor");
|
||||
private static final Attributes.Name BUNDLE_VERSION = new Attributes.Name("Bundle-Version");
|
||||
private static final Attributes.Name IMPLEMENTATION_TITLE = new Attributes.Name("Implementation-Title");
|
||||
private static final Attributes.Name IMPLEMENTATION_VENDOR = new Attributes.Name("Implementation-Vendor");
|
||||
private static final Attributes.Name IMPLEMENTATION_VERSION = new Attributes.Name("Implementation-Version");
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class);
|
||||
|
||||
@Override
|
||||
public void logStaxImplementation(Class<?> theClass) {
|
||||
try {
|
||||
URL rootUrl = getRootUrlForClass(theClass);
|
||||
if (rootUrl == null) {
|
||||
ourLog.info("Unable to determine location of StAX implementation containing class");
|
||||
} else {
|
||||
Manifest manifest;
|
||||
URL metaInfUrl = new URL(rootUrl, "META-INF/MANIFEST.MF");
|
||||
InputStream is = metaInfUrl.openStream();
|
||||
try {
|
||||
manifest = new Manifest(is);
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
Attributes attrs = manifest.getMainAttributes();
|
||||
String title = attrs.getValue(IMPLEMENTATION_TITLE);
|
||||
String symbolicName = attrs.getValue(BUNDLE_SYMBOLIC_NAME);
|
||||
if (symbolicName != null) {
|
||||
int i = symbolicName.indexOf(';');
|
||||
if (i != -1) {
|
||||
symbolicName = symbolicName.substring(0, i);
|
||||
}
|
||||
}
|
||||
String vendor = attrs.getValue(IMPLEMENTATION_VENDOR);
|
||||
if (vendor == null) {
|
||||
vendor = attrs.getValue(BUNDLE_VENDOR);
|
||||
}
|
||||
String version = attrs.getValue(IMPLEMENTATION_VERSION);
|
||||
if (version == null) {
|
||||
version = attrs.getValue(BUNDLE_VERSION);
|
||||
}
|
||||
if (ourLog.isDebugEnabled()) {
|
||||
ourLog.debug("FHIR XML procesing will use StAX implementation at {}\n Title: {}\n Symbolic name: {}\n Vendor: {}\n Version: {}", new Object[] { rootUrl, title, symbolicName, vendor, version } );
|
||||
} else {
|
||||
ourLog.info("FHIR XML procesing will use StAX implementation '{}' version '{}'", title, version);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
ourLog.info("Unable to determine StAX implementation: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static URL getRootUrlForClass(Class<?> cls) {
|
||||
ClassLoader classLoader = cls.getClassLoader();
|
||||
String resource = cls.getName().replace('.', '/') + ".class";
|
||||
if (classLoader == null) {
|
||||
// A null class loader means the bootstrap class loader. In this case we use the
|
||||
// system class loader. This is safe since we can assume that the system class
|
||||
// loader uses parent first as delegation policy.
|
||||
classLoader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
URL url = classLoader.getResource(resource);
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
String file = url.getFile();
|
||||
if (file.endsWith(resource)) {
|
||||
try {
|
||||
return new URL(url.getProtocol(), url.getHost(), url.getPort(), file.substring(0, file.length() - resource.length()));
|
||||
} catch (MalformedURLException ex) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ca.uhn.fhir.util.jar;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IDependencyLog {
|
||||
|
||||
void logStaxImplementation(Class<?> theClass);
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ca.uhn.fhir.util.reflection;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public interface IBeanUtils {
|
||||
Method findAccessor(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName)
|
||||
throws NoSuchFieldException;
|
||||
|
||||
Method findMutator(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName)
|
||||
throws NoSuchFieldException;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package ca.uhn.fhir.util.reflection;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class JavaBeansBeanUtil implements IBeanUtils {
|
||||
|
||||
@Override
|
||||
public Method findAccessor(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName) throws NoSuchFieldException {
|
||||
BeanInfo info;
|
||||
try {
|
||||
info = Introspector.getBeanInfo(theClassToIntrospect);
|
||||
} catch (IntrospectionException e) {
|
||||
throw new NoSuchFieldException(e.getMessage());
|
||||
}
|
||||
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
|
||||
if (thePropertyName.equals(pd.getName())) {
|
||||
if (theTargetReturnType.isAssignableFrom(pd.getPropertyType())) {
|
||||
return pd.getReadMethod();
|
||||
}else {
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has an accessor for field " + thePropertyName + " but it does not return type " + theTargetReturnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has no accessor for field " + thePropertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method findMutator(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName) throws NoSuchFieldException {
|
||||
BeanInfo info;
|
||||
try {
|
||||
info = Introspector.getBeanInfo(theClassToIntrospect);
|
||||
} catch (IntrospectionException e) {
|
||||
throw new NoSuchFieldException(e.getMessage());
|
||||
}
|
||||
for (PropertyDescriptor pd : info.getPropertyDescriptors()) {
|
||||
if (thePropertyName.equals(pd.getName())) {
|
||||
if (theTargetReturnType.isAssignableFrom(pd.getPropertyType())) {
|
||||
return pd.getWriteMethod();
|
||||
}else {
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has an mutator for field " + thePropertyName + " but it does not return type " + theTargetReturnType);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has no mutator for field " + thePropertyName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package ca.uhn.fhir.util.reflection;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.lang3.text.WordUtils;
|
||||
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2015 University Health Network
|
||||
* %%
|
||||
* Licensed 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
|
||||
*
|
||||
* http://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.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
public class JavaReflectBeanUtil implements IBeanUtils {
|
||||
|
||||
@Override
|
||||
public Method findAccessor(Class<?> theClassToIntrospect, Class<?> theTargetReturnType, String thePropertyName)
|
||||
throws NoSuchFieldException {
|
||||
String methodName = "get" + WordUtils.capitalize(thePropertyName);
|
||||
try {
|
||||
Method method = theClassToIntrospect.getMethod(methodName);
|
||||
if (theTargetReturnType.isAssignableFrom(method.getReturnType())) {
|
||||
return method;
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
// fall through
|
||||
} catch (SecurityException e) {
|
||||
throw new ConfigurationException("Failed to scan class '" + theClassToIntrospect + "' because of a security exception", e);
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has no accessor for field " + thePropertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Method findMutator(Class<?> theClassToIntrospect, Class<?> theTargetArgumentType, String thePropertyName)
|
||||
throws NoSuchFieldException {
|
||||
String methodName = "set" + WordUtils.capitalize(thePropertyName);
|
||||
try {
|
||||
return theClassToIntrospect.getMethod(methodName, theTargetArgumentType);
|
||||
} catch (NoSuchMethodException e) {
|
||||
//fall through
|
||||
} catch (SecurityException e) {
|
||||
throw new ConfigurationException("Failed to scan class '" + theClassToIntrospect + "' because of a security exception", e);
|
||||
}
|
||||
throw new NoSuchFieldException(theClassToIntrospect + " has an mutator for field " + thePropertyName + " but it does not return type " + theTargetArgumentType);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -23,9 +23,8 @@ package ca.uhn.fhir.validation;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.thymeleaf.util.Validate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
abstract class BaseValidationContext<T> implements IValidationContext<T> {
|
||||
|
||||
|
@ -38,7 +37,7 @@ abstract class BaseValidationContext<T> implements IValidationContext<T> {
|
|||
|
||||
@Override
|
||||
public void addValidationMessage(SingleValidationMessage theMessage) {
|
||||
Validate.notNull(theMessage, "theMessage must not be null");
|
||||
ObjectUtil.requireNonNull(theMessage, "theMessage must not be null");
|
||||
myMessages.add(theMessage);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ import ca.uhn.fhir.context.FhirContext;
|
|||
import ca.uhn.fhir.model.api.Bundle;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.util.OperationOutcomeUtil;
|
||||
import ca.uhn.fhir.validation.schematron.SchematronProvider;
|
||||
|
||||
/**
|
||||
* Resource validator, which checks resources for compliance against various validation schemes (schemas, schematrons, profiles, etc.)
|
||||
|
@ -49,9 +50,6 @@ public class FhirValidator {
|
|||
|
||||
private static final String I18N_KEY_NO_PHLOC_ERROR = FhirValidator.class.getName() + ".noPhlocError";
|
||||
|
||||
private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName() + ".noPhlocWarningOnStartup";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class);
|
||||
|
||||
private static volatile Boolean ourPhlocPresentOnClasspath;
|
||||
private final FhirContext myContext;
|
||||
private List<IValidatorModule> myValidators = new ArrayList<IValidatorModule>();
|
||||
|
@ -63,13 +61,7 @@ public class FhirValidator {
|
|||
myContext = theFhirContext;
|
||||
|
||||
if (ourPhlocPresentOnClasspath == null) {
|
||||
try {
|
||||
Class.forName("com.phloc.schematron.ISchematronResource");
|
||||
ourPhlocPresentOnClasspath = true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING));
|
||||
ourPhlocPresentOnClasspath = false;
|
||||
}
|
||||
ourPhlocPresentOnClasspath = SchematronProvider.isScematronAvailable(theFhirContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +102,12 @@ public class FhirValidator {
|
|||
* Should the validator validate the resource against the base schema (the schema provided with the FHIR distribution itself)
|
||||
*/
|
||||
public synchronized boolean isValidateAgainstStandardSchematron() {
|
||||
return haveValidatorOfType(SchematronBaseValidator.class);
|
||||
if (!ourPhlocPresentOnClasspath) {
|
||||
return false; // No need to ask since we dont have Phloc. Also Class.forname will complain
|
||||
// about missing phloc import.
|
||||
}
|
||||
Class<? extends IValidatorModule> cls = SchematronProvider.getSchematronValidatorClass();
|
||||
return haveValidatorOfType(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +144,9 @@ public class FhirValidator {
|
|||
if (theValidateAgainstStandardSchematron && !ourPhlocPresentOnClasspath) {
|
||||
throw new IllegalArgumentException(myContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_ERROR));
|
||||
}
|
||||
addOrRemoveValidator(theValidateAgainstStandardSchematron, SchematronBaseValidator.class, new SchematronBaseValidator(myContext));
|
||||
Class<? extends IValidatorModule> cls = SchematronProvider.getSchematronValidatorClass();
|
||||
IValidatorModule instance = SchematronProvider.getSchematronValidatorInstance(myContext);
|
||||
addOrRemoveValidator(theValidateAgainstStandardSchematron, cls, instance);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,9 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
|
||||
class SchemaBaseValidator implements IValidatorModule {
|
||||
public class SchemaBaseValidator implements IValidatorModule {
|
||||
public static final String RESOURCES_JAR_NOTE = "Note that as of HAPI FHIR 1.2, DSTU2 validation files are kept in a separate JAR (hapi-fhir-validation-resources-XXX.jar) which must be added to your classpath. See the HAPI FHIR download page for more information.";
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SchemaBaseValidator.class);
|
||||
private static final Set<String> SCHEMA_NAMES;
|
||||
|
||||
|
@ -129,7 +131,7 @@ class SchemaBaseValidator implements IValidatorModule {
|
|||
ourLog.debug("Going to load resource: {}", pathToBase);
|
||||
InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase);
|
||||
if (baseIs == null) {
|
||||
throw new InternalErrorException("Schema not found. " + SchematronBaseValidator.RESOURCES_JAR_NOTE);
|
||||
throw new InternalErrorException("Schema not found. " + RESOURCES_JAR_NOTE);
|
||||
}
|
||||
baseIs = new BOMInputStream(baseIs, false);
|
||||
InputStreamReader baseReader = new InputStreamReader(baseIs, Charset.forName("UTF-8"));
|
||||
|
|
|
@ -21,7 +21,6 @@ package ca.uhn.fhir.validation;
|
|||
*/
|
||||
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.thymeleaf.util.Validate;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.Bundle;
|
||||
|
@ -29,8 +28,9 @@ import ca.uhn.fhir.model.api.IResource;
|
|||
import ca.uhn.fhir.rest.method.MethodUtil;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.util.ObjectUtil;
|
||||
|
||||
class ValidationContext<T> extends BaseValidationContext<T> implements IValidationContext<T> {
|
||||
public class ValidationContext<T> extends BaseValidationContext<T> implements IValidationContext<T> {
|
||||
|
||||
private final IEncoder myEncoder;
|
||||
private final T myResource;
|
||||
|
@ -136,8 +136,8 @@ class ValidationContext<T> extends BaseValidationContext<T> implements IValidati
|
|||
}
|
||||
|
||||
public static IValidationContext<IBaseResource> forText(final FhirContext theContext, final String theResourceBody) {
|
||||
Validate.notNull(theContext, "theContext can not be null");
|
||||
Validate.notEmpty(theResourceBody, "theResourceBody can not be null or empty");
|
||||
ObjectUtil.requireNonNull(theContext, "theContext can not be null");
|
||||
ObjectUtil.requireNotEmpty(theResourceBody, "theResourceBody can not be null or empty");
|
||||
return new BaseValidationContext<IBaseResource>(theContext) {
|
||||
|
||||
private EncodingEnum myEncoding;
|
||||
|
@ -169,5 +169,4 @@ class ValidationContext<T> extends BaseValidationContext<T> implements IValidati
|
|||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package ca.uhn.fhir.validation;
|
||||
package ca.uhn.fhir.validation.schematron;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
|
@ -37,6 +37,13 @@ import ca.uhn.fhir.model.api.Bundle;
|
|||
import ca.uhn.fhir.model.api.BundleEntry;
|
||||
import ca.uhn.fhir.rest.server.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.IValidationContext;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
import ca.uhn.fhir.validation.ResultSeverityEnum;
|
||||
import ca.uhn.fhir.validation.SchemaBaseValidator;
|
||||
import ca.uhn.fhir.validation.SingleValidationMessage;
|
||||
import ca.uhn.fhir.validation.ValidationContext;
|
||||
|
||||
import com.phloc.commons.error.IResourceError;
|
||||
import com.phloc.commons.error.IResourceErrorGroup;
|
||||
|
@ -44,13 +51,16 @@ import com.phloc.schematron.ISchematronResource;
|
|||
import com.phloc.schematron.SchematronHelper;
|
||||
import com.phloc.schematron.xslt.SchematronResourceSCH;
|
||||
|
||||
/**
|
||||
* This class is only used using reflection from {@link SchematronProvider} in order
|
||||
* to be truly optional.
|
||||
*/
|
||||
public class SchematronBaseValidator implements IValidatorModule {
|
||||
|
||||
static final String RESOURCES_JAR_NOTE = "Note that as of HAPI FHIR 1.2, DSTU2 validation files are kept in a separate JAR (hapi-fhir-validation-resources-XXX.jar) which must be added to your classpath. See the HAPI FHIR download page for more information.";
|
||||
private Map<Class<? extends IBaseResource>, ISchematronResource> myClassToSchematron = new HashMap<Class<? extends IBaseResource>, ISchematronResource>();
|
||||
private FhirContext myCtx;
|
||||
|
||||
SchematronBaseValidator(FhirContext theContext) {
|
||||
public SchematronBaseValidator(FhirContext theContext) {
|
||||
myCtx = theContext;
|
||||
}
|
||||
|
||||
|
@ -126,7 +136,7 @@ public class SchematronBaseValidator implements IValidatorModule {
|
|||
InputStream baseIs = FhirValidator.class.getResourceAsStream(pathToBase);
|
||||
try {
|
||||
if (baseIs == null) {
|
||||
throw new InternalErrorException("Failed to load schematron for resource '" + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName() + "'. " + RESOURCES_JAR_NOTE);
|
||||
throw new InternalErrorException("Failed to load schematron for resource '" + theCtx.getFhirContext().getResourceDefinition(theCtx.getResource()).getBaseDefinition().getName() + "'. " + SchemaBaseValidator.RESOURCES_JAR_NOTE);
|
||||
}
|
||||
} finally {
|
||||
IOUtils.closeQuietly(baseIs);
|
|
@ -0,0 +1,42 @@
|
|||
package ca.uhn.fhir.validation.schematron;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.IValidatorModule;
|
||||
|
||||
public class SchematronProvider {
|
||||
|
||||
|
||||
private static final String I18N_KEY_NO_PHLOC_WARNING = FhirValidator.class.getName() + ".noPhlocWarningOnStartup";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirValidator.class);
|
||||
|
||||
public static boolean isScematronAvailable(FhirContext theFhirContext) {
|
||||
try {
|
||||
Class.forName("com.phloc.schematron.ISchematronResource");
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
ourLog.info(theFhirContext.getLocalizer().getMessage(I18N_KEY_NO_PHLOC_WARNING));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<? extends IValidatorModule> getSchematronValidatorClass() {
|
||||
try {
|
||||
return (Class<? extends IValidatorModule>) Class.forName("ca.uhn.fhir.validation.schematron.SchematronBaseValidator");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException("Cannot resolve schematron validator ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static IValidatorModule getSchematronValidatorInstance(FhirContext myContext) {
|
||||
try {
|
||||
Class<? extends IValidatorModule> cls = getSchematronValidatorClass();
|
||||
Constructor<? extends IValidatorModule> constructor = cls.getConstructor(FhirContext.class);
|
||||
return constructor.newInstance(myContext);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new IllegalStateException("Cannot construct schematron validator ", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.util.reflection.IBeanUtils;
|
||||
import ca.uhn.fhir.util.reflection.JavaBeansBeanUtil;
|
||||
import ca.uhn.fhir.util.reflection.JavaReflectBeanUtil;
|
||||
|
||||
public class BeanUtilTest {
|
||||
|
||||
@Test
|
||||
public void testFindAccessor() throws Exception {
|
||||
JavaBeansBeanUtil javaBeansBeanUtil = new JavaBeansBeanUtil();
|
||||
testBeanUtilsAccessor(javaBeansBeanUtil);
|
||||
JavaReflectBeanUtil javaReflectBeanUtil = new JavaReflectBeanUtil();
|
||||
testBeanUtilsAccessor(javaReflectBeanUtil);
|
||||
assertNotNull(BeanUtils.findAccessor(BeanUtilTestClass.class, String.class, "field"));
|
||||
Method jbMGet = javaBeansBeanUtil.findAccessor(BeanUtilTestClass.class, String.class, "field");
|
||||
Method jrMGet = javaReflectBeanUtil.findAccessor(BeanUtilTestClass.class, String.class, "field");
|
||||
assertNotNull(jbMGet);
|
||||
assertNotNull(jrMGet);
|
||||
assertEquals(jbMGet, jrMGet);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMutator() throws Exception {
|
||||
JavaBeansBeanUtil javaBeansBeanUtil = new JavaBeansBeanUtil();
|
||||
testBeanUtilsMutator(javaBeansBeanUtil);
|
||||
JavaReflectBeanUtil javaReflectBeanUtil = new JavaReflectBeanUtil();
|
||||
testBeanUtilsMutator(javaReflectBeanUtil);
|
||||
assertNotNull(BeanUtils.findMutator(BeanUtilTestClass.class, String.class, "field"));
|
||||
Method jbMSet = javaBeansBeanUtil.findMutator(BeanUtilTestClass.class, String.class, "field");
|
||||
Method jrMSet = javaReflectBeanUtil.findMutator(BeanUtilTestClass.class, String.class, "field");
|
||||
assertNotNull(jbMSet);
|
||||
assertNotNull(jrMSet);
|
||||
assertEquals(jbMSet, jrMSet);
|
||||
}
|
||||
|
||||
private void testBeanUtilsAccessor(IBeanUtils util) throws Exception {
|
||||
assertNotNull(util.findAccessor(BeanUtilTestClass.class, String.class, "field"));
|
||||
try {
|
||||
assertNull(util.findAccessor(BeanUtilTestClass.class, String.class, "fieldX"));
|
||||
fail("Field is not in class");
|
||||
} catch (NoSuchFieldException e) { }
|
||||
try {
|
||||
assertNull(util.findAccessor(BeanUtilTestClass.class, Integer.class, "field"));
|
||||
fail("Field is in class, but we expect Integer as return type");
|
||||
} catch (NoSuchFieldException e) { }
|
||||
}
|
||||
|
||||
private void testBeanUtilsMutator(IBeanUtils util) throws Exception {
|
||||
assertNotNull(util.findMutator(BeanUtilTestClass.class, String.class, "field"));
|
||||
try {
|
||||
assertNull(util.findMutator(BeanUtilTestClass.class, String.class, "fieldX"));
|
||||
fail("Field is not in class");
|
||||
} catch (NoSuchFieldException e) { }
|
||||
try {
|
||||
assertNull(util.findMutator(BeanUtilTestClass.class, Integer.class, "field"));
|
||||
fail("Field is in class, but we expect Integer as parameter type");
|
||||
} catch (NoSuchFieldException e) { }
|
||||
}
|
||||
|
||||
public static class BeanUtilTestClass {
|
||||
private String myField;
|
||||
|
||||
public String getField() {
|
||||
return myField;
|
||||
}
|
||||
|
||||
public void setField(String value) {
|
||||
this.myField = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.util.jar.DependencyLogFactory;
|
||||
import ca.uhn.fhir.util.jar.IDependencyLog;
|
||||
|
||||
public class DependencyLogUtilTest {
|
||||
|
||||
@Test
|
||||
public void testDependencyLogFactory() {
|
||||
IDependencyLog logger = DependencyLogFactory.createJarLogger();
|
||||
assertNotNull(logger);
|
||||
logger.logStaxImplementation(DependencyLogUtilTest.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package ca.uhn.fhir.util;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ObjectUtilTest {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
String a = new String("a");
|
||||
String b = new String("b");
|
||||
assertFalse(ObjectUtil.equals(b, a));
|
||||
assertFalse(ObjectUtil.equals(a, b));
|
||||
assertFalse(ObjectUtil.equals(a, null));
|
||||
assertFalse(ObjectUtil.equals(null, a));
|
||||
assertTrue(ObjectUtil.equals(null, null));
|
||||
assertTrue(ObjectUtil.equals(a, a));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireNonNull() {
|
||||
String message = "Must not be null in test";
|
||||
try {
|
||||
ObjectUtil.requireNonNull(null, message);
|
||||
fail("should not get here.");
|
||||
} catch (NullPointerException e) {
|
||||
assertEquals(message, e.getMessage());
|
||||
}
|
||||
assertNotNull(ObjectUtil.requireNonNull("some string", message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequireNotEmpty() {
|
||||
//All these are empty, null or whitespace strings.
|
||||
testRequireNotEmptyErrorScenario(null);
|
||||
testRequireNotEmptyErrorScenario("");
|
||||
testRequireNotEmptyErrorScenario(" ");
|
||||
testRequireNotEmptyErrorScenario(" ");
|
||||
//All these are non empty, some non whitespace char in the string.
|
||||
ObjectUtil.requireNotEmpty("abc ", "");
|
||||
ObjectUtil.requireNotEmpty(" abc ", "");
|
||||
ObjectUtil.requireNotEmpty(" abc", "");
|
||||
|
||||
}
|
||||
|
||||
private void testRequireNotEmptyErrorScenario(String string) {
|
||||
String message = "must not be empty in test";
|
||||
try {
|
||||
ObjectUtil.requireNotEmpty(string, message);
|
||||
fail("should not get here.");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertEquals(message, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue