Skip to content

Commit

Permalink
Fix #23 Stop using illegal reflective access
Browse files Browse the repository at this point in the history
  • Loading branch information
reda-alaoui committed Jan 13, 2020
1 parent de94ecf commit 035f8ca
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.cosium.spring.data.jpa.entity.graph.repository.query;

import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph;
import java.lang.reflect.Method;
import org.springframework.core.MethodParameter;
import org.springframework.data.jpa.repository.query.JpaParameters;

/** @author Réda Housni Alaoui */
class EntityGraphAwareJpaParameters extends JpaParameters {

public EntityGraphAwareJpaParameters(Method method) {
super(method);
}

@Override
protected JpaParameter createParameter(MethodParameter parameter) {
return new EntityGraphAwareJpaParameter(parameter);
}

private static class EntityGraphAwareJpaParameter extends JpaParameters.JpaParameter {

private final MethodParameter parameter;

protected EntityGraphAwareJpaParameter(MethodParameter parameter) {
super(parameter);
this.parameter = parameter;
}

@Override
public boolean isBindable() {
return !EntityGraph.class.equals(parameter.getParameterType()) && super.isBindable();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.cosium.spring.data.jpa.entity.graph.repository.query;

import java.lang.reflect.Method;
import org.springframework.data.jpa.provider.QueryExtractor;
import org.springframework.data.jpa.repository.query.JpaParameters;
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;

/** @author Réda Housni Alaoui */
class EntityGraphAwareJpaQueryMethod extends JpaQueryMethod {

protected EntityGraphAwareJpaQueryMethod(
Method method,
RepositoryMetadata metadata,
ProjectionFactory factory,
QueryExtractor extractor) {
super(method, metadata, factory, extractor);
}

@Override
protected JpaParameters createParameters(Method method) {
return new EntityGraphAwareJpaParameters(method);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.cosium.spring.data.jpa.entity.graph.repository.query;

import java.lang.reflect.Method;
import org.springframework.data.jpa.provider.QueryExtractor;
import org.springframework.data.jpa.repository.query.JpaQueryMethod;
import org.springframework.data.jpa.repository.query.JpaQueryMethodFactory;
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.repository.core.RepositoryMetadata;

/** @author Réda Housni Alaoui */
public class EntityGraphAwareJpaQueryMethodFactory implements JpaQueryMethodFactory {

private final QueryExtractor extractor;

public EntityGraphAwareJpaQueryMethodFactory(QueryExtractor extractor) {
this.extractor = extractor;
}

@Override
public JpaQueryMethod build(
Method method, RepositoryMetadata metadata, ProjectionFactory factory) {
return new EntityGraphAwareJpaQueryMethod(method, metadata, factory, extractor);
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package com.cosium.spring.data.jpa.entity.graph.repository.support;

import static org.springframework.data.querydsl.QuerydslUtils.QUERY_DSL_PRESENT;

import com.cosium.spring.data.jpa.entity.graph.domain.EntityGraph;
import com.cosium.spring.data.jpa.entity.graph.repository.query.EntityGraphAwareJpaQueryMethodFactory;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.provider.PersistenceProvider;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
import org.springframework.util.ReflectionUtils;

import javax.persistence.EntityManager;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import static org.springframework.data.querydsl.QuerydslUtils.QUERY_DSL_PRESENT;

/**
* This repository factory allows to build {@link EntityGraph} aware repositories. Created on
Expand All @@ -24,10 +18,6 @@
*/
public class EntityGraphJpaRepositoryFactory extends JpaRepositoryFactory {

static {
addEntityGraphToSpecialTypes();
}

/**
* Creates a new {@link JpaRepositoryFactory}.
*
Expand All @@ -36,34 +26,9 @@ public class EntityGraphJpaRepositoryFactory extends JpaRepositoryFactory {
public EntityGraphJpaRepositoryFactory(EntityManager entityManager) {
super(entityManager);
addRepositoryProxyPostProcessor(new RepositoryMethodEntityGraphExtractor(entityManager));
}

/**
* Add {@link EntityGraph} to the special types.<br>
* {@link EntityGraph} must be considered as a special type by Spring Data JPA.<br>
* For this to occur, {@link EntityGraph} must be part of Spring Data JPA arrays storing special
* types.<br>
* Once a type is marked as special, Spring Data JPA will not try to bind it to an under
* construction query.
*/
private static void addEntityGraphToSpecialTypes() {
addEntityGraphToSpecialTypes(Parameters.class, "TYPES");
addEntityGraphToSpecialTypes(Parameter.class, "TYPES");
}

private static void addEntityGraphToSpecialTypes(Class<?> clazz, String fieldName) {
try {
Field field = ReflectionUtils.findField(clazz, fieldName);
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
List<Class<?>> specialTypes = new ArrayList<Class<?>>((List<Class<?>>) field.get(null));
specialTypes.add(EntityGraph.class);
ReflectionUtils.setField(field, null, specialTypes);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
setQueryMethodFactory(
new EntityGraphAwareJpaQueryMethodFactory(
PersistenceProvider.fromEntityManager(entityManager)));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.cosium.spring.data.jpa.entity.graph.repository.support;

import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

/**
* Forces the use of {@link RepositoryEntityManagerEntityGraphInjector} while targeting {@link
* EntityGraphJpaRepositoryFactory}.
Expand Down

0 comments on commit 035f8ca

Please sign in to comment.