private static Object getValue(final Node propertyNode) { // bean validation not sufficient for sets // not possible to access elements, reverting to // Hibernate implementation // TODO investigate other implementation next to // hibernate, JSR 303 v1.1 not sufficient checkNodeImpl(propertyNode); return ExceptionUtil.wrapCatchedExceptions(new Callable<Object>() { @Override public Object call() throws Exception { Method parentMethod = propertyNode.getClass().getMethod("getParent"); Method valueMethod = propertyNode.getClass().getMethod("getValue"); Object parentNode = parentMethod.invoke(propertyNode); if (parentNode != null) { return valueMethod.invoke(parentNode); } else { return valueMethod.invoke(propertyNode); } } }); }
private static Object getParameterValue(final Node propertyNode) { // bean validation not sufficient for sets // not possible to access elements, reverting to // Hibernate implementation // TODO investigate other implementation next to // hibernate, JSR 303 v1.1 not sufficient checkNodeImpl(propertyNode); return ExceptionUtil.wrapCatchedExceptions(new Callable<Object>() { @Override public Object call() throws Exception { Method valueMethod = propertyNode.getClass().getMethod("getValue"); return valueMethod.invoke(propertyNode); } }); }
private String makePath ( final ConstraintViolation<Object> entry ) { final StringBuilder sb = new StringBuilder (); final Path p = entry.getPropertyPath (); for ( final Node n : p ) { if ( sb.length () > 0 ) { sb.append ( '.' ); } sb.append ( n.getName () ); } return sb.toString (); }
@Override public void setupModule(SetupContext context) { context.setMixInAnnotations(Object.class, DisableGetters.class); context.setMixInAnnotations(Collection.class, DisableTypeInfo.class); context.setMixInAnnotations(Map.class, DisableTypeInfo.class); // context.setMixInAnnotations(Array.class, DisableTypeInfo.class); //Default types for interfaces unknown to Jackson context.setMixInAnnotations(Bindings.class, UseSimpleBindings.class); context.setMixInAnnotations(PrincipalCollection.class, UseSimplePrincipalCollection.class); //serializers and typeinfo for shiro classes context.setMixInAnnotations(SimpleAuthenticationInfo.class, UseTypeInfoForCredentials.class); context.setMixInAnnotations(SimpleHash.class, SimpleHashMixin.class); context.setMixInAnnotations(ByteSource.class, UseSimpleByteSource.class); context.setMixInAnnotations(SimpleByteSource.class, SimpleByteSourceMixin.class); //and it's safer to use public interfaces on some classes context.setMixInAnnotations(ConstraintViolation.class, UseDefaultAutoDetect.class); context.setMixInAnnotations(ConstraintDescriptor.class, UseDefaultAutoDetect.class); context.setMixInAnnotations(Node.class, UseDefaultAutoDetect.class); }
@Override public ValidationErrorMessage createBody(ConstraintViolationException ex, HttpServletRequest req) { ErrorMessage tmpl = super.createBody(ex, req); ValidationErrorMessage msg = new ValidationErrorMessage(tmpl); for (ConstraintViolation<?> violation : ex.getConstraintViolations()) { Node pathNode = findLastNonEmptyPathNode(violation.getPropertyPath()); // path is probably useful only for properties (fields) if (pathNode != null && pathNode.getKind() == ElementKind.PROPERTY) { msg.addError(pathNode.getName(), convertToString(violation.getInvalidValue()), violation.getMessage()); // type level constraints etc. } else { msg.addError(violation.getMessage()); } } return msg; }
/** * Take a stab at fixing validation problems ? * * @param object */ private void validate(Object object) { Set<ConstraintViolation<Object>> viols = validator.validate(object); for (ConstraintViolation<Object> constraintViolation : viols) { if (Null.class.isAssignableFrom(constraintViolation.getConstraintDescriptor().getAnnotation().getClass())) { Object o = constraintViolation.getLeafBean(); Iterator<Node> iterator = constraintViolation.getPropertyPath().iterator(); String propertyName = null; while (iterator.hasNext()) { propertyName = iterator.next().getName(); } if (propertyName != null) { try { PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(o.getClass(), propertyName); descriptor.getWriteMethod().invoke(o, new Object[] { null }); } catch (Exception e) { e.printStackTrace(); } } } } }
private static void checkNodeImpl(Node propertyNode) { boolean hibernateNodeImpl = propertyNode.getClass().getName().equals(HIBERNATE_PROPERTY_NODE_IMPL); // NOSONAR class / may not be available boolean hiberanteNodeImpl2 = propertyNode.getClass().getName().equals(HIBERNATE_PROPERTY_NODE_ENGINE_IMPL); // NOSONAR; PreconditionUtil.assertTrue("cannot convert violations for java.util.Set elements, consider using Hibernate validator", hibernateNodeImpl || hiberanteNodeImpl2); }
/** * Translate validated bean and root path into validated resource and * resource path. For example, embeddables belonging to an entity document * are mapped back to an entity violation and a proper path to the * embeddable attribute. * * @param violation to compute the reference * @return computaed reference */ private ResourceRef resolvePath(ConstraintViolation<?> violation) { Object resource = violation.getRootBean(); Object nodeObject = resource; ResourceRef ref = new ResourceRef(resource); Iterator<Node> iterator = violation.getPropertyPath().iterator(); while (iterator.hasNext()) { Node node = iterator.next(); // ignore methods/parameters if (node.getKind() == ElementKind.METHOD) { continue; } if (node.getKind() == ElementKind.PARAMETER) { resource = getParameterValue(node); nodeObject = resource; ref = new ResourceRef(resource); assertResource(resource); continue; } // visit list, set, map references nodeObject = ref.getNodeReference(nodeObject, node); ref.visitNode(nodeObject); // visit property nodeObject = ref.visitProperty(nodeObject, node); } return ref; }
public Object visitProperty(Object nodeObject, Node node) { Object next; if (node.getKind() == ElementKind.PROPERTY) { next = PropertyUtils.getProperty(nodeObject, node.getName()); } else if (node.getKind() == ElementKind.BEAN) { next = nodeObject; } else { throw new UnsupportedOperationException("unknown node: " + node); } if (node.getName() != null) { appendSeparator(); if (!isResource(nodeObject.getClass()) || isPrimaryKey(nodeObject.getClass(), node.getName())) { // continue along attributes path or primary key on root appendSourcePointer(node.getName()); } else if (isAssociation(nodeObject.getClass(), node.getName())) { appendSourcePointer("/data/relationships/"); appendSourcePointer(node.getName()); } else { appendSourcePointer("/data/attributes/"); appendSourcePointer(node.getName()); } } return next; }
private Object getNodeReference(Object element, Node node) { Integer index = node.getIndex(); Object key = node.getKey(); if (index != null) { appendSeparator(); appendSourcePointer(index); return ((List<?>) element).get(index); } else if (key != null) { appendSeparator(); appendSourcePointer(key); return ((Map<?, ?>) element).get(key); } else if (element instanceof Set && getValue(node) != null) { Object elementEntry = getValue(node); // since sets get translated to arrays, we do the same here // crnk-client allocates sets that preserver the order // of arrays List<Object> list = new ArrayList<>(); list.addAll((Set<?>) element); index = list.indexOf(elementEntry); appendSeparator(); appendSourcePointer(index); return getValue(node); } return element; }
@Override public String toString() { Iterator<Node> iterator = iterator(); StringBuilder builder = new StringBuilder(); while (iterator.hasNext()) { Node node = iterator.next(); String name = node.getName(); if (name != null && builder.length() > 0) { builder.append("."); } builder.append(node); } return builder.toString(); }
@Test public void testSimplePath() { final MinijaxPath path = new MinijaxPath(Arrays.asList(new MinijaxPropertyNode(0, "foo"))); assertEquals("foo", path.toString()); for (final Node node : path) { assertTrue(node.isInIterable()); assertNotNull(node.getName()); assertNull(node.getKey()); assertEquals(ElementKind.PROPERTY, node.getKind()); assertEquals(node, node.as(PropertyNode.class)); assertNull(node.as(PropertyNode.class).getContainerClass()); assertEquals(0, (int) node.as(PropertyNode.class).getTypeArgumentIndex()); } }
@Test public void testNestedPath() { final MinijaxPath path = new MinijaxPath(Arrays.asList( new MinijaxPropertyNode(0, "foo"), new MinijaxPropertyNode(1, "bar"))); assertEquals("foo.bar", path.toString()); int i = 0; for (final Node node : path) { assertEquals(i++, (int) node.getIndex()); } }
private String findAttributeName(ConstraintViolation<?> violation) { for (Iterator<Node> iterator = violation.getPropertyPath().iterator(); iterator.hasNext();) { Node node = iterator.next(); if (!iterator.hasNext()) { return node.getName(); } } return null; }
public ValidationResponse(final ConstraintViolationException cause) { super(false, new ArrayList<>()); //noinspection ThrowableResultOfMethodCallIgnored checkNotNull(cause); Set<ConstraintViolation<?>> violations = cause.getConstraintViolations(); if (violations != null && !violations.isEmpty()) { for (ConstraintViolation<?> violation : violations) { List<String> entries = new ArrayList<>(); // iterate path to get the full path Iterator<Node> it = violation.getPropertyPath().iterator(); while (it.hasNext()) { Node node = it.next(); if (ElementKind.PROPERTY == node.getKind() || (ElementKind.PARAMETER == node.getKind() && !it.hasNext())) { if (node.getKey() != null) { entries.add(node.getKey().toString()); } entries.add(node.getName()); } } if (entries.isEmpty()) { if (messages == null) { messages = new ArrayList<>(); } messages.add(violation.getMessage()); } else { if (errors == null) { errors = new HashMap<>(); } errors.put(Joiner.on('.').join(entries), violation.getMessage()); } } } else if (cause.getMessage() != null) { messages = new ArrayList<>(); messages.add(cause.getMessage()); } }
/** * return {@code true} */ public boolean isCascadable(final Object traversableObject, final Node traversableProperty, final Class<?> rootBeanType, final Path pathToTraversableObject, final ElementType elementType) { return true; }
/** * return {@code true} */ public boolean isReachable(final Object traversableObject, final Node traversableProperty, final Class<?> rootBeanType, final Path pathToTraversableObject, final ElementType elementType) { return true; }
@Override protected void compose(final ClassSourceFileComposerFactory composerFactory) { this.addImports(composerFactory, Annotation.class, ConstraintViolation.class, GWT.class, ValidationGroupsMetadata.class, Group.class, GroupChain.class, PathImpl.class, Node.class, GroupChainGenerator.class, GwtBeanDescriptor.class, BeanMetadata.class, GwtValidationContext.class, ArrayList.class, HashSet.class, IllegalArgumentException.class, Set.class, Collection.class, Iterator.class, List.class, ValidationException.class); composerFactory.setSuperclass(AbstractGwtSpecificValidator.class.getCanonicalName() + "<" + this.beanType.getQualifiedSourceName() + ">"); composerFactory.addImplementedInterface(this.validatorType.getName()); }
private Node findLastNonEmptyPathNode(Path path) { List<Node> list = new ArrayList<>(); for (Iterator<Node> it = path.iterator(); it.hasNext(); ) { list.add(it.next()); } Collections.reverse(list); for (Node node : list) { if (!isEmpty(node.getName())) { return node; } } return null; }
@Override protected String extractCategory(ValuedParameter[] params, ConstraintViolation<Object> violation) { Iterator<Node> node = violation.getPropertyPath().iterator(); int index = getFirstParameterIndex( node ); node = violation.getPropertyPath().iterator();// Reset the interator StringBuilder joinedCategoryBuilder = new StringBuilder( mountCategory( node ).replace( "arg" + index , params[index].getName() ) ); return appendPropertyNameIfDefined( joinedCategoryBuilder , violation ) ; }
/** * Returns the category for this constraint violation. By default, the category returned * is the full path for property. You can override this method if you prefer another strategy. */ protected String extractCategory(ValuedParameter[] params, ConstraintViolation<Object> violation) { Iterator<Node> path = violation.getPropertyPath().iterator(); Node method = path.next(); logger.debug("Constraint violation on method {}: {}", method, violation); StringBuilder cat = new StringBuilder(); cat.append(params[path.next().as(ParameterNode.class).getParameterIndex()].getName());// parameter name while (path.hasNext()) { cat.append(".").append(path.next()); } return cat.toString(); }
public PathImpl(List<? extends Node> nodes) { this.nodes = nodes; }
@SuppressWarnings("unchecked") @Override public Iterator<Node> iterator() { return (Iterator<Node>) nodes.iterator(); }
@Override public <T extends Node> T as(Class<T> nodeType) { throw new UnsupportedOperationException(); }
public boolean isCascadable(Object traversableObject, Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) { return false; }
public boolean isReachable(Object traversableObject, Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) { return false; }
/** {@inheritDoc} */ public boolean isCascadable(Object arg0, Node arg1, Class<?> arg2, Path arg3, ElementType arg4) { return true; }
/** {@inheritDoc} */ public boolean isReachable(Object arg0, Node arg1, Class<?> arg2, Path arg3, ElementType arg4) { return true; }
@Override public boolean isCascadable(final Object traversableObject, final Node traversableProperty, final Class<?> rootBeanType, final Path pathToTraversableObject, final ElementType elementType) { return true; }
@Override public boolean isReachable(final Object traversableObject, final Node traversableProperty, final Class<?> rootBeanType, final Path pathToTraversableObject, final ElementType elementType) { return true; }
private String mountCategory( Iterator<Node> node ){ ignoreMethodName( node ); String joined = Joiner.on(".").join( node ); return removeLastDotIndexIfAny(joined); }
private void ignoreMethodName( Iterator<Node> node ){ node.next(); }
private int getFirstParameterIndex( Iterator<Node> node ){ ignoreMethodName( node ); ParameterNode parameterNode = node.next().as(ParameterNode.class); return parameterNode.getParameterIndex(); }