Re-org submodules, add debug compiler options
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package org.springframework.data.rest.core;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public interface Handler<T,V> {
|
||||
V handle(T t);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.data.rest.core;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public interface Link {
|
||||
|
||||
String rel();
|
||||
|
||||
URI href();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.springframework.data.rest.core;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public class SimpleLink implements Link {
|
||||
|
||||
private String rel;
|
||||
private URI href;
|
||||
|
||||
public SimpleLink() {
|
||||
}
|
||||
|
||||
public SimpleLink(String rel, URI href) {
|
||||
this.rel = rel;
|
||||
this.href = href;
|
||||
}
|
||||
|
||||
@Override public String rel() {
|
||||
return rel;
|
||||
}
|
||||
|
||||
@Override public URI href() {
|
||||
return href;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "SimpleLink{" +
|
||||
"rel='" + rel + '\'' +
|
||||
", href=" + href +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public abstract class BeanUtils {
|
||||
|
||||
private BeanUtils() {
|
||||
}
|
||||
|
||||
public static ConfigurableConversionService CONVERSION_SERVICE = new DefaultConversionService();
|
||||
|
||||
private static final LoadingCache<Object[], Field> fields = CacheBuilder.newBuilder().build(
|
||||
new CacheLoader<Object[], Field>() {
|
||||
@Override public Field load(Object[] key) throws Exception {
|
||||
Class<?> clazz = (Class<?>) key[0];
|
||||
String name = (String) key[1];
|
||||
Field f = ReflectionUtils.findField(clazz, name);
|
||||
if (null != f) {
|
||||
ReflectionUtils.makeAccessible(f);
|
||||
return f;
|
||||
} else {
|
||||
throw new IllegalArgumentException("Field " + clazz.getName() + "." + name + " not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
private static final LoadingCache<Object[], Method> methods = CacheBuilder.newBuilder().build(
|
||||
new CacheLoader<Object[], Method>() {
|
||||
@Override public Method load(Object[] key) throws Exception {
|
||||
Class<?> clazz = (Class<?>) key[0];
|
||||
String name = (String) key[1];
|
||||
Integer paramCnt = key.length == 3 ? (Integer) key[2] : 0;
|
||||
|
||||
for (Method m : clazz.getDeclaredMethods()) {
|
||||
if (m.getName().equals(name)) {
|
||||
if (m.getParameterTypes().length == paramCnt) {
|
||||
ReflectionUtils.makeAccessible(m);
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Method " + clazz.getName() + "." + name + " not found");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public static boolean hasProperty(String property, Object... objs) {
|
||||
for (Object obj : objs) {
|
||||
if (obj instanceof Map) {
|
||||
return ((Map) obj).containsKey(property);
|
||||
}
|
||||
Class<?> type = obj.getClass();
|
||||
try {
|
||||
if (FluentBeanUtils.isFluentBean(type)) {
|
||||
return null != methods.get(new Object[]{type, property});
|
||||
} else {
|
||||
if (null == methods.get(new Object[]{type, "get" + StringUtils.capitalize(property)})) {
|
||||
return null != fields.get(new Object[]{type, property});
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (UncheckedExecutionException e) {
|
||||
if (e.getCause().getClass() == IllegalArgumentException.class) {
|
||||
return false;
|
||||
} else {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> T findFirst(Class<T> clazz, List<?> stack) {
|
||||
for (Object o : stack) {
|
||||
if (ClassUtils.isAssignable(clazz, o.getClass())) {
|
||||
return (T) o;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static Object findFirst(Object o, Object... objs) {
|
||||
for (Object obj : objs) {
|
||||
if (o == obj || null != o && o.equals(obj)) {
|
||||
return obj;
|
||||
} else if (obj instanceof List) {
|
||||
return Collections.binarySearch((List) obj, o);
|
||||
} else if (obj instanceof Object[]) {
|
||||
return Arrays.binarySearch((Object[]) obj, o);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Object findFirst(String property, Object... objs) {
|
||||
for (Object obj : objs) {
|
||||
if (obj instanceof Map) {
|
||||
return ((Map) obj).get(property);
|
||||
}
|
||||
Class<?> type = obj.getClass();
|
||||
try {
|
||||
Field f = fields.get(new Object[]{type, property});
|
||||
if (FluentBeanUtils.isFluentBean(type)) {
|
||||
return FluentBeanUtils.get(property, obj);
|
||||
} else {
|
||||
Method getter = methods.get(new Object[]{type, "get" + StringUtils.capitalize(property)});
|
||||
try {
|
||||
if (null != getter) {
|
||||
return getter.invoke(obj);
|
||||
} else {
|
||||
return f.get(obj);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean containsType(Class<?> type, List<Object> objs) {
|
||||
return containsType(type, objs.toArray());
|
||||
}
|
||||
|
||||
public static boolean containsType(Class<?> type, Object[] objs) {
|
||||
for (Object obj : objs) {
|
||||
if (null != obj && ClassUtils.isAssignable(obj.getClass(), type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static Object invoke(String methodName, Object target, Object... args) {
|
||||
return invoke(methodName, target, Object.class, args);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public static <T> T invoke(String methodName, Object target, Class<T> returnType, Object... args) {
|
||||
if (null == target) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> type = target.getClass();
|
||||
try {
|
||||
Method m = methods.get(new Object[]{type, methodName, args.length});
|
||||
List<Object> newArgs = new ArrayList<Object>(args.length);
|
||||
Class<?>[] paramTypes = m.getParameterTypes();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object o = args[i];
|
||||
Class<?> oType = o.getClass();
|
||||
Class<?> pType = paramTypes[i];
|
||||
if (!ClassUtils.isAssignable(oType, pType)) {
|
||||
newArgs.add(CONVERSION_SERVICE.convert(o, pType));
|
||||
} else {
|
||||
newArgs.add(o);
|
||||
}
|
||||
}
|
||||
|
||||
Object rtnVal = m.invoke(target, newArgs.toArray());
|
||||
if ((returnType != Void.TYPE || returnType != Object.class)
|
||||
&& null != rtnVal
|
||||
&& !ClassUtils.isAssignable(returnType, rtnVal.getClass())) {
|
||||
return CONVERSION_SERVICE.convert(rtnVal, returnType);
|
||||
} else {
|
||||
return (T) rtnVal;
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.JsonProcessingException;
|
||||
import org.codehaus.jackson.JsonToken;
|
||||
import org.codehaus.jackson.map.DeserializationContext;
|
||||
import org.codehaus.jackson.map.deser.std.StdDeserializer;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public class FluentBeanDeserializer extends StdDeserializer {
|
||||
|
||||
private ConversionService conversionService;
|
||||
private FluentBeanUtils.Metadata beanMeta;
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public FluentBeanDeserializer(final Class<?> valueClass, ConversionService conversionService) {
|
||||
super(valueClass);
|
||||
this.conversionService = conversionService;
|
||||
this.beanMeta = FluentBeanUtils.metadata(valueClass);
|
||||
|
||||
if (!FluentBeanUtils.isFluentBean(valueClass)) {
|
||||
throw new IllegalArgumentException("Class of type " + valueClass + " is not a FluentBean");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object deserialize(JsonParser jp,
|
||||
DeserializationContext ctxt)
|
||||
throws IOException,
|
||||
JsonProcessingException {
|
||||
if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
|
||||
throw ctxt.mappingException(_valueClass);
|
||||
}
|
||||
|
||||
Object bean;
|
||||
try {
|
||||
bean = _valueClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
while (jp.nextToken() != JsonToken.END_OBJECT) {
|
||||
String name = jp.getCurrentName();
|
||||
Method setter = beanMeta.setters().get(name);
|
||||
|
||||
Object obj;
|
||||
if (null != setter) {
|
||||
Class<?> targetType = setter.getParameterTypes()[0];
|
||||
if (ClassUtils.isAssignable(targetType, Long.class)) {
|
||||
obj = jp.nextLongValue(-1);
|
||||
} else if (ClassUtils.isAssignable(targetType, Integer.class)) {
|
||||
obj = jp.nextIntValue(-1);
|
||||
} else if (ClassUtils.isAssignable(targetType, Boolean.class)) {
|
||||
obj = jp.nextBooleanValue();
|
||||
} else {
|
||||
obj = jp.nextTextValue();
|
||||
}
|
||||
|
||||
if (null != obj) {
|
||||
if (!ClassUtils.isAssignable(obj.getClass(), targetType)) {
|
||||
obj = conversionService.convert(obj, targetType);
|
||||
}
|
||||
|
||||
try {
|
||||
setter.invoke(bean, obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.map.SerializerProvider;
|
||||
import org.codehaus.jackson.map.ser.std.SerializerBase;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public class FluentBeanSerializer extends SerializerBase {
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public FluentBeanSerializer(final Class<?> t) {
|
||||
super(t);
|
||||
|
||||
if (!FluentBeanUtils.isFluentBean(t)) {
|
||||
throw new IllegalArgumentException("Class of type " + t + " is not a FluentBean");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@Override
|
||||
public void serialize(final Object value,
|
||||
final JsonGenerator jgen,
|
||||
final SerializerProvider provider)
|
||||
throws IOException,
|
||||
JsonGenerationException {
|
||||
if (null == value) {
|
||||
provider.defaultSerializeNull(jgen);
|
||||
} else {
|
||||
Class<?> type = value.getClass();
|
||||
if (ClassUtils.isAssignable(type, Collection.class)) {
|
||||
jgen.writeStartArray();
|
||||
for (Object o : (Collection) value) {
|
||||
write(o, jgen, provider);
|
||||
}
|
||||
jgen.writeEndArray();
|
||||
} else if (ClassUtils.isAssignable(type, Map.class)) {
|
||||
jgen.writeStartObject();
|
||||
for (Map.Entry<String, Object> entry : ((Map<String, Object>) value).entrySet()) {
|
||||
jgen.writeFieldName(entry.getKey());
|
||||
write(entry.getValue(), jgen, provider);
|
||||
}
|
||||
jgen.writeEndObject();
|
||||
} else {
|
||||
write(value, jgen, provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void write(final Object value,
|
||||
final JsonGenerator jgen,
|
||||
final SerializerProvider provider) throws IOException {
|
||||
Class<?> type = value.getClass();
|
||||
if (ClassUtils.isAssignable(type, _handledType)) {
|
||||
jgen.writeStartObject();
|
||||
for (String fname : FluentBeanUtils.metadata(type).fieldNames()) {
|
||||
jgen.writeFieldName(fname);
|
||||
write(FluentBeanUtils.get(fname, value), jgen, provider);
|
||||
}
|
||||
jgen.writeEndObject();
|
||||
} else {
|
||||
jgen.writeObject(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public abstract class FluentBeanUtils {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FluentBeanUtils.class);
|
||||
private static final LoadingCache<Class<?>, Metadata> metadata = CacheBuilder.newBuilder().build(
|
||||
new CacheLoader<Class<?>, Metadata>() {
|
||||
@Override public Metadata load(Class<?> type) throws Exception {
|
||||
final Metadata meta = new Metadata();
|
||||
ReflectionUtils.doWithFields(
|
||||
type,
|
||||
new ReflectionUtils.FieldCallback() {
|
||||
@Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
|
||||
final String fname = field.getName();
|
||||
if (!fname.startsWith("_")) {
|
||||
ReflectionUtils.doWithMethods(field.getDeclaringClass(), new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
if (method.getName().equals(fname)) {
|
||||
if (method.getParameterTypes().length == 0) {
|
||||
meta.getters.put(fname, method);
|
||||
} else if (method.getParameterTypes().length == 1) {
|
||||
meta.setters.put(fname, method);
|
||||
}
|
||||
meta.fieldNames.add(fname);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
public static Metadata metadata(Class<?> targetType) {
|
||||
try {
|
||||
return metadata.get(targetType);
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Object set(String property, Object value, Object bean) {
|
||||
if (null == bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> type = bean.getClass();
|
||||
try {
|
||||
Method setter = metadata.get(type).setters.get(property);
|
||||
if (null != setter) {
|
||||
return setter.invoke(bean, value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(t.getMessage(), t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object get(String property, Object bean) {
|
||||
if (null == bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Class<?> type = bean.getClass();
|
||||
try {
|
||||
Method getter = metadata.get(type).getters.get(property);
|
||||
if (null != getter) {
|
||||
return getter.invoke(bean);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug(t.getMessage(), t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isFluentBean(Class<?> type) {
|
||||
try {
|
||||
return metadata.get(type).getters.size() > 0;
|
||||
} catch (ExecutionException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Metadata {
|
||||
List<String> fieldNames = new ArrayList<String>();
|
||||
Map<String, Method> getters = new HashMap<String, Method>();
|
||||
Map<String, Method> setters = new HashMap<String, Method>();
|
||||
|
||||
public List<String> fieldNames() {
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
public Map<String, Method> getters() {
|
||||
return getters;
|
||||
}
|
||||
|
||||
public Map<String, Method> setters() {
|
||||
return setters;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.springframework.data.rest.core.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.springframework.data.rest.core.Handler;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
public abstract class UriUtils {
|
||||
|
||||
private UriUtils() {
|
||||
}
|
||||
|
||||
public static boolean validBaseUri(URI baseUri, URI uri) {
|
||||
String path = UriUtils.path(baseUri.relativize(uri));
|
||||
return !StringUtils.hasText(path) || path.charAt(0) != '/';
|
||||
}
|
||||
|
||||
public static <V> V foreach(URI baseUri, URI uri, Handler<URI, V> handler) {
|
||||
List<URI> uris = explode(baseUri, uri);
|
||||
V v = null;
|
||||
for (URI u : uris) {
|
||||
v = handler.handle(u);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Stack<URI> explode(URI baseUri, URI uri) {
|
||||
Stack<URI> uris = new Stack<URI>();
|
||||
if (StringUtils.hasText(uri.getPath())) {
|
||||
URI relativeUri = baseUri.relativize(uri);
|
||||
if (StringUtils.hasText(relativeUri.getPath())) {
|
||||
for (String part : relativeUri.getPath().split("/")) {
|
||||
uris.add(URI.create(part + (StringUtils.hasText(uri.getQuery()) ? "?" + uri.getQuery() : "")));
|
||||
}
|
||||
}
|
||||
}
|
||||
return uris;
|
||||
}
|
||||
|
||||
public static URI merge(URI baseUri, URI... uris) {
|
||||
StringBuilder query = new StringBuilder();
|
||||
|
||||
UriComponentsBuilder ub = UriComponentsBuilder.fromUri(baseUri);
|
||||
for (URI uri : uris) {
|
||||
String s = uri.getScheme();
|
||||
if (null != s) {
|
||||
ub.scheme(s);
|
||||
}
|
||||
|
||||
s = uri.getUserInfo();
|
||||
if (null != s) {
|
||||
ub.userInfo(s);
|
||||
}
|
||||
|
||||
s = uri.getHost();
|
||||
if (null != s) {
|
||||
ub.host(s);
|
||||
}
|
||||
|
||||
int i = uri.getPort();
|
||||
if (i > 0) {
|
||||
ub.port(i);
|
||||
}
|
||||
|
||||
s = uri.getPath();
|
||||
if (null != s) {
|
||||
if (!uri.isAbsolute() && StringUtils.hasText(s)) {
|
||||
ub.pathSegment(s);
|
||||
} else {
|
||||
ub.path(s);
|
||||
}
|
||||
}
|
||||
|
||||
s = uri.getQuery();
|
||||
if (null != s) {
|
||||
if (query.length() > 0) {
|
||||
query.append("&");
|
||||
}
|
||||
query.append(s);
|
||||
}
|
||||
|
||||
s = uri.getFragment();
|
||||
if (null != s) {
|
||||
ub.fragment(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (query.length() > 0) {
|
||||
ub.query(query.toString());
|
||||
}
|
||||
|
||||
return ub.build().toUri();
|
||||
}
|
||||
|
||||
public static String path(URI uri) {
|
||||
if (null == uri) {
|
||||
return null;
|
||||
}
|
||||
String s = uri.getPath();
|
||||
if (s.endsWith("/")) {
|
||||
return s.substring(0, s.length() - 1);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static URI tail(URI baseUri, URI uri) {
|
||||
Stack<URI> uris = explode(baseUri, uri);
|
||||
return uris.size() > 0 ? uris.get(Math.max(uris.size() - 1, 0)) : null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.springframework.data.rest.core.spec
|
||||
|
||||
import org.springframework.data.rest.core.util.UriUtils
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Jon Brisbin <jon@jbrisbin.com>
|
||||
*/
|
||||
class UriUtilsSpec extends Specification {
|
||||
|
||||
def "merges URIs correctly"() {
|
||||
|
||||
given:
|
||||
// (absolute) URI of the base resource
|
||||
def baseUri = new URI("http://localhost:8080/baseUrl")
|
||||
// (relative) URI of the top-level Resource
|
||||
def uri2 = new URI("resource")
|
||||
// (relative) URI of the second-level Resource
|
||||
def uri3 = new URI("1")
|
||||
// (fragment) URI of the bottom-level Resource
|
||||
def uri4 = new URI("count")
|
||||
|
||||
when:
|
||||
def uri5 = UriUtils.merge(baseUri, uri2, uri3, uri4)
|
||||
|
||||
then:
|
||||
uri5.toString() == "http://localhost:8080/baseUrl/resource/1/count"
|
||||
|
||||
}
|
||||
|
||||
def "explodes URIs correctly"() {
|
||||
|
||||
given:
|
||||
// (absolute) URI of the base resource
|
||||
def baseUri = new URI("http://localhost:8080/baseUrl")
|
||||
// (absolute) URI of the full resource to get a path to
|
||||
def resourceUri = new URI("http://localhost:8080/baseUrl/resource/1/property")
|
||||
|
||||
when:
|
||||
def uris = UriUtils.explode(baseUri, resourceUri)
|
||||
|
||||
then:
|
||||
uris.size() == 3
|
||||
uris[2].path == "property"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
18
spring-data-rest-core/src/test/resources/logback.xml
Normal file
18
spring-data-rest-core/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<configuration>
|
||||
|
||||
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>
|
||||
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.data.services" level="DEBUG"/>
|
||||
<logger name="org.springframework" level="INFO"/>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="stdout"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user