From 7ad5d6bba8d952fc9b358b8050c6219fb3d0f4f8 Mon Sep 17 00:00:00 2001 From: Thomas Andersen Date: Tue, 6 Oct 2015 21:56:29 +0200 Subject: [PATCH] Move dependency on java.util.jar and java.beans to optional dependency Move some more dependencies to optionel dependencies and write more test for different base methods. --- .../main/java/ca/uhn/fhir/util/BeanUtils.java | 58 ++++------ .../main/java/ca/uhn/fhir/util/XmlUtil.java | 83 ++------------ .../fhir/util/jar/DependencyLogFactory.java | 36 ++++++ .../uhn/fhir/util/jar/DependencyLogImpl.java | 107 ++++++++++++++++++ .../ca/uhn/fhir/util/jar/IDependencyLog.java | 27 +++++ .../uhn/fhir/util/reflection/IBeanUtils.java | 31 +++++ .../util/reflection/JavaBeansBeanUtil.java | 70 ++++++++++++ .../util/reflection/JavaReflectBeanUtil.java | 63 +++++++++++ .../java/ca/uhn/fhir/util/BeanUtilTest.java | 78 +++++++++++++ .../uhn/fhir/util/DependencyLogUtilTest.java | 15 +++ .../java/ca/uhn/fhir/util/ObjectUtilTest.java | 57 ++++++++++ 11 files changed, 514 insertions(+), 111 deletions(-) create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogFactory.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogImpl.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/IDependencyLog.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/IBeanUtils.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaBeansBeanUtil.java create mode 100644 hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaReflectBeanUtil.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/util/BeanUtilTest.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/util/DependencyLogUtilTest.java create mode 100644 hapi-fhir-base/src/test/java/ca/uhn/fhir/util/ObjectUtilTest.java diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BeanUtils.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BeanUtils.java index 6e8b9b18495..03b86d86aee 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BeanUtils.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/BeanUtils.java @@ -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); + } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java index 5938389b912..fe6b26cd1e8 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/XmlUtil.java @@ -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 { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogFactory.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogFactory.java new file mode 100644 index 00000000000..ea861a8254d --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogFactory.java @@ -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 clas = (Class) Class.forName("ca.uhn.fhir.util.jar.DependencyLogImpl"); + return clas.newInstance(); + } catch (ReflectiveOperationException e) { + ourLog.info("Could not log dependency."); + return null; + } + } +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogImpl.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogImpl.java new file mode 100644 index 00000000000..b3c778073d5 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/DependencyLogImpl.java @@ -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; + } + } +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/IDependencyLog.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/IDependencyLog.java new file mode 100644 index 00000000000..3ad25a542ed --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/jar/IDependencyLog.java @@ -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); + +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/IBeanUtils.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/IBeanUtils.java new file mode 100644 index 00000000000..36f1784c6f3 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/IBeanUtils.java @@ -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; +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaBeansBeanUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaBeansBeanUtil.java new file mode 100644 index 00000000000..c7f43cd1106 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaBeansBeanUtil.java @@ -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); + } +} diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaReflectBeanUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaReflectBeanUtil.java new file mode 100644 index 00000000000..a8c8bd98dd3 --- /dev/null +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/reflection/JavaReflectBeanUtil.java @@ -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); + + } + +} diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/BeanUtilTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/BeanUtilTest.java new file mode 100644 index 00000000000..bf195717f58 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/BeanUtilTest.java @@ -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; + } + } +} diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/DependencyLogUtilTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/DependencyLogUtilTest.java new file mode 100644 index 00000000000..faecd8fcce4 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/DependencyLogUtilTest.java @@ -0,0 +1,15 @@ +package ca.uhn.fhir.util; + +import static org.junit.Assert.*; + +import org.junit.Test; + +import ca.uhn.fhir.util.jar.DependencyLogFactory; + +public class DependencyLogUtilTest { + + @Test + public void testDependencyLogFactory() { + assertNotNull(DependencyLogFactory.createJarLogger()); + } +} diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/ObjectUtilTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/ObjectUtilTest.java new file mode 100644 index 00000000000..80a8d43db49 --- /dev/null +++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/ObjectUtilTest.java @@ -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()); + } + } + +}