Fixed proxy instead of resource type in audit 61/40961/2
authorvempo <vitaliy.emporopulo@amdocs.com>
Wed, 4 Apr 2018 12:59:32 +0000 (15:59 +0300)
committerOren Kleks <orenkle@amdocs.com>
Sun, 8 Apr 2018 04:51:30 +0000 (04:51 +0000)
Change-Id: I1b3c22105f27e9d3dee0947815d32eb453a56831
Issue-ID: SDC-1190
Signed-off-by: vempo <vitaliy.emporopulo@amdocs.com>
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/main/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilter.java
openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java

index 06660f3..4985874 100644 (file)
@@ -19,6 +19,8 @@ package org.openecomp.sdc.logging.servlet.jaxrs;
 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER;
 import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER;
 
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.UUID;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ContainerRequestFilter;
@@ -26,6 +28,8 @@ import javax.ws.rs.container.ResourceInfo;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.ext.Provider;
 import org.openecomp.sdc.logging.api.ContextData;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
 import org.openecomp.sdc.logging.api.LoggingContext;
 import org.openecomp.sdc.logging.servlet.HttpHeader;
 
@@ -60,6 +64,8 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
 
     static final String START_TIME_KEY = "audit.start.time";
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingRequestFilter.class);
+
     private ResourceInfo resource;
 
     private HttpHeader requestIdHeader = new HttpHeader(DEFAULT_REQUEST_ID_HEADER);
@@ -79,6 +85,7 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
      * Configuration parameter for request ID HTTP header.
      */
     public void setRequestIdHeaders(String requestIdHeaders) {
+        LOGGER.debug("Valid request ID headers: {}", requestIdHeaders);
         this.requestIdHeader = new HttpHeader(requestIdHeaders.split(MULTI_VALUE_SEPARATOR));
     }
 
@@ -86,6 +93,7 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
      * Configuration parameter for partner name HTTP header.
      */
     public void setPartnerNameHeaders(String partnerNameHeaders) {
+        LOGGER.debug("Valid partner name headers: {}", partnerNameHeaders);
         this.partnerNameHeader = new HttpHeader(partnerNameHeaders.split(MULTI_VALUE_SEPARATOR));
     }
 
@@ -95,6 +103,12 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
         if (resource == null) {
             // JAX-RS could not find a mapping this response, probably due to HTTP 404 (not found),
             // 405 (method not allowed), 415 (unsupported media type), etc. with a message in Web server log
+
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("No matching resource was found for URI '{}' and method '{}'",
+                        containerRequestContext.getUriInfo().getPath(), containerRequestContext.getMethod());
+            }
+
             return;
         }
 
@@ -103,7 +117,7 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
         LoggingContext.clear();
 
         ContextData.ContextDataBuilder contextData = ContextData.builder();
-        contextData.serviceName(resource.getResourceClass().getName() + "." + resource.getResourceMethod().getName());
+        contextData.serviceName(getServiceName());
 
         String partnerName = partnerNameHeader.getAny(containerRequestContext::getHeaderString);
         if (partnerName != null) {
@@ -115,4 +129,50 @@ public class LoggingRequestFilter implements ContainerRequestFilter {
 
         LoggingContext.put(contextData.build());
     }
+
+    private String getServiceName() {
+
+        Class<?> resourceClass = resource.getResourceClass();
+        Method resourceMethod = resource.getResourceMethod();
+
+        if (Proxy.isProxyClass(resourceClass)) {
+            LOGGER.debug("Proxy class injected for JAX-RS resource");
+            return getServiceNameFromJavaProxy(resourceClass, resourceMethod);
+        }
+
+        return formatServiceName(resourceClass, resourceMethod);
+    }
+
+    private String getServiceNameFromJavaProxy(Class<?> proxyType, Method resourceMethod) {
+
+        for (Class<?> interfaceType : proxyType.getInterfaces()) {
+
+            if (isMatchingInterface(interfaceType, resourceMethod)) {
+                return formatServiceName(interfaceType, resourceMethod);
+            }
+        }
+
+        LOGGER.debug("Failed to find method '{}' in interfaces implemented by injected Java proxy", resourceMethod);
+        return formatServiceName(proxyType, resourceMethod);
+    }
+
+    private String formatServiceName(Class<?> resourceClass, Method resourceMethod) {
+        return resourceClass.getName() + "#" + resourceMethod.getName();
+    }
+
+    private boolean isMatchingInterface(Class<?> candidateType, Method requestedMethod) {
+
+        try {
+
+            Method candidate = candidateType.getDeclaredMethod(requestedMethod.getName(),
+                    requestedMethod.getParameterTypes());
+            return candidate != null;
+
+        } catch (NoSuchMethodException ignored) {
+            // ignore and move on to the next
+            LOGGER.debug("Failed to find method '{}' in interface '{}'", requestedMethod, candidateType);
+        }
+
+        return false;
+    }
 }
index 0e0be01..579f41c 100644 (file)
@@ -21,6 +21,7 @@ import static org.easymock.EasyMock.anyString;
 import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.START_TIME_KEY;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
 import java.util.UUID;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.container.ResourceInfo;
@@ -44,13 +45,19 @@ import org.testng.annotations.Test;
 @PrepareForTest({LoggingContext.class, ContextData.class})
 public class LoggingRequestFilterTest extends PowerMockTestCase {
 
-    private static final Class RESOURCE_CLASS = MockResource.class;
-    private static final Method RESOURCE_METHOD = MockResource.class.getDeclaredMethods()[0];
-    private static final String RESOURCE_NAME = RESOURCE_CLASS.getName() + "." + RESOURCE_METHOD.getName();
+    private static final Class DEFAULT_RESOURCE_CLASS = MockResource.class;
+    private static final Method DEFAULT_RESOURCE_METHOD = MockResource.class.getDeclaredMethods()[0];
+    private static final String DEFAULT_SERVICE_NAME =
+            formatServiceName(DEFAULT_RESOURCE_CLASS, DEFAULT_RESOURCE_METHOD);
 
     private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString();
+
     private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString();
 
+    private static String formatServiceName(Class resourceClass, Method resourceMethod) {
+        return resourceClass.getName() + "#" + resourceMethod.getName();
+    }
+
     /**
      * Verify all mocks after each test.
      */
@@ -74,9 +81,9 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
     }
 
     @Test
-    public void serviceNamePopulatedWhenThereIsMatchingResource() {
+    public void serviceNamePopulatedWhenThereIsMatchingResourceAndConcreteType() {
 
-        mockContextDataBuilder(null, RESOURCE_NAME, null);
+        mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, null);
         mockLoggingContext();
 
         LoggingRequestFilter filter = new LoggingRequestFilter();
@@ -87,10 +94,55 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
                 new PartnerHeader(null)));
     }
 
+    @Test
+    public void serviceNamePopulatedWhenThereIsMatchingResourceAndJavaProxyType() throws NoSuchMethodException {
+
+        Object proxyResource = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+                new Class<?>[] {MockResource.class}, (proxy, method, arguments) -> null);
+
+        final String serviceName = formatServiceName(MockResource.class, DEFAULT_RESOURCE_METHOD);
+
+        mockContextDataBuilder(null, serviceName, null);
+        mockLoggingContext();
+
+        LoggingRequestFilter filter = new LoggingRequestFilter();
+
+        Class<?> proxyClass = proxyResource.getClass();
+        Method proxyMethod =
+                proxyClass.getMethod(DEFAULT_RESOURCE_METHOD.getName(), DEFAULT_RESOURCE_METHOD.getParameterTypes());
+
+        filter.setResource(mockResource(proxyClass, proxyMethod));
+
+        filter.filter(mockContainerRequestContext(
+                new RequestIdHeader(null),
+                new PartnerHeader(null)));
+    }
+
+    @Test
+    public void serviceNameIncludesProxyClassnameWhenJavaProxyTypeAndNoMatchingInterface() {
+
+        Object proxyResource = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+                new Class<?>[] {Comparable.class}, (proxy, method, arguments) -> null);
+
+        final String serviceName = formatServiceName(proxyResource.getClass(), DEFAULT_RESOURCE_METHOD);
+
+        mockContextDataBuilder(null, serviceName, null);
+        mockLoggingContext();
+
+        LoggingRequestFilter filter = new LoggingRequestFilter();
+
+        Class<?> proxyClass = proxyResource.getClass();
+        filter.setResource(mockResource(proxyClass, DEFAULT_RESOURCE_METHOD));
+
+        filter.filter(mockContainerRequestContext(
+                new RequestIdHeader(null),
+                new PartnerHeader(null)));
+    }
+
     @Test
     public void partnerNamePopulatedWhenPresentInDefaultHeader() {
 
-        mockContextDataBuilder(null, RESOURCE_NAME, RANDOM_PARTNER_NAME);
+        mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, RANDOM_PARTNER_NAME);
         mockLoggingContext();
 
         LoggingRequestFilter filter = new LoggingRequestFilter();
@@ -105,7 +157,7 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
     public void partnerNamePopulatedWhenPresentInCustomHeader() {
 
         final String partnerHeader = "x-partner-header";
-        mockContextDataBuilder(null, RESOURCE_NAME, RANDOM_PARTNER_NAME);
+        mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, RANDOM_PARTNER_NAME);
         mockLoggingContext();
 
         LoggingRequestFilter filter = new LoggingRequestFilter();
@@ -120,7 +172,7 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
     @Test
     public void requestIdPopulatedWhenPresentInDefaultHeader() {
 
-        mockContextDataBuilder(RANDOM_REQUEST_ID, RESOURCE_NAME, null);
+        mockContextDataBuilder(RANDOM_REQUEST_ID, DEFAULT_SERVICE_NAME, null);
         mockLoggingContext();
 
         LoggingRequestFilter filter = new LoggingRequestFilter();
@@ -135,7 +187,7 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
     public void requestIdPopulatedWhenPresentInCustomHeader() {
 
         final String requestIdHeader = "x-request-id";
-        mockContextDataBuilder(RANDOM_REQUEST_ID, RESOURCE_NAME, null);
+        mockContextDataBuilder(RANDOM_REQUEST_ID, DEFAULT_SERVICE_NAME, null);
         mockLoggingContext();
 
         LoggingRequestFilter filter = new LoggingRequestFilter();
@@ -148,10 +200,14 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
     }
 
     private ResourceInfo mockResource() {
+        return mockResource(DEFAULT_RESOURCE_CLASS, DEFAULT_RESOURCE_METHOD);
+    }
+
+    private ResourceInfo mockResource(Class resourceType, Method resourceMethod) {
         ResourceInfo resource = EasyMock.mock(ResourceInfo.class);
         //noinspection unchecked
-        EasyMock.expect(resource.getResourceClass()).andReturn(RESOURCE_CLASS);
-        EasyMock.expect(resource.getResourceMethod()).andReturn(RESOURCE_METHOD);
+        EasyMock.expect(resource.getResourceClass()).andReturn(resourceType);
+        EasyMock.expect(resource.getResourceMethod()).andReturn(resourceMethod);
         EasyMock.replay(resource);
         return resource;
     }
@@ -252,11 +308,19 @@ public class LoggingRequestFilterTest extends PowerMockTestCase {
         }
     }
 
-    private static class MockResource {
+    private interface MockResource {
 
         @SuppressWarnings("EmptyMethod")
-        void process() {
+        void process();
+    }
+
+    private static class MockResourceImpl implements MockResource {
+
+        @Override
+        public void process() {
             // no-op
         }
     }
+
+
 }
\ No newline at end of file