Make dependencies truly optionel + clean up / minimize android build

both Phloc and Schematron was not truly optionel since they was referred
from different files. So the references has been moved to a factory and
ObjectUtil extended for some of the missing methods, where Schematron
was used. Android pom file is cleaned so that all artifcates are build
using the same base configuration and then schematron, phloc and some
server components have been removed from artifact to minimize android
artifacts.
This commit is contained in:
Thomas Andersen 2015-10-04 21:05:30 +02:00
parent 9560ab8dd2
commit f4f57fd480
7 changed files with 174 additions and 152 deletions

View File

@ -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>
@ -77,7 +83,7 @@
<!-- Android does not come with the Servlet API bundled, and MethodUtil
requires it.
We provide a dummy implementation of servlet api to reduce size.
We provide a dummy implementation of servlet api to reduce size
and prevent from rewriting the BaseMethodBinding and friends.
-->
<!-- dependency>
@ -125,25 +131,25 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>normal</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<createSourcesJar>true</createSourcesJar>
<shadedArtifactAttached>true</shadedArtifactAttached>
<artifactSet>
<includes>
<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>
@ -156,21 +162,56 @@
<shadedPattern>ca.uhn.fhir.repackage.javax.json</shadedPattern>
</relocation>
</relocations>
<filters>
<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>ca/uhn/fhir/rest/server/**</exclude>
<exclude>**/*.java</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>
<includes>
<include>ca/uhn/fhir/rest/server/exceptions/**</include>
</includes>
</filter>
</filters>
</configuration>
<executions>
<!-- shaded jar -->
<execution>
<id>shaded</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
<!-- dstu jar -->
<execution>
<id>dstu</id>
<phase>package</phase>
@ -178,52 +219,14 @@
<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>
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
<excludes>
<exclude>ca/uhn/fhir/util/ITestingUiClientFactory</exclude>
<exclude>ca/uhn/fhir/rest/server/**</exclude>
<exclude>**/*.java</exclude>
</excludes>
<includes>
<include>ca/uhn/fhir/rest/server/exceptions/**</include>
</includes>
</filter>
<!-- Exclude server side stuff, except exceptions which are used clientside -->
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</artifact>
<excludes>
@ -233,6 +236,7 @@
</filters>
</configuration>
</execution>
<!-- dstu2 jar -->
<execution>
<id>dstu2</id>
<phase>package</phase>
@ -240,51 +244,14 @@
<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>
<filters>
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
<excludes>
<exclude>ca/uhn/fhir/util/ITestingUiClientFactory</exclude>
<exclude>ca/uhn/fhir/rest/server/**</exclude>
<exclude>**/*.java</exclude>
</excludes>
<includes>
<include>ca/uhn/fhir/rest/server/exceptions/**</include>
</includes>
</filter>
<!-- Exclude server side stuff, except exceptions which are used clientside -->
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</artifact>
<excludes>

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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"));

View File

@ -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
};
}
}

View File

@ -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);
}
}
}