Work on Android

This commit is contained in:
jamesagnew 2015-02-16 14:17:29 -05:00
parent c40a933590
commit e845ab7a40
10 changed files with 254 additions and 94 deletions

View File

@ -12,6 +12,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="maven.pomderived" value="true"/>

View File

@ -60,6 +60,30 @@
<artifactId>slf4j-android</artifactId>
<version>${slf4j_version}</version>
</dependency>
<!-- <dependency> <groupId>org.codehaus.woodstox</groupId> <artifactId>stax2-api</artifactId>
<version>3.1.4</version> </dependency> -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>${commons_codec_version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons_io_version}</version>
</dependency>
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit_version}</version>
<scope>test</scope>
</dependency>
<!-- <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId>
<version>${commons_io_version}</version> <scope>test</scope> </dependency> -->
</dependencies>
<build>
@ -71,6 +95,25 @@
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven_failsafe_plugin_version}</version>
<configuration>
<classpathDependencyScopeExclude>compile+runtime</classpathDependencyScopeExclude>
<additionalClasspathElements>
<additionalClasspathElement>target/hapi-fhir-android-0.9-SNAPSHOT-shaded.jar</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@ -84,8 +127,11 @@
<configuration>
<shadedArtifactAttached>true</shadedArtifactAttached>
<createDependencyReducedPom>true</createDependencyReducedPom>
<!--<minimizeJar>true</minimizeJar>-->
<artifactSet>
<includes>
<include>commons-codec:commons-codec</include>
<include>commons-io:commons-io</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-base</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu</include>
<include>ca.uhn.hapi.fhir:hapi-fhir-structures-dstu2</include>
@ -96,6 +142,7 @@
<include>org.slf4j:slf4j*</include>
<include>org.apache.commons:*</include>
<include>org.apache.httpcomponents:*</include>
<include>org.glassfish:javax.json</include>
</includes>
</artifactSet>
<relocations>
@ -109,20 +156,20 @@
</relocation>
</relocations>
<filters>
<!--
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
<!--
<includes>
<include>**/*.class</include>
<include>**/*.properties</include>
<include>**/*.html</include>
</includes>
-->
<excludes>
<exclude>ca/uhn/fhir/model/dstu/valueset/**</exclude>
<exclude>**/*.java</exclude>
</excludes>
</filter>
<filter>
<artifact>ca.uhn.hapi.fhir:hapi-fhir-base</artifact>
<includes>
<include>ca/uhn/fhir/model/dstu/valueset/NarrativeStatusEnum.class</include>
</includes>
</filter>
-->
</filters>
</configuration>
</execution>

View File

@ -0,0 +1 @@
com.ctc.wstx.stax.WstxInputFactory

View File

@ -0,0 +1 @@
com.ctc.wstx.stax.WstxOutputFactory

View File

@ -0,0 +1,25 @@
package android.util;
public class Log {
public static final int VERBOSE = 2;
public static final int DEBUG = 3;
public static final int INFO = 4;
public static final int WARN = 5;
public static final int ERROR = 6;
public static final int ASSERT = 7;
public static boolean isLoggable(String theName, int thePriority) {
return true;
}
public static boolean isLoggable(int thePriority) {
return true;
}
public static int println(int thePriority, String theName, String theMessage) {
System.out.println("[" + theName + "] " + theMessage);
return 0;
}
}

View File

@ -0,0 +1,87 @@
package ca.uhn.fhir.android;
import static org.junit.Assert.*;
import java.io.File;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.exceptions.FhirClientConnectionException;
public class BuiltJarIT {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BuiltJarIT.class);
@Test
public void testParser() {
FhirContext ctx = FhirContext.forDstu2();
Patient p = new Patient();
p.addIdentifier().setSystem("system");
String str = ctx.newXmlParser().encodeResourceToString(p);
Patient p2 = ctx.newXmlParser().parseResource(Patient.class, str);
assertEquals("system", p2.getIdentifierFirstRep().getSystemElement().getValueAsString());
}
/**
* A simple client test - We try to connect to a server that doesn't exist, but
* if we at least get the right exception it means we made it up to the HTTP/network stack
*
* Disabled for now - TODO: add the old version of the apache client (the one that
* android uses) and see if this passes
*/
public void testClient() {
FhirContext ctx = FhirContext.forDstu2();
try {
IGenericClient client = ctx.newRestfulGenericClient("http://127.0.0.1:44442/SomeBase");
client.conformance();
} catch (FhirClientConnectionException e) {
// this is good
}
}
/**
* Android does not like duplicate entries in the JAR
*/
@Test
public void testJarForDuplicates() throws Exception {
Collection<File> files = FileUtils.listFiles(new File("target"), new WildcardFileFilter("*-shaded.jar"), null);
if (files.isEmpty()) {
throw new Exception("No files matching target/*-shaded.jar");
}
for (File file : files) {
ourLog.info("Testing file: {}", file);
ZipFile zip = new ZipFile(file);
try {
Set<String> names = new HashSet<String>();
for (Enumeration<? extends ZipEntry> iter = zip.entries(); iter.hasMoreElements();) {
ZipEntry next = iter.nextElement();
String nextName = next.getName();
if (!names.add(nextName)) {
throw new Exception("File " + file + " contains duplicate contents: " + nextName);
}
}
ourLog.info("File {} contains {} entries", file, names.size());
} finally {
zip.close();
}
}
}
}

View File

@ -57,18 +57,18 @@ import com.ctc.wstx.stax.WstxOutputFactory;
* This class contains code adapted from the Apache Axiom project.
*/
public class XmlUtil {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(XmlUtil.class);
private static volatile XMLOutputFactory ourOutputFactory;
private static volatile XMLInputFactory ourInputFactory;
private static volatile boolean ourHaveLoggedStaxImplementation;
private static final Map<String, Integer> VALID_ENTITY_NAMES;
private static final ExtendedEntityReplacingXmlResolver XML_RESOLVER = new ExtendedEntityReplacingXmlResolver();
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 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);
private static volatile XMLOutputFactory ourOutputFactory;
private static final Map<String, Integer> VALID_ENTITY_NAMES;
private static final ExtendedEntityReplacingXmlResolver XML_RESOLVER = new ExtendedEntityReplacingXmlResolver();
static {
HashMap<String, Integer> validEntityNames = new HashMap<String, Integer>();
@ -189,6 +189,18 @@ public class XmlUtil {
return er;
}
public static XMLStreamWriter createXmlStreamWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateOutputFactory();
XMLStreamWriter retVal = outputFactory.createXMLStreamWriter(theWriter);
return retVal;
}
public static XMLEventWriter createXmlWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateOutputFactory();
XMLEventWriter retVal = outputFactory.createXMLEventWriter(theWriter);
return retVal;
}
private static XMLInputFactory getOrCreateInputFactory() throws FactoryConfigurationError {
if (ourInputFactory == null) {
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
@ -218,6 +230,56 @@ public class XmlUtil {
return ourInputFactory;
}
private static XMLOutputFactory getOrCreateOutputFactory() throws FactoryConfigurationError {
if (ourOutputFactory == null) {
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(outputFactory.getClass());
}
/*
* Note that these properties are Woodstox specific and they cause a crash in environments where SJSXP is
* being used (e.g. glassfish) so we don't set them there.
*/
try {
Class.forName("com.ctc.wstx.stax.WstxOutputFactory");
if (outputFactory instanceof WstxOutputFactory) {
outputFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new MyEscaper());
}
} catch (ClassNotFoundException e) {
ourLog.debug("WstxOutputFactory (Woodstox) not found on classpath");
}
ourOutputFactory = outputFactory;
}
return ourOutputFactory;
}
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);
@ -262,70 +324,21 @@ public class XmlUtil {
}
}
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;
}
}
public static XMLStreamWriter createXmlStreamWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateOutputFactory();
XMLStreamWriter retVal = outputFactory.createXMLStreamWriter(theWriter);
return retVal;
}
public static XMLEventWriter createXmlWriter(Writer theWriter) throws FactoryConfigurationError, XMLStreamException {
XMLOutputFactory outputFactory = getOrCreateOutputFactory();
XMLEventWriter retVal = outputFactory.createXMLEventWriter(theWriter);
return retVal;
}
public static void main(String[] args) {
System.out.println(Character.toString((char) 167));
}
private static XMLOutputFactory getOrCreateOutputFactory() throws FactoryConfigurationError {
if (ourOutputFactory == null) {
XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
if (!ourHaveLoggedStaxImplementation) {
logStaxImplementation(outputFactory.getClass());
}
/*
* Note that these properties are Woodstox specific and they cause a crash in environments where SJSXP is
* being used (e.g. glassfish) so we don't set them there.
*/
try {
Class.forName("com.ctc.wstx.stax.WstxOutputFactory");
if (outputFactory instanceof WstxOutputFactory) {
outputFactory.setProperty(XMLOutputFactory2.P_TEXT_ESCAPER, new MyEscaper());
private static final class ExtendedEntityReplacingXmlResolver implements XMLResolver {
@Override
public Object resolveEntity(String thePublicID, String theSystemID, String theBaseURI, String theNamespace) throws XMLStreamException {
if (thePublicID == null && theSystemID == null) {
if (theNamespace != null && VALID_ENTITY_NAMES.containsKey(theNamespace)) {
return new String(Character.toChars(VALID_ENTITY_NAMES.get(theNamespace)));
}
} catch (ClassNotFoundException e) {
ourLog.debug("WstxOutputFactory (Woodstox) not found on classpath");
}
ourOutputFactory = outputFactory;
return null;
}
return ourOutputFactory;
}
public static class MyEscaper implements EscapingWriterFactory {
@ -379,17 +392,4 @@ public class XmlUtil {
}
private static final class ExtendedEntityReplacingXmlResolver implements XMLResolver {
@Override
public Object resolveEntity(String thePublicID, String theSystemID, String theBaseURI, String theNamespace) throws XMLStreamException {
if (thePublicID == null && theSystemID == null) {
if (theNamespace != null && VALID_ENTITY_NAMES.containsKey(theNamespace)) {
return new String(Character.toChars(VALID_ENTITY_NAMES.get(theNamespace)));
}
}
return null;
}
}
}

View File

@ -307,9 +307,6 @@
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-sources/tinder</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-resources/tinder</directory>
</resource>

View File

@ -372,9 +372,6 @@
<resource>
<directory>${basedir}/src/main/resources</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-sources/tinder</directory>
</resource>
<resource>
<directory>${basedir}/target/generated-resources/tinder</directory>
</resource>

View File

@ -172,6 +172,7 @@
<junit_version>4.12</junit_version>
<logback_version>1.1.2</logback_version>
<maven_assembly_plugin_version>2.4.1</maven_assembly_plugin_version>
<maven_failsafe_plugin_version>2.18.1</maven_failsafe_plugin_version>
<maven_javadoc_plugin_version>2.10.1</maven_javadoc_plugin_version>
<maven_jxr_plugin_version>2.5</maven_jxr_plugin_version>
<maven_license_plugin_version>1.7</maven_license_plugin_version>
@ -190,6 +191,8 @@
<thymeleaf-version>2.1.4.RELEASE</thymeleaf-version>
<ebay_cors_filter_version>1.0.1</ebay_cors_filter_version>
<woodstox_version>4.4.0</woodstox_version>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
@ -715,7 +718,8 @@
<module>restful-server-example-test</module>
<module>hapi-fhir-testpage-overlay</module>
<module>hapi-fhir-jpaserver-uhnfhirtest</module>
<!-- <module>hapi-fhir-dist</module> -->
<module>hapi-fhir-android</module>
<module>hapi-fhir-dist</module>
</modules>
</profile>
</profiles>