-
Notifications
You must be signed in to change notification settings - Fork 71
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(jans-config-api): new data type interceptor - wip
- Loading branch information
Showing
4 changed files
with
422 additions
and
0 deletions.
There are no files selected for viewing
262 changes: 262 additions & 0 deletions
262
...nfig-api/server/src/main/java/io/jans/configapi/interceptor/RequestReaderInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
/* | ||
* Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. | ||
* | ||
* Copyright (c) 2020, Janssen Project | ||
*/ | ||
|
||
package io.jans.configapi.interceptor; | ||
|
||
//import io.jans.as.common.model.common.User; | ||
|
||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
|
||
import io.jans.configapi.core.interceptor.RequestInterceptor; | ||
import io.jans.orm.PersistenceEntryManager; | ||
import io.jans.configapi.core.rest.ProtectedApi; | ||
import io.jans.configapi.core.util.DataUtil; | ||
import io.jans.configapi.security.service.AuthorizationService; | ||
import io.jans.configapi.util.ApiConstants; | ||
import io.jans.configapi.util.DataProcessingUtil; | ||
import io.jans.orm.PersistenceEntryManager; | ||
import jakarta.annotation.Priority; | ||
import jakarta.inject.Inject; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.ws.rs.Priorities; | ||
import jakarta.ws.rs.ext.ReaderInterceptor; | ||
import jakarta.ws.rs.ext.ReaderInterceptorContext; | ||
import jakarta.ws.rs.WebApplicationException; | ||
import jakarta.ws.rs.container.ResourceInfo; | ||
import jakarta.ws.rs.core.Context; | ||
import jakarta.ws.rs.core.HttpHeaders; | ||
import jakarta.ws.rs.core.Response; | ||
import jakarta.ws.rs.core.UriInfo; | ||
import jakarta.ws.rs.ext.Provider; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.io.IOException; | ||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.Method; | ||
import java.lang.reflect.Parameter; | ||
import java.util.Arrays; | ||
import java.util.Collection; | ||
import java.util.Map; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
import org.json.JSONException; | ||
import org.json.JSONObject; | ||
import java.util.Date; | ||
import org.apache.commons.io.IOUtils; | ||
import org.apache.commons.lang.StringUtils; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import jakarta.interceptor.AroundInvoke; | ||
import jakarta.interceptor.Interceptor; | ||
import jakarta.interceptor.InvocationContext; | ||
|
||
@Interceptor | ||
@RequestInterceptor | ||
@Priority(Interceptor.Priority.APPLICATION) | ||
public class RequestReaderInterceptor { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(RequestReaderInterceptor.class); | ||
private static final String[] IGNORE_METHODS = { "@jakarta.ws.rs.GET()", "@jakarta.ws.rs.DELETE()", "@jakarta.ws.rs.OPTIONS()", "@jakarta.ws.rs.PATCH()" }; | ||
|
||
@Inject | ||
private Logger log; | ||
|
||
@Context | ||
UriInfo info; | ||
|
||
@Context | ||
HttpServletRequest request; | ||
|
||
@Context | ||
private HttpHeaders httpHeaders; | ||
|
||
@Context | ||
private ResourceInfo resourceInfo; | ||
|
||
@Inject | ||
private DataProcessingUtil dataProcessingUtil; | ||
|
||
|
||
@Inject | ||
PersistenceEntryManager persistenceEntryManager; | ||
|
||
@SuppressWarnings({ "all" }) | ||
@AroundInvoke | ||
public Object aroundReadFrom(InvocationContext context) throws Exception { | ||
System.out.println("\n\n\n RequestReaderInterceptor: entry - log=" + log + " logger=" + logger | ||
+ " , request:{} " + request + " info:{} " + info + ". resourceInfo=" + resourceInfo | ||
+ " , context:{} " + context + " , dataProcessingUtil = " + dataProcessingUtil+" , persistenceEntryManager"+persistenceEntryManager+" \n\n\n"); | ||
try { | ||
logger.error( | ||
"======================= RequestReaderInterceptor Performing DataType Conversion ============================"); | ||
|
||
// context | ||
logger.error( | ||
"======ReaderInterceptorContext - context.getClass():{}, context.getConstructor(), context.getContextData():{}, context.getMethod():{}, context.getParameters():{}, context.getTarget():{}, context.getInputStream():{} ", | ||
context.getClass(), context.getConstructor(), context.getContextData(), context.getMethod(), | ||
context.getParameters(), context.getTarget()); | ||
|
||
//method | ||
logger.error( | ||
"======ReaderInterceptorContext - context.getMethod().getAnnotatedExceptionTypes().toString() :{}, context.getMethod().getAnnotatedParameterTypes().toString() :{}, context.getMethod().getAnnotatedReceiverType().toString() :{}, context.getMethod().getAnnotation(jakarta.ws.rs.GET.class):{}, context.getMethod().getAnnotations().toString() :{}., context.getMethod().getAnnotationsByType(jakarta.ws.rs.GET.class):{} ", | ||
context.getMethod().getAnnotatedExceptionTypes().toString(), context.getMethod().getAnnotatedParameterTypes().toString(), context.getMethod().getAnnotatedReceiverType().toString(), context.getMethod().getAnnotation(jakarta.ws.rs.GET.class), | ||
context.getMethod().getAnnotations().toString(), context.getMethod().getAnnotationsByType(jakarta.ws.rs.GET.class)); | ||
|
||
|
||
boolean contains = isIgnoreMethod(context); | ||
logger.error("====== context.getMethod():{} present in ignoreList contains:{}", context.getMethod(), | ||
contains); | ||
if (contains) { | ||
logger.error("====== Exiting ReaderInterceptorContext as no action required for {} method. ======", | ||
context.getMethod()); | ||
return context.proceed(); | ||
} | ||
|
||
processRequest(context); | ||
|
||
} catch (Exception ex) { | ||
throw new WebApplicationException(ex); | ||
} | ||
return context.proceed(); | ||
} | ||
|
||
private boolean isIgnoreMethod(InvocationContext context) { | ||
logger.error("Checking if method to be ignored"); | ||
if(context.getMethod().getAnnotations()==null || context.getMethod().getAnnotations().length<=0) { | ||
return false; | ||
} | ||
|
||
for(int i=0; i<context.getMethod().getAnnotations().length;i++) { | ||
logger.error("======ReaderInterceptorContext - context.getMethod().getAnnotations()["+i+"]:{} ",context.getMethod().getAnnotations()[i]); | ||
|
||
logger.error("======ReaderInterceptorContext - anyMatch:{} ",Arrays.stream(IGNORE_METHODS).anyMatch(context.getMethod().getAnnotations()[i].toString()::equals)); | ||
|
||
if(context.getMethod().getAnnotations()[i]!=null && Arrays.stream(IGNORE_METHODS).anyMatch(context.getMethod().getAnnotations()[i].toString()::equals)) { | ||
logger.error("======ReaderInterceptorContext - context.getMethod() matched and hence will be ignored!!!!"); | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
private void processRequest(InvocationContext context) | ||
throws IOException, IllegalAccessException, InstantiationException { | ||
logger.error( | ||
"ReaderInterceptorContext Data - context:{} , context.getClass():{}, context.getContextData():{}, context.getMethod():{} , context.getParameters():{} , context.getTarget():{} ", | ||
context, context.getClass(), context.getContextData(), context.getMethod(), context.getParameters(), | ||
context.getTarget()); | ||
|
||
Object[] ctxParameters = context.getParameters(); | ||
logger.error("RequestReaderInterceptor - Processing Data - ctxParameters:{} ", ctxParameters); | ||
|
||
Method method = context.getMethod(); | ||
logger.error("RequestReaderInterceptor - Processing Data - method:{} ", method, method.getParameterCount()); | ||
|
||
int paramCount = method.getParameterCount(); | ||
Parameter[] parameters = method.getParameters(); | ||
Class[] clazzArray = method.getParameterTypes(); | ||
|
||
logger.error( | ||
"RequestReaderInterceptor - Processing Data - paramCount:{} , parameters:{}, clazzArray:{} , dataProcessingUtil:{}", | ||
paramCount, parameters, clazzArray, dataProcessingUtil); | ||
|
||
if (clazzArray != null && clazzArray.length > 0) { | ||
for (int i = 0; i < clazzArray.length; i++) { | ||
Class<?> clazz = clazzArray[i]; | ||
String propertyName = parameters[i].getName(); | ||
logger.error("propertyName:{}, clazz:{} , clazz.isPrimitive():{} ", propertyName, clazz, | ||
clazz.isPrimitive()); | ||
|
||
Object obj = ctxParameters[i]; | ||
String jsonStr = null; | ||
if (!clazz.isPrimitive()) { | ||
|
||
jsonStr = getJsonString(obj); | ||
logger.error("RequestReaderInterceptor final - obj - jsonStr:{} ", jsonStr); | ||
|
||
//validate Json | ||
//validateJson(jsonStr); | ||
|
||
performDataConversion(castObject(obj, clazz)); | ||
|
||
logger.error("RequestReaderInterceptor final - obj - obj:{} ", obj); | ||
|
||
} | ||
} | ||
} | ||
} | ||
|
||
private <T> T performDataConversion(T obj) { | ||
try { | ||
obj = dataProcessingUtil.encodeObjDataType(obj); | ||
logger.error("RequestReaderInterceptor - Data after encoding - obj:{} , obj.getClass():{}", obj, | ||
obj.getClass()); | ||
} catch (Exception ex) { | ||
logger.error("Exception while data conversion ", ex.getMessage()); | ||
} | ||
return obj; | ||
} | ||
|
||
private <T> String getJsonString(T obj) { | ||
String jsonStr = null; | ||
try { | ||
jsonStr = dataProcessingUtil.getJsonString(obj); | ||
logger.error("RequestReaderInterceptor - Object string - jsonStr:{}", jsonStr); | ||
} catch (Exception ex) { | ||
logger.error("Exception while data conversion ", ex.getMessage()); | ||
} | ||
return jsonStr; | ||
} | ||
|
||
private <T> T castObject(Object obj, Class<T> clazz) { | ||
T t = (T) clazz.cast(obj); | ||
return t; | ||
} | ||
|
||
private void validateJson(String jsonStr) throws JsonProcessingException { | ||
logger.error("\n\n\n validateJson() - jsonStr:{} ", jsonStr); | ||
JSONObject jsonObj = new JSONObject(jsonStr); | ||
logger.error("\n\n\n validateJson() - jsonObj:{} ", jsonObj); | ||
|
||
Map<String, Object> jsonObjMap = jsonObj.toMap(); | ||
logger.error("\n\n\n validateJson() - jsonObjMap:{} ", jsonObjMap); | ||
|
||
for (Map.Entry<String, Object> entry : jsonObjMap.entrySet()) { | ||
logger.error("validateJson() - entry.getKey():{}, entry.getValue():{}", entry.getKey(), entry.getValue()); | ||
|
||
if ( entry.getValue() instanceof Date) { | ||
logger.error("validateJson() - entry.getKey():{} is instanceof Date entry.getValue():{}", entry.getKey(), entry.getValue()); | ||
|
||
//encodeDate | ||
logger.error("\n\n\n validateJson() - Encoding date \n\n\n\n"); | ||
jsonObjMap.put(entry.getKey(), "31-12-2080"); | ||
} | ||
|
||
if (entry.getKey().equalsIgnoreCase("createdAt")) { | ||
logger.error("validateJson() - entry.getKey():{} is instanceof Date entry.getValue():{}", entry.getKey(), entry.getValue()); | ||
|
||
//encodeDate | ||
logger.error("\n\n\n validateJson() - Encoding date \n\n\n\n"); | ||
//logger.error("\n\n\n decodeTime(null, (String) entry.getValue():{} ", decodeTime(null, (Long) entry.getValue())); | ||
//jsonObjMap.put(entry.getKey(), "31-12-2080"); | ||
} | ||
} | ||
|
||
|
||
} | ||
|
||
public Date decodeTime(String baseDn, Long strDate) { | ||
log.error("Decode date value - baseDn:{}, strDate:{} ", baseDn, strDate); | ||
return persistenceEntryManager.decodeTime(baseDn, strDate.toString()); | ||
} | ||
|
||
} |
80 changes: 80 additions & 0 deletions
80
jans-config-api/server/src/main/java/io/jans/configapi/util/DataTypeConversionMapping.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package io.jans.configapi.core.util; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class DataTypeConversionMapping { | ||
|
||
/** | ||
* Name of the class to be used for DataType conversion | ||
*/ | ||
private String dataTypeConverterClassName; | ||
|
||
/** | ||
* Accepatable dateFormat | ||
*/ | ||
private String dateFormat; | ||
|
||
/** | ||
* Map of DataType and method to invoke for encoding | ||
*/ | ||
private Map<String, String> encoder; | ||
|
||
/** | ||
* Map of DataType and method to invoke for decoding | ||
*/ | ||
private Map<String, String> decoder; | ||
|
||
/** | ||
* Map of Class and attribute to be ignored for conversion | ||
*/ | ||
private Map<String, List<String>> exclusion; | ||
|
||
|
||
|
||
public String getDataTypeConverterClassName() { | ||
return dataTypeConverterClassName; | ||
} | ||
|
||
public void setDataTypeConverterClassName(String dataTypeConverterClassName) { | ||
this.dataTypeConverterClassName = dataTypeConverterClassName; | ||
} | ||
|
||
public String getDateFormat() { | ||
return dateFormat; | ||
} | ||
|
||
public void setDateFormat(String dateFormat) { | ||
this.dateFormat = dateFormat; | ||
} | ||
|
||
public Map<String, String> getEncoder() { | ||
return encoder; | ||
} | ||
|
||
public void setEncoder(Map<String, String> encoder) { | ||
this.encoder = encoder; | ||
} | ||
|
||
public Map<String, String> getDecoder() { | ||
return decoder; | ||
} | ||
|
||
public void setDecoder(Map<String, String> decoder) { | ||
this.decoder = decoder; | ||
} | ||
|
||
public Map<String, List<String>> getExclusion() { | ||
return exclusion; | ||
} | ||
|
||
public void setExclusion(Map<String, List<String>> exclusion) { | ||
this.exclusion = exclusion; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "DataTypeConversionMapping [dataTypeConverterClassName=" + dataTypeConverterClassName + ", dateFormat=" | ||
+ dateFormat + ", encoder=" + encoder + ", decoder=" + decoder + ", exclusion=" + exclusion + "]"; | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
...onfig-api/shared/src/main/java/io/jans/configapi/core/interceptor/RequestInterceptor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. | ||
* | ||
* Copyright (c) 2020, Janssen Project | ||
*/ | ||
|
||
package io.jans.configapi.core.interceptor; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
import jakarta.interceptor.InterceptorBinding; | ||
|
||
@InterceptorBinding | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target({ ElementType.TYPE, ElementType.METHOD }) | ||
public @interface RequestInterceptor { | ||
} |
Oops, something went wrong.