wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jra...@apache.org
Subject svn commit: r1027712 [2/5] - in /incubator/wink/trunk: wink-client-apache-httpclient/ wink-client/ wink-common/ wink-common/src/main/java/org/apache/wink/common/internal/registry/ wink-common/src/main/resources/org/apache/wink/common/internal/i18n/ win...
Date Tue, 26 Oct 2010 19:52:56 GMT
Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/PopulateResponseMediaTypeHandler.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/PopulateResponseMediaTypeHandler.java?rev=1027712&r1=1027711&r2=1027712&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/PopulateResponseMediaTypeHandler.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/handlers/PopulateResponseMediaTypeHandler.java Tue Oct 26 19:52:54 2010
@@ -43,7 +43,7 @@ public class PopulateResponseMediaTypeHa
                                                         LoggerFactory
                                                             .getLogger(PopulateResponseMediaTypeHandler.class);
 
-    private static final MediaType APPLICATION_TYPE = new MediaType("application", "*"); //$NON-NLS-1$ //$NON-NLS-2$
+    private static final MediaType APPLICATION_TYPE = new MediaType("application", "*");                       //$NON-NLS-1$ //$NON-NLS-2$
 
     private boolean                errorFlow        = false;
 
@@ -52,15 +52,19 @@ public class PopulateResponseMediaTypeHa
         MediaType responseMediaType = null;
         Object result = context.getResponseEntity();
 
+        boolean debug = logger.isDebugEnabled();
+
         if (result == null) {
-            logger.trace("No entity so no Content-Type needs to be set"); //$NON-NLS-1$
+            if (debug)
+                logger.trace("No entity so no Content-Type needs to be set"); //$NON-NLS-1$
             return;
         }
 
         if (result instanceof Response) {
             Response response = (Response)result;
             if (response.getEntity() == null) {
-                logger.trace("No entity so no Content-Type needs to be set"); //$NON-NLS-1$
+                if (debug)
+                    logger.trace("No entity so no Content-Type needs to be set"); //$NON-NLS-1$
                 return;
             }
 
@@ -72,8 +76,9 @@ public class PopulateResponseMediaTypeHa
                 } else {
                     responseMediaType = MediaType.valueOf(first.toString());
                 }
-                logger.trace("Content-Type was set by application to {}", responseMediaType); //$NON-NLS-1$
             }
+            if (debug)
+                logger.trace("Content-Type was set by application to {}", responseMediaType); //$NON-NLS-1$
         }
 
         if (responseMediaType == null) {
@@ -82,7 +87,9 @@ public class PopulateResponseMediaTypeHa
             if (searchResult != null && searchResult.isFound()) {
                 MethodMetadata methodMetadata = searchResult.getMethod().getMetadata();
                 producedMime = methodMetadata.getProduces();
-                logger.trace("Determining Content-Type from @Produces on method: {}", producedMime); //$NON-NLS-1$
+                if (debug)
+                    logger
+                        .trace("Determining Content-Type from @Produces on method: {}", producedMime); //$NON-NLS-1$
             }
             if (producedMime == null || producedMime.isEmpty()) {
                 if (result instanceof Response) {
@@ -90,24 +97,30 @@ public class PopulateResponseMediaTypeHa
                     producedMime =
                         context.getAttribute(ProvidersRegistry.class)
                             .getMessageBodyWriterMediaTypes(response.getEntity().getClass());
+                    if (debug)
+                        logger
+                            .trace("Determining Content-Type from compatible generic type to {} from MessageBodyWriters: {}", //$NON-NLS-1$
+                                   response.getEntity().getClass(),
+                                   producedMime);
                 } else {
                     producedMime =
                         context.getAttribute(ProvidersRegistry.class)
                             .getMessageBodyWriterMediaTypes(result.getClass());
+                    if (debug)
+                        logger
+                            .trace("Determining Content-Type from compatible generic type to {} from MessageBodyWriters: {}", //$NON-NLS-1$
+                                   result.getClass(),
+                                   producedMime);
                 }
                 /*
                  * This is to inform the application developer that they should
                  * specify the Content-Type.
                  */
-                if (logger.isInfoEnabled()) {
+                if (debug) {
                     logger
-                        .info(Messages
+                        .debug(Messages
                             .getMessage("populateResponseMediaTypeHandlerFromCompatibleMessageBodyWriters")); //$NON-NLS-1$
                 }
-                logger
-                    .trace("Determining Content-Type from compatible generic type to {} from MessageBodyWriters: {}", //$NON-NLS-1$
-                           result.getClass(),
-                           producedMime);
             }
             if (producedMime.isEmpty()) {
                 producedMime.add(MediaType.WILDCARD_TYPE);
@@ -120,7 +133,8 @@ public class PopulateResponseMediaTypeHa
             List<CandidateMediaType> candidates = new LinkedList<CandidateMediaType>();
             for (MediaType acceptableMediaType : acceptableMediaTypes) {
                 for (MediaType mediaType : producedMime) {
-                    logger.trace("Comparing {} to {}", acceptableMediaType, mediaType); //$NON-NLS-1$
+                    if (debug)
+                        logger.trace("Comparing {} to {}", acceptableMediaType, mediaType); //$NON-NLS-1$
                     if (mediaType.isCompatible(acceptableMediaType)) {
                         MediaType candidateMediaType = null;
                         if (MediaTypeUtils.compareTo(mediaType, acceptableMediaType) > 0) {
@@ -128,13 +142,14 @@ public class PopulateResponseMediaTypeHa
                         } else {
                             candidateMediaType = acceptableMediaType;
                         }
-                        logger.trace("MediaType compatible so using candidate type {}", //$NON-NLS-1$
-                                     candidateMediaType);
+                        if (debug)
+                            logger.trace("MediaType compatible so using candidate type {}", //$NON-NLS-1$
+                                         candidateMediaType);
                         String q = acceptableMediaType.getParameters().get("q"); //$NON-NLS-1$
                         CandidateMediaType candidate =
                             new CandidateMediaType(candidateMediaType, q);
                         if (Double.compare(candidate.q, 0.0) != 0) {
-                            if (logger.isTraceEnabled()) {
+                            if (debug) {
                                 logger
                                     .trace("Candidate {} has q value {} so adding to possible candidates", //$NON-NLS-1$
                                            candidate.getMediaType(),
@@ -149,13 +164,13 @@ public class PopulateResponseMediaTypeHa
             // there are no candidates
             if (candidates.isEmpty()) {
                 if (isErrorFlow()) {
-                    logger.trace("Error flow and no candidates so not going to set a Content-Type"); //$NON-NLS-1$
+                    if (debug)
+                        logger
+                            .trace("Error flow and no candidates so not going to set a Content-Type"); //$NON-NLS-1$
                     return;
                 }
-                if (logger.isInfoEnabled()) {
-                    logger.info(Messages
-                        .getMessage("populateResponseMediaTypeHandlerNoAcceptableResponse")); //$NON-NLS-1$
-                }
+                logger.info(Messages
+                    .getMessage("populateResponseMediaTypeHandlerNoAcceptableResponse")); //$NON-NLS-1$
                 throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE);
             }
 
@@ -167,7 +182,7 @@ public class PopulateResponseMediaTypeHa
             for (CandidateMediaType candidate : candidates) {
                 if (max == null) {
                     max = candidate;
-                    if (logger.isTraceEnabled()) {
+                    if (debug) {
                         logger.trace("No previous best candidate so using candidate {}", max //$NON-NLS-1$
                             .getMediaType());
                     }
@@ -179,14 +194,14 @@ public class PopulateResponseMediaTypeHa
                         MediaTypeUtils.compareTo(candidate.getMediaType(), max.getMediaType());
                     if (comparison > 0) {
                         max = candidate;
-                        if (logger.isTraceEnabled()) {
+                        if (debug) {
                             logger
                                 .trace("Best candidate is now {} because it was a more specific media type", //$NON-NLS-1$
                                        max.getMediaType());
                         }
                     } else if (comparison == 0 && candidate.getQ() > max.getQ()) {
                         max = candidate;
-                        if (logger.isTraceEnabled()) {
+                        if (debug) {
                             logger
                                 .trace("Best candidate is now {} because it had a higher quality value {} compared to {} with quality value {}", //$NON-NLS-1$
                                        new Object[] {max.getMediaType(), max.getQ(), candidate,
@@ -197,9 +212,10 @@ public class PopulateResponseMediaTypeHa
 
                 if (!useOctetStream && (candidate.getMediaType().equals(MediaType.WILDCARD_TYPE) || candidate
                     .getMediaType().equals(APPLICATION_TYPE))) {
-                    logger
-                        .trace("If necessary, use an application/octet-stream because there is a wildcard: {}", //$NON-NLS-1$
-                               candidate.getMediaType());
+                    if (debug)
+                        logger
+                            .trace("If necessary, use an application/octet-stream because there is a wildcard", //$NON-NLS-1$
+                                   candidate.getMediaType());
                     useOctetStream = true;
                 }
             }
@@ -207,23 +223,24 @@ public class PopulateResponseMediaTypeHa
             if (max.getMediaType().isWildcardSubtype() == false) {
                 responseMediaType = max.getMediaType();
             } else if (useOctetStream) {
-                logger
-                    .trace("Content-Type was reset to application/octet-stream because it was either */* or was application/*"); //$NON-NLS-1$
+                if (debug)
+                    logger
+                        .trace("Content-Type was reset to application/octet-stream because it was either */* or was application/*"); //$NON-NLS-1$
                 responseMediaType = MediaType.APPLICATION_OCTET_STREAM_TYPE;
             } else {
                 if (isErrorFlow()) {
-                    logger.trace("Error flow so not going to set a response Content-Type"); //$NON-NLS-1$
+                    if (debug)
+                        logger.trace("Error flow so not going to set a response Content-Type"); //$NON-NLS-1$
                     return;
                 }
-                if (logger.isInfoEnabled()) {
-                    logger.info(Messages
-                        .getMessage("populateResponseMediaTypeHandlerNoAcceptableResponse")); //$NON-NLS-1$
-                }
+                logger.info(Messages
+                    .getMessage("populateResponseMediaTypeHandlerNoAcceptableResponse")); //$NON-NLS-1$
                 throw new WebApplicationException(Response.Status.NOT_ACCEPTABLE);
             }
 
         }
-        logger.trace("Response Content-Type will be set to {}", responseMediaType); //$NON-NLS-1$
+        if (debug)
+            logger.trace("Response Content-Type will be set to {}", responseMediaType); //$NON-NLS-1$
         context.setResponseMediaType(responseMediaType);
     }
 

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/LogUtilities.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/LogUtilities.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/LogUtilities.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/LogUtilities.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,238 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.lang.reflect.Method;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.registry.metadata.ClassMetadata;
+import org.apache.wink.common.internal.registry.metadata.MethodMetadata;
+import org.apache.wink.server.internal.registry.ResourceRecord;
+import org.apache.wink.server.internal.registry.SubResourceRecord;
+import org.slf4j.Logger;
+
+public class LogUtilities {
+
+    /*
+     * break the table into rows of BREAK_POINT. this may eliminate the
+     * accumulation of a massive string (i.e. thousands of resources)
+     */
+    static final int BREAK_POINT = 20;
+
+    private LogUtilities() {
+        /* do nothing */
+    }
+
+    static String constructMethodString(Method javaMethod) {
+        if (javaMethod == null) {
+            return "";
+        }
+        StringBuffer methodName = new StringBuffer();
+        methodName.append(javaMethod.getName());
+        boolean isFirst = true;
+        methodName.append("(");
+        for (Class<?> paramTypes : javaMethod.getParameterTypes()) {
+            if (!isFirst) {
+                methodName.append(",");
+            } else {
+                isFirst = false;
+            }
+            methodName.append(paramTypes.getSimpleName());
+        }
+        methodName.append(")");
+        return methodName.toString();
+    }
+
+    static String constructMediaTypeString(Set<MediaType> mtSet) {
+        if (mtSet == null || mtSet.isEmpty()) {
+            return "[*/*]";
+        }
+        return mtSet.toString();
+    }
+
+    public static void logResourceMetadata(List<ResourceRecord> resourceRecords,
+                                        Logger logger,
+                                        boolean isTrace,
+                                        boolean isLogForOneResource) {
+        StringBuffer sb = new StringBuffer();
+        Formatter f = new Formatter(sb);
+        f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s",
+                 "Path",
+                 "HTTP Method",
+                 "Consumes",
+                 "Produces",
+                 "Resource Method");
+
+        int counter = 0;
+        for (ResourceRecord record : resourceRecords) {
+            try {
+                final String resourceClassName = record.getMetadata().getResourceClass().getName();
+                final ClassMetadata resourceMetadata = record.getMetadata();
+                final String resourcePath = resourceMetadata.getPath();
+                for (MethodMetadata methodMetadata : resourceMetadata.getResourceMethods()) {
+                    ++counter;
+                    try {
+                        String path = resourcePath;
+                        String httpMethod = methodMetadata.getHttpMethod();
+
+                        String consumes = constructMediaTypeString(methodMetadata.getConsumes());
+                        String produces = constructMediaTypeString(methodMetadata.getProduces());
+
+                        String methodName =
+                            constructMethodString(methodMetadata.getReflectionMethod());
+
+                        /* path is null so regular resource method */
+                        f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s.%6$s",
+                                 path,
+                                 httpMethod,
+                                 consumes,
+                                 produces,
+                                 resourceClassName,
+                                 methodName);
+                    } catch (Exception e) {
+                        logger.trace("Could not print the entire method metadata for {}",
+                                     resourceClassName,
+                                     e);
+                    }
+
+                    if (counter % LogUtilities.BREAK_POINT == 0) {
+                        if (isTrace) {
+                            if (isLogForOneResource) {
+                                logger
+                                    .trace("Resource information for {}:{}", resourceMetadata.getResourceClass().getName(), sb); //$NON-NLS-1$
+                            } else {
+                                logger.trace(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                            }
+                        } else {
+                            if (isLogForOneResource) {
+                                logger
+                                    .debug("Resource information for {}:{}", resourceMetadata.getResourceClass().getName(), sb); //$NON-NLS-1$
+                            } else {
+                                logger.debug(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                            }
+                        }
+                        sb = new StringBuffer();
+                        f = new Formatter(sb);
+                        f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s",
+                                 "Path",
+                                 "HTTP Method",
+                                 "Consumes",
+                                 "Produces",
+                                 "Resource Method");
+                    }
+                }
+
+                for (SubResourceRecord subResourceRecord : record.getSubResourceRecords()) {
+                    ++counter;
+
+                    try {
+                        MethodMetadata method = subResourceRecord.getMetadata();
+
+                        StringBuilder path = new StringBuilder(resourcePath);
+                        if (!resourcePath.endsWith("/")) {
+                            path.append("/");
+                        }
+                        path.append(method.getPath());
+
+                        String httpMethod = method.getHttpMethod();
+                        if (httpMethod == null) {
+                            httpMethod = "(Sub-Locator)";
+                        }
+
+                        String consumes = constructMediaTypeString(method.getConsumes());
+                        String produces = constructMediaTypeString(method.getProduces());
+
+                        String methodName = constructMethodString(method.getReflectionMethod());
+
+                        f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s.%6$s",
+                                 path,
+                                 httpMethod,
+                                 consumes,
+                                 produces,
+                                 resourceClassName,
+                                 methodName);
+                    } catch (Exception e) {
+                        logger.trace("Could not print the entire method metadata for {}",
+                                     resourceClassName,
+                                     e);
+                    }
+
+                    if (counter % LogUtilities.BREAK_POINT == 0) {
+                        if (isTrace) {
+                            if (isLogForOneResource) {
+                                logger
+                                    .trace("Resource information for {}:{}", resourceMetadata.getResourceClass().getName(), sb); //$NON-NLS-1$
+                            } else {
+                                logger.trace(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                            }
+                        } else {
+                            if (isLogForOneResource) {
+                                logger
+                                    .debug("Resource information for {}:{}", resourceMetadata.getResourceClass().getName(), sb); //$NON-NLS-1$
+                            } else {
+                                logger.debug(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                            }
+                        }
+                        sb = new StringBuffer();
+                        f = new Formatter(sb);
+                        f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s",
+                                 "Path",
+                                 "HTTP Method",
+                                 "Consumes",
+                                 "Produces",
+                                 "Resource Method");
+                    }
+                }
+            } catch (Exception e) {
+                logger.trace("Could not print the entire resource metadata", e);
+            }
+        }
+
+        if (counter % LogUtilities.BREAK_POINT != 0) {
+            if (isTrace) {
+                if (isLogForOneResource) {
+                    logger
+                        .trace("Resource information for {}:{}", resourceRecords.get(0).getMetadata().getResourceClass().getName(), sb); //$NON-NLS-1$
+                } else {
+                    logger.trace(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                }
+            } else {
+                if (isLogForOneResource) {
+                    logger
+                        .debug("Resource information for {}:{}", resourceRecords.get(0).getMetadata().getResourceClass().getName(), sb); //$NON-NLS-1$
+                } else {
+                    logger.debug(Messages.getMessage("registeredResources", sb)); //$NON-NLS-1$
+                }
+            }
+            sb = new StringBuffer();
+            f = new Formatter(sb);
+            f.format("%n%1$-80s %2$-13s %3$-20s %4$-20s %5$s",
+                     "Path",
+                     "HTTP Method",
+                     "Consumes",
+                     "Produces",
+                     "Resource Method");
+        }
+    }
+}

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Providers.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Providers.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Providers.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Providers.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.util.Formatter;
+import java.util.List;
+
+import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.registry.ProvidersRegistry;
+import org.apache.wink.common.internal.registry.ProvidersRegistry.ProviderRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs the provider information.
+ */
+public class Providers {
+    private static final String     CUSTOM                       = "Custom?";
+
+    private static final String     CONSUMES_MEDIA_TYPE          = "Consumes Media Type";
+
+    private static final String     PRODUCES_MEDIA_TYPE          = "Produces Media Type";
+
+    private static final String     PROVIDER_FORMAT_LINE         = "%n%1$-35s %2$-25s %3$-8s %4$s";
+    
+    private static final String     EXCEPTION_MAPPER_FORMAT_LINE = "%n%1$-25s %2$-8s %3$s";
+    
+    private static final String     PROVIDER_CLASS               = "Provider Class";
+
+    private static final String     GENERIC_TYPE                 = "Generic Type";
+
+    /*
+     * break the table into rows of BREAK_POINT. this may eliminate the
+     * accumulation of a massive string (i.e. thousands of resources)
+     */
+    private static final int        BREAK_POINT                  = 20;
+
+    private static final Logger     logger                       =
+                                                                     LoggerFactory
+                                                                         .getLogger(Providers.class);
+
+    private final ProvidersRegistry providersRegistry;
+
+    public Providers(ProvidersRegistry providersRegistry) {
+        this.providersRegistry = providersRegistry;
+    }
+
+    public void log() {
+        try {
+            if (logger.isInfoEnabled()) {
+                boolean isProviderDefined = false;
+
+                /*
+                 * readers
+                 */
+                List<ProviderRecord<?>> providerRecords =
+                    providersRegistry.getMessageBodyReaderRecords();
+                boolean temp = log(providerRecords, "MessageBodyReader");
+                if (temp) {
+                    isProviderDefined = true;
+                }
+
+                /*
+                 * writers
+                 */
+                providerRecords = providersRegistry.getMessageBodyWriterRecords();
+                temp = log(providerRecords, "MessageBodyWriter");
+                if (temp) {
+                    isProviderDefined = true;
+                }
+
+                /*
+                 * exception mappers
+                 */
+                providerRecords = providersRegistry.getExceptionMapperRecords();
+                temp = log(providerRecords);
+                if (temp) {
+                    isProviderDefined = true;
+                }
+
+                /*
+                 * context resolvers
+                 */
+                providerRecords = providersRegistry.getContextResolverRecords();
+                temp = log(providerRecords, "ContextResolver");
+                if (temp) {
+                    isProviderDefined = true;
+                }
+
+                /*
+                 * debug or more
+                 */
+                if (isProviderDefined && logger.isDebugEnabled()) {
+                    logTable();
+                }
+
+                if (!isProviderDefined) {
+                    logger.info(Messages.getMessage("noJAXRSApplicationDefinedProviders"));
+                }
+            }
+        } catch (Exception e) {
+            logger.trace("Could not print the entire providers metadata", e);
+        }
+    }
+
+    private boolean log(List<ProviderRecord<?>> records, String providerType) {
+        if (records != null && !records.isEmpty()) {
+            for (ProviderRecord<?> record : records) {
+                if (record.getGenericType() == null || Object.class.equals(record.getGenericType())) {
+                    logger.info(Messages
+                        .getMessage("registeredJAXRSProviderWithMediaTypeAndAllGenericType", record
+                            .getProviderClass().getName(), providerType, record.getMediaType()));
+                } else {
+                    logger.info(Messages.getMessage("registeredJAXRSProviderWithMediaType", record
+                        .getProviderClass().getName(), providerType, record.getGenericType()
+                        .getName(), record.getMediaType()));
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private boolean log(List<ProviderRecord<?>> records) {
+        if (records != null && !records.isEmpty()) {
+            for (ProviderRecord<?> record : records) {
+                if (record.getGenericType() == null || Object.class.equals(record.getGenericType())) {
+                    logger.info(Messages
+                        .getMessage("registeredJAXRSProviderWithoutMediaTypeAndAllGenericType",
+                                    record.getProviderClass().getName(),
+                                    "ExceptionMapper"));
+                } else {
+                    logger.info(Messages.getMessage("registeredJAXRSProviderWithoutMediaType",
+                                                    record.getProviderClass().getName(),
+                                                    "ExceptionMapper",
+                                                    record.getGenericType().getName()));
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    private void log(List<ProviderRecord<?>> providerRecords,
+                     String providerType,
+                     String mediaTypeHeader) {
+        StringBuffer sb = new StringBuffer();
+
+        if (!providerRecords.isEmpty()) {
+            Formatter f = new Formatter(sb);
+            f.format(PROVIDER_FORMAT_LINE, mediaTypeHeader, GENERIC_TYPE, CUSTOM, PROVIDER_CLASS);
+
+            int counter = 0;
+
+            for (ProviderRecord<?> record : providerRecords) {
+                ++counter;
+                f.format(PROVIDER_FORMAT_LINE, record.getMediaType(), record.getGenericType()
+                    .getSimpleName(), !record.isSystemProvider(), record.getProviderClass()
+                    .getName());
+
+                if (counter % BREAK_POINT == 0) {
+                    logger.debug("The following JAX-RS {} providers are registered:{}",
+                                 providerType,
+                                 sb);
+                    sb = new StringBuffer();
+                    f = new Formatter(sb);
+                    f.format(PROVIDER_FORMAT_LINE,
+                             mediaTypeHeader,
+                             GENERIC_TYPE,
+                             CUSTOM,
+                             PROVIDER_CLASS);
+                }
+            }
+
+            if (counter % BREAK_POINT != 0) {
+                logger.debug("The following JAX-RS {} providers are registered:{}",
+                             providerType,
+                             sb);
+            }
+        }
+    }
+
+    private void logExceptionMapper(List<ProviderRecord<?>> providerRecords) {
+        StringBuffer sb = new StringBuffer();
+
+        if (!providerRecords.isEmpty()) {
+            Formatter f = new Formatter(sb);
+            f.format(EXCEPTION_MAPPER_FORMAT_LINE, GENERIC_TYPE, CUSTOM, PROVIDER_CLASS);
+            int counter = 0;
+            for (ProviderRecord<?> record : providerRecords) {
+                ++counter;
+
+                f.format(EXCEPTION_MAPPER_FORMAT_LINE,
+                         record.getGenericType().getSimpleName(),
+                         !record.isSystemProvider(),
+                         record.getProviderClass().getName());
+
+                if (counter % BREAK_POINT == 0) {
+                    logger.debug("The following JAX-RS {} providers are registered:{}",
+                                 "ExceptionMapper",
+                                 sb);
+                    sb = new StringBuffer();
+                    f = new Formatter(sb);
+                    f.format(EXCEPTION_MAPPER_FORMAT_LINE, GENERIC_TYPE, CUSTOM, PROVIDER_CLASS);
+                }
+            }
+
+            if (counter % BREAK_POINT != 0) {
+                logger.debug("The following JAX-RS {} providers are registered:{}",
+                             "ExceptionMapper",
+                             sb);
+            }
+        }
+    }
+
+    private void logTable() {
+        List<ProviderRecord<?>> providerRecords = providersRegistry.getMessageBodyReaderRecords();
+        log(providerRecords, "MessageBodyReader", CONSUMES_MEDIA_TYPE);
+
+        providerRecords = providersRegistry.getMessageBodyWriterRecords();
+        log(providerRecords, "MessageBodyWriter", PRODUCES_MEDIA_TYPE);
+
+        providerRecords = providersRegistry.getExceptionMapperRecords();
+        logExceptionMapper(providerRecords);
+
+        providerRecords = providersRegistry.getContextResolverRecords();
+        log(providerRecords, "ContextResolver", PRODUCES_MEDIA_TYPE);
+    }
+}

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Requests.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Requests.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Requests.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Requests.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.wink.server.handlers.HandlersChain;
+import org.apache.wink.server.handlers.MessageContext;
+import org.apache.wink.server.handlers.RequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs the incoming requests from client to server. This will log the headers
+ * plus the containers.
+ */
+public class Requests implements RequestHandler {
+
+    final private static Logger  logger             = LoggerFactory.getLogger(Requests.class);
+
+    final private static int     BREAK_POINT        =
+                                                        Integer
+                                                            .valueOf(System
+                                                                .getProperty(Requests.class
+                                                                                 .getName() + ".breakPoint",
+                                                                             "4096")).intValue();
+
+    final private static boolean IS_LOGGED_AS_BYTES =
+                                                        Boolean
+                                                            .valueOf(System
+                                                                .getProperty(Requests.class
+                                                                                 .getName() + ".logAsBytes",
+                                                                             "false"))
+                                                            .booleanValue();
+
+    final private static int     BUFFER_SIZE        =
+                                                        Integer
+                                                            .valueOf(System
+                                                                .getProperty(Requests.class
+                                                                                 .getName() + ".bufferSize",
+                                                                             "8192")).intValue();
+
+    public void init(Properties props) {
+        /* do nothing */
+    }
+
+    public void handleRequest(MessageContext context, HandlersChain chain) throws Throwable {
+        logger.trace("handleRequest({}, {}) entry", context, chain);
+        try {
+            if (logger.isDebugEnabled()) {
+                logStartRequest(context);
+            }
+            chain.doChain(context);
+        } finally {
+            if (logger.isDebugEnabled()) {
+                logFinishRequest(context);
+            }
+        }
+        logger.trace("handleRequest({}, {}) exit", context, chain);
+    }
+
+    void logStartRequest(MessageContext context) {
+        logger.trace("logStartRequest() entry");
+        try {
+            if (!logger.isDebugEnabled()) {
+                logger.trace("logStartRequest() exit"); // how would this ever
+                // occur?
+                return;
+            }
+            
+            /*
+             * start wrapping the InputStream here in the hope that it will be
+             * called during logFinishRequest
+             */
+            HttpServletRequestWrapper request =
+                context.getAttribute(HttpServletRequestWrapper.class);
+            if (request == null) {
+                logger.debug("Could not find the HTTP Servlet Request to wrap.");
+                // this is a really bad path that should probably be an error,
+                // but just in case
+                logger.trace("logStartRequest() exit");
+                return;
+            }
+            
+            logger.debug("Request URI is " + context.getUriInfo().getRequestUri().toASCIIString());
+            HttpHeaders headers = context.getHttpHeaders();
+            MultivaluedMap<String, String> headersMap = headers.getRequestHeaders();
+            String headersString = "{";
+            for(String key : headersMap.keySet()) {
+                headersString += (key + "=" + headersMap.get(key) + ",");
+            }
+            if(headersString.length() > 1)
+                headersString = headersString.substring(0, headersString.length() -1);
+            headersString += "}";
+            logger.debug("HTTP Headers are " + headersString);
+            
+            RequestWrapper wrapper = new RequestWrapper(request);
+            context.setAttribute(RequestWrapper.class, wrapper);
+            context.setAttribute(HttpServletRequest.class, wrapper);
+            context.setAttribute(HttpServletRequestWrapper.class, wrapper);
+        } catch (Exception e) {
+            logger.trace("Could not log the start of the request", e);
+        }
+        logger.trace("logStartRequest() exit");
+    }
+
+    void logFinishRequest(MessageContext context) {
+        logger.trace("logFinishRequest() entry");
+        try {
+            if (!logger.isDebugEnabled()) {
+                logger.trace("logFinishRequest() exit"); // how would this ever
+                // occur?
+                return;
+            }
+            RequestWrapper requestWrapper = context.getAttribute(RequestWrapper.class);
+            if (requestWrapper == null) {
+                logger.debug("Did not find the RequestWrapper so will not log the request entity.");
+                logger.trace("logStartRequest() exit");
+                return;
+            }
+            LoggedServletInputStream loggedInputStream = requestWrapper.getLoggedInputStream();
+            if (loggedInputStream == null || loggedInputStream.getLoggedByteBufferLength() == 0) {
+                logger
+                    .debug("The request entity was not read from the HttpServletRequest.getInputStream().");
+                return;
+            }
+            byte[] buffer = loggedInputStream.getLoggedByteBuffer();
+            final int bufferLength = loggedInputStream.getLoggedByteBufferLength();
+
+            if (IS_LOGGED_AS_BYTES) {
+                logger.debug("The request entity as bytes:");
+                StringBuffer sb = new StringBuffer();
+                int outputCount = 0;
+
+                for (int count = 0; count < bufferLength; ++count) {
+                    sb.append(String.format("%#04x ", buffer[count]));
+                    sb.append(" ");
+                    ++outputCount;
+                    if (outputCount > BREAK_POINT) {
+                        /*
+                         * 100KB increments
+                         */
+                        logger.debug("{}", sb);
+                        sb = new StringBuffer();
+                        outputCount = 0;
+                    }
+                }
+                if (outputCount > 0) {
+                    logger.debug("{}", sb);
+                    sb = new StringBuffer();
+                }
+            } else {
+                logger.debug("The request entity as a String in the default encoding:");
+                int offset = 0;
+                while (offset < bufferLength) {
+                    int length = bufferLength - offset;
+                    if (length > BREAK_POINT) {
+                        length = BREAK_POINT;
+                    }
+                    String str = new String(buffer, offset, length);
+                    logger.debug("{}", str);
+                    offset += length;
+                }
+            }
+            /*
+             * remove it in case during a Response chain, an exception is thrown
+             * and then a Request needs to be logged again. so only 1 shot at
+             * logging a request.
+             */
+            context.setAttribute(RequestWrapper.class, null);
+        } catch (Exception e) {
+            logger.debug("Could not log the finishing of the request", e);
+        }
+        logger.trace("logFinishRequest() exit");
+    }
+
+    public static class RequestWrapper extends HttpServletRequestWrapper {
+        final private HttpServletRequest request;
+
+        private LoggedServletInputStream inputStreamLogger            = null;
+
+        private ServletInputStream       originalStream;
+        private boolean                  hasStreamBeenRetrievedBefore = false;
+
+        public RequestWrapper(HttpServletRequest request) {
+            super(request);
+            this.request = request;
+        }
+
+        @Override
+        public ServletInputStream getInputStream() throws IOException {
+            if (inputStreamLogger != null) {
+                return inputStreamLogger;
+            }
+
+            if (!hasStreamBeenRetrievedBefore) {
+                originalStream = request.getInputStream();
+            }
+            if (originalStream == null) {
+                /*
+                 * this could happen in a weird situation with the web
+                 * container. defensive coding for now.
+                 */
+                logger
+                    .debug("The web container did not return a stream from HttpServletRequest.getInputStream()");
+                return null;
+            }
+
+            inputStreamLogger = new LoggedServletInputStream(originalStream, BUFFER_SIZE);
+            return inputStreamLogger;
+        }
+
+        public LoggedServletInputStream getLoggedInputStream() {
+            return inputStreamLogger;
+        }
+    }
+
+    /**
+     * A wrapper class for a ServletInputStream that also logs the bytes.
+     */
+    public static class LoggedServletInputStream extends ServletInputStream {
+
+        final private ServletInputStream originalRequest;
+
+        private final byte[]             requestBuffer;
+
+        private int                      offset = 0;
+
+        public LoggedServletInputStream(ServletInputStream originalRequest, int bufferSize) {
+            this.originalRequest = originalRequest;
+            requestBuffer = new byte[bufferSize];
+        }
+
+        @Override
+        public int available() throws IOException {
+            return originalRequest.available();
+        }
+
+        @Override
+        public void close() throws IOException {
+            originalRequest.close();
+        }
+
+        @Override
+        public void mark(int readlimit) {
+            originalRequest.mark(readlimit);
+        }
+
+        @Override
+        public boolean markSupported() {
+            return originalRequest.markSupported();
+        }
+
+        @Override
+        public int read() throws IOException {
+            int value = originalRequest.read();
+
+            if (value < 0) {
+                return value;
+            }
+
+            if (offset < requestBuffer.length - 1) {
+                requestBuffer[offset] = (byte)value;
+                ++offset;
+            }
+            return value;
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            int value = originalRequest.read(b);
+
+            if (value < 0) {
+                return value;
+            }
+
+            int diff = value;
+            if (offset + value > requestBuffer.length) {
+                diff = requestBuffer.length - offset;
+            }
+
+            if (diff > 0) {
+                System.arraycopy(b, 0, requestBuffer, offset, diff);
+                offset += diff;
+            }
+            return value;
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            int value = originalRequest.read(b, off, len);
+
+            if (value < 0) {
+                return value;
+            }
+
+            int diff = value;
+            if (offset + value > requestBuffer.length) {
+                diff = requestBuffer.length - offset;
+            }
+
+            if (diff > 0) {
+                System.arraycopy(b, off, requestBuffer, offset, diff);
+                offset += diff;
+            }
+
+            return value;
+        }
+
+        @Override
+        public int readLine(byte[] b, int off, int len) throws IOException {
+            int value = originalRequest.readLine(b, off, len);
+
+            if (value < 0) {
+                return value;
+            }
+
+            int diff = value;
+            if (offset + value > requestBuffer.length) {
+                diff = requestBuffer.length - offset;
+            }
+
+            if (diff > 0) {
+                System.arraycopy(b, off, requestBuffer, offset, diff);
+                offset += diff;
+            }
+
+            return value;
+        }
+
+        @Override
+        public void reset() throws IOException {
+            originalRequest.reset();
+        }
+
+        @Override
+        public long skip(long n) throws IOException {
+            return originalRequest.skip(n);
+        }
+
+        public byte[] getLoggedByteBuffer() {
+            return requestBuffer;
+        }
+
+        public int getLoggedByteBufferLength() {
+            return offset;
+        }
+
+    }
+}

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/ResourceInvocation.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/ResourceInvocation.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/ResourceInvocation.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/ResourceInvocation.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.wink.common.internal.registry.metadata.MethodMetadata;
+import org.apache.wink.server.handlers.HandlersChain;
+import org.apache.wink.server.handlers.MessageContext;
+import org.apache.wink.server.handlers.RequestHandler;
+import org.apache.wink.server.internal.handlers.SearchResult;
+import org.apache.wink.server.internal.registry.ResourceInstance;
+import org.apache.wink.server.internal.registry.ResourceRecord;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs the resource invocation as it goes through each level (i.e. sub-resource
+ * locator) in a table in DEBUG mode. Logs the resource metadata for each level
+ * in TRACE mode.
+ */
+public class ResourceInvocation implements RequestHandler {
+
+    public static class ResourceInvocationData {
+        private List<ResourceRecord> resourceMetadata = new ArrayList<ResourceRecord>();
+
+        private List<MethodMetadata> methodMeta       = new ArrayList<MethodMetadata>();
+
+        public List<ResourceRecord> getResourceMetadata() {
+            return resourceMetadata;
+        }
+
+        public List<MethodMetadata> getMethodMetadata() {
+            return methodMeta;
+        }
+
+        /**
+         * Called every single time a resource has been invoked.
+         * 
+         * @param context
+         */
+        public void addInvocation(MessageContext context) {
+            try {
+                ResourceInvocationData data = context.getAttribute(ResourceInvocationData.class);
+                if (data == null) {
+                    return;
+                }
+                SearchResult result = context.getAttribute(SearchResult.class);
+                data.getResourceMetadata().add(result.getResource().getRecord());
+                if (result.isFound()) {
+                    data.getMethodMetadata().add(result.getMethod().getMetadata());
+                }
+            } catch (Exception e) {
+                logger.trace("Encountered exception while calling addInvocation", e);
+            }
+        }
+    }
+
+    final private static Logger logger = LoggerFactory.getLogger(ResourceInvocation.class);
+
+    public void init(Properties props) {
+        /* do nothing */
+    }
+
+    public void handleRequest(MessageContext context, HandlersChain chain) throws Throwable {
+        logger.trace("handleRequest({}, {}) entry", context, chain);
+        try {
+            if (logger.isDebugEnabled()) {
+                logStartRequest(context);
+            }
+            chain.doChain(context);
+        } finally {
+            if (logger.isDebugEnabled()) {
+                logFinishRequest(context);
+            }
+        }
+        logger.trace("handleRequest({}, {}) exit", context, chain);
+    }
+
+    private void logStartRequest(MessageContext context) {
+        /*
+         * setup for some resource invocation logging
+         */
+        context.setAttribute(ResourceInvocationData.class, new ResourceInvocationData());
+    }
+
+    public void logFinishRequest(MessageContext context) {
+        try {
+            ResourceInvocationData data = context.getAttribute(ResourceInvocationData.class);
+            if (data == null) {
+                return;
+            }
+
+            List<ResourceRecord> resClassData = data.getResourceMetadata();
+            List<MethodMetadata> resMethodData = data.getMethodMetadata();
+
+            StringBuffer sb = new StringBuffer();
+            Formatter f = new Formatter(sb);
+            int size = resMethodData.size();
+
+            for (int i = 0; i < size; ++i) {
+                f.format("%n-> %1$s.%2$s", resClassData.get(i).getMetadata().getResourceClass()
+                    .getName(), prettyMethodPrint(resMethodData.get(i).getReflectionMethod()));
+                if (logger.isTraceEnabled()) {
+                    LogUtilities
+                        .logResourceMetadata(Collections.singletonList(resClassData.get(i)),
+                                             logger,
+                                             true,
+                                             true);
+                }
+            }
+
+            SearchResult result = context.getAttribute(SearchResult.class);
+            if (result.isError()) {
+                ResourceInstance instance = result.getResource();
+                if (instance != null) {
+                    f.format("%n-> %1$s.(No matching method)", instance.getResourceClass()
+                        .getName());
+                    if (logger.isTraceEnabled()) {
+                        LogUtilities.logResourceMetadata(Collections.singletonList(result
+                            .getResource().getRecord()), logger, true, true);
+                    }
+                } else {
+                    f.format("No resource instance was invoked.");
+                }
+            }
+            logger.debug("Resource invocation:{}", sb);
+        } catch (Exception e) {
+            logger.trace("Encountered exception while calling logFinishRequest", e);
+        }
+    }
+
+    private String prettyMethodPrint(Method javaMethod) {
+        if (javaMethod == null) {
+            return "";
+        }
+        StringBuffer methodName = new StringBuffer();
+        methodName.append(javaMethod.getName());
+        boolean isFirst = true;
+        methodName.append("(");
+        for (Class<?> paramTypes : javaMethod.getParameterTypes()) {
+            if (!isFirst) {
+                methodName.append(",");
+            } else {
+                isFirst = false;
+            }
+            methodName.append(paramTypes.getSimpleName());
+        }
+        methodName.append(")");
+        return methodName.toString();
+    }
+}

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Resources.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Resources.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Resources.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Resources.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.util.List;
+
+import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.registry.metadata.ClassMetadata;
+import org.apache.wink.server.internal.registry.ResourceRecord;
+import org.apache.wink.server.internal.registry.ResourceRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Logs all the resource information.
+ */
+public class Resources {
+
+    private static final Logger    logger = LoggerFactory.getLogger(Resources.class);
+
+    private final ResourceRegistry resourceRegistry;
+
+    public Resources(ResourceRegistry resourceRegistry) {
+        this.resourceRegistry = resourceRegistry;
+    }
+
+    public void log() {
+        logger.trace("log() entry");
+        try {
+            if (logger.isInfoEnabled()) {
+                List<ResourceRecord> resourceRecords = resourceRegistry.getRecords();
+                logResourceInfo(resourceRecords);
+
+                if (logger.isDebugEnabled()) {
+                    if (resourceRecords.isEmpty()) {
+                        logger
+                            .debug("There are no @javax.ws.rs.Path annotated classes defined in the application.");
+                    }
+                    LogUtilities.logResourceMetadata(resourceRecords, logger, false, false);
+                }
+            }
+        } catch (Exception e) {
+            logger.trace("Could not produce all the resource metadata.", e);
+        }
+        logger.trace("log() exit");
+    }
+
+    private void logResourceInfo(List<ResourceRecord> resourceRecords) {
+        for (ResourceRecord record : resourceRecords) {
+            try {
+                final String resourceClassName = record.getMetadata().getResourceClass().getName();
+                final ClassMetadata resourceMetadata = record.getMetadata();
+                final String resourcePath = resourceMetadata.getPath();
+                logger.info(Messages.getMessage("serverRegisterJAXRSResourceWithPath",
+                                                resourceClassName,
+                                                resourcePath));
+            } catch (Exception e) {
+                logger.trace("Could not print all of the resource metadata.", e);
+            }
+        }
+    }
+}

Added: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Responses.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Responses.java?rev=1027712&view=auto
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Responses.java (added)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/log/Responses.java Tue Oct 26 19:52:54 2010
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *  
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.wink.server.internal.log;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.List;
+import java.util.Properties;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.ws.rs.core.MultivaluedMap;
+
+import org.apache.wink.common.internal.MultivaluedMapImpl;
+import org.apache.wink.server.handlers.HandlersChain;
+import org.apache.wink.server.handlers.MessageContext;
+import org.apache.wink.server.handlers.ResponseHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Responses implements ResponseHandler {
+
+    private boolean              isErrorFlow        = false;
+
+    final private static Logger  logger             = LoggerFactory.getLogger(Responses.class);
+
+    final private static int     BREAK_POINT        =
+                                                        Integer
+                                                            .valueOf(System
+                                                                .getProperty(Responses.class
+                                                                                 .getName() + ".breakPoint",
+                                                                             "4096")).intValue();
+
+    final private static boolean IS_LOGGED_AS_BYTES =
+                                                        Boolean
+                                                            .valueOf(System
+                                                                .getProperty(Responses.class
+                                                                                 .getName() + ".logAsBytes",
+                                                                             "false"))
+                                                            .booleanValue();
+
+    final private static int     BUFFER_SIZE        =
+                                                        Integer
+                                                            .valueOf(System
+                                                                .getProperty(Responses.class
+                                                                                 .getName() + ".bufferSize",
+                                                                             "8192")).intValue();
+
+    public void log() {
+
+    }
+
+    public void init(Properties props) {
+        /* do nothing */
+    }
+
+    public void setIsErrorFlow(boolean isErrorFlow) {
+        this.isErrorFlow = isErrorFlow;
+    }
+
+    public boolean isErrorFlow() {
+        return isErrorFlow;
+    }
+
+    public void handleResponse(MessageContext context, HandlersChain chain) throws Throwable {
+        logger.trace("handleRequest({}, {}) entry", context, chain);
+        try {
+            if (logger.isDebugEnabled()) {
+                logStartResponse(context);
+            }
+            chain.doChain(context);
+        } finally {
+            if (logger.isDebugEnabled()) {
+                logFinishResponse(context);
+            }
+        }
+        logger.trace("handleRequest({}, {}) exit", context, chain);
+    }
+
+    void logStartResponse(MessageContext context) {
+        logger.trace("logStartResponse({}) entry", context);
+        try {
+            if (!logger.isDebugEnabled()) {
+                logger.trace("logStartResponse() exit"); // how would this ever
+                // occur?
+                return;
+            }
+
+            /*
+             * start wrapping the OutputStream here in the hope that it will be
+             * called during logFinishResponse
+             */
+            HttpServletResponseWrapper response =
+                context.getAttribute(HttpServletResponseWrapper.class);
+            if (response == null) {
+                logger.debug("Could not find the HTTP Servlet Response to wrap.");
+                // this is a really bad path that should probably be an error,
+                // but just in case
+                logger.trace("logStartRequest() exit");
+                return;
+            }
+            ResponseWrapper wrapper = new ResponseWrapper(response);
+            context.setAttribute(ResponseWrapper.class, wrapper);
+            context.setAttribute(HttpServletResponse.class, wrapper);
+            context.setAttribute(HttpServletResponseWrapper.class, wrapper);
+        } catch (Exception e) {
+            logger.trace("Could not log the start of the request", e);
+        }
+        logger.trace("logStartResponse() exit");
+    }
+
+    void logFinishResponse(MessageContext context) {
+        logger.trace("logFinishResponse({}) entry", context);
+        try {
+            if (!logger.isDebugEnabled()) {
+                logger.trace("logFinishResponse() exit"); // how would this ever
+                // occur?
+                return;
+            }
+            ResponseWrapper responseWrapper = context.getAttribute(ResponseWrapper.class);
+            if (responseWrapper == null) {
+                logger
+                    .debug("Did not find the ResponseWrapper so will not log the response entity.");
+                logger.trace("logStartRequest() exit");
+                return;
+            }
+
+            if (isErrorFlow) {
+                logger
+                    .debug("An error occurred when handling the initial request/response, so wrote the entity and headers in the error response handlers chain.");
+            }
+
+            
+            MultivaluedMap<String, String> headers = responseWrapper.getLoggedResponseHeaders();
+            if (headers != null && headers.size() > 0) {
+                List<String> keys = new ArrayList<String>(headers.keySet());
+                Collections.sort(keys);
+                StringBuilder sb = new StringBuilder();
+                Formatter f = new Formatter(sb);
+                for(String k : keys) {
+                    List<String> values = headers.get(k);
+                    for(String v : values) {
+                        f.format("%n%1$-30s%2$s", k, v);
+                    }
+                }
+                logger.debug("The written response headers:{}", sb);
+            } else {
+                logger.debug("There were no custom headers written on the response.");
+            }
+
+            LoggedServletOutputStream loggedOutputStream = responseWrapper.getLoggedOutputStream();
+            if (loggedOutputStream == null || loggedOutputStream.getLoggedByteBufferLength() == 0) {
+                logger
+                    .debug("The response entity was not written to the HttpServletResponse.getOutputStream().");
+                return;
+            }
+            byte[] buffer = loggedOutputStream.getLoggedByteBuffer();
+            final int bufferLength = loggedOutputStream.getLoggedByteBufferLength();
+
+            if (IS_LOGGED_AS_BYTES) {
+                logger.debug("The response entity as bytes:");
+                StringBuffer sb = new StringBuffer();
+                int outputCount = 0;
+
+                for (int count = 0; count < bufferLength; ++count) {
+                    sb.append(String.format("%#04x ", buffer[count]));
+                    sb.append(" ");
+                    ++outputCount;
+                    if (outputCount > BREAK_POINT) {
+                        /*
+                         * 100KB increments
+                         */
+                        logger.debug("{}", sb);
+                        sb = new StringBuffer();
+                        outputCount = 0;
+                    }
+                }
+                if (outputCount > 0) {
+                    logger.debug("{}", sb);
+                    sb = new StringBuffer();
+                }
+            } else {
+                logger.debug("The response entity as a String in the default encoding:");
+                int offset = 0;
+                while (offset < bufferLength) {
+                    int length = bufferLength - offset;
+                    if (length > BREAK_POINT) {
+                        length = BREAK_POINT;
+                    }
+                    String str = new String(buffer, offset, length);
+                    logger.debug("{}", str);
+                    offset += length;
+                }
+            }
+            /*
+             * remove it in case during a Response chain, an exception is thrown
+             * and then a Request needs to be logged again. so only 1 shot at
+             * logging a request.
+             */
+            context.setAttribute(ResponseWrapper.class, null);
+        } catch (Exception e) {
+            logger.debug("Could not log the finishing of the response", e);
+        }
+        logger.trace("logFinishResponse() exit");
+    }
+
+    public static class ResponseWrapper extends HttpServletResponseWrapper {
+        final private HttpServletResponse      response;
+
+        private LoggedServletOutputStream      outputStreamLogger           = null;
+
+        private ServletOutputStream            originalStream;
+        private boolean                        hasStreamBeenRetrievedBefore = false;
+
+        private MultivaluedMap<String, String> headers                      =
+                                                                                new MultivaluedMapImpl<String, String>();
+
+        public ResponseWrapper(HttpServletResponse response) {
+            super(response);
+            this.response = response;
+        }
+
+        @Override
+        public void addHeader(String headerName, String headerValue) {
+            /*
+             * we override this in case someone manually circumvents the
+             * Response object by using a @Context HttpServletResponse.
+             */
+            headers.add(headerName, headerValue);
+            super.addHeader(headerName, headerValue);
+        }
+
+        @Override
+        public ServletOutputStream getOutputStream() throws IOException {
+            if (outputStreamLogger != null) {
+                return outputStreamLogger;
+            }
+
+            if (!hasStreamBeenRetrievedBefore) {
+                originalStream = response.getOutputStream();
+            }
+            if (originalStream == null) {
+                /*
+                 * this could happen in a weird situation with the web
+                 * container. defensive coding for now.
+                 */
+                logger
+                    .debug("The web container did not return a stream from HttpServletResponse.getOutputStream()");
+                return null;
+            }
+
+            outputStreamLogger = new LoggedServletOutputStream(originalStream, BUFFER_SIZE);
+            return outputStreamLogger;
+        }
+
+        public LoggedServletOutputStream getLoggedOutputStream() {
+            return outputStreamLogger;
+        }
+
+        public MultivaluedMap<String, String> getLoggedResponseHeaders() {
+            return headers;
+        }
+    }
+
+    /**
+     * A wrapper class for a ServletInputStream that also logs the bytes.
+     */
+    public static class LoggedServletOutputStream extends ServletOutputStream {
+
+        final private ServletOutputStream originalRequest;
+
+        private final byte[]              responseBuffer;
+
+        private int                       offset = 0;
+
+        public LoggedServletOutputStream(ServletOutputStream originalRequest, int bufferSize) {
+            this.originalRequest = originalRequest;
+            responseBuffer = new byte[bufferSize];
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            if (offset < responseBuffer.length) {
+                responseBuffer[offset] = (byte)b;
+                ++offset;
+            }
+            originalRequest.write(b);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            if (len > 0) {
+                int length = len;
+                if (len + offset >= responseBuffer.length) {
+                    length = responseBuffer.length - offset;
+                }
+                System.arraycopy(b, off, responseBuffer, offset, length);
+                offset += length;
+            }
+            originalRequest.write(b, off, len);
+        }
+
+        @Override
+        public void write(byte[] b) throws IOException {
+            if (b.length > 0) {
+                int length = b.length;
+                if (b.length + offset >= responseBuffer.length) {
+                    length = responseBuffer.length - offset;
+                }
+                System.arraycopy(b, 0, responseBuffer, offset, length);
+                offset += length;
+            }
+            originalRequest.write(b);
+        }
+
+        public int getLoggedByteBufferLength() {
+            return offset;
+        }
+
+        public byte[] getLoggedByteBuffer() {
+            return responseBuffer;
+        }
+
+        @Override
+        public void close() throws IOException {
+            originalRequest.close();
+        }
+
+        @Override
+        public void flush() throws IOException {
+            originalRequest.flush();
+        }
+    }
+}

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRecord.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRecord.java?rev=1027712&r1=1027711&r2=1027712&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRecord.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ResourceRecord.java Tue Oct 26 19:52:54 2010
@@ -141,6 +141,10 @@ public class ResourceRecord extends Temp
         return getMatchingSubResources(uri, false, true);
     }
 
+    public List<SubResourceRecord> getSubResourceRecords() {
+        return subResources;
+    }
+
     public List<SubResourceInstance> getMatchingSubResources(String uri,
                                                              boolean method,
                                                              boolean locator) {

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ServerInjectableFactory.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ServerInjectableFactory.java?rev=1027712&r1=1027711&r2=1027712&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ServerInjectableFactory.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/registry/ServerInjectableFactory.java Tue Oct 26 19:52:54 2010
@@ -56,6 +56,8 @@ import org.apache.wink.common.internal.r
 import org.apache.wink.common.internal.uri.UriEncoder;
 import org.apache.wink.common.internal.utils.MediaTypeUtils;
 import org.apache.wink.common.internal.utils.StringUtils;
+import org.apache.wink.common.utils.ProviderUtils;
+import org.apache.wink.common.utils.ProviderUtils.PROVIDER_EXCEPTION_ORIGINATOR;
 import org.apache.wink.server.internal.handlers.SearchResult;
 
 public class ServerInjectableFactory extends InjectableFactory {
@@ -187,13 +189,19 @@ public class ServerInjectableFactory ext
                                                    mediaType);
 
                 if (mbr != null) {
-                    Object read =
-                        mbr.readFrom(paramType,
+                    Object read;
+                    try {
+                        read = mbr.readFrom(paramType,
                                      getGenericType(),
                                      getAnnotations(),
                                      mediaType,
                                      runtimeContext.getHttpHeaders().getRequestHeaders(),
                                      runtimeContext.getInputStream());
+                    } catch (RuntimeException e) {
+                        ProviderUtils.logUserProviderException(e, mbr, PROVIDER_EXCEPTION_ORIGINATOR.readFrom, new Object[]{paramType, getGenericType(), getAnnotations(), mediaType, runtimeContext.getHttpHeaders().getRequestHeaders(),
+                                runtimeContext.getInputStream()}, runtimeContext);
+                        throw e;
+                    }
                     return read;
                 }
             }

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java?rev=1027712&r1=1027711&r2=1027712&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java Tue Oct 26 19:52:54 2010
@@ -37,6 +37,8 @@ import org.apache.wink.common.internal.u
 import org.apache.wink.server.internal.DeploymentConfiguration;
 import org.apache.wink.server.internal.RequestProcessor;
 import org.apache.wink.server.internal.application.ServletWinkApplication;
+import org.apache.wink.server.internal.log.Providers;
+import org.apache.wink.server.internal.log.Resources;
 import org.apache.wink.server.internal.utils.ServletFileLoader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -68,12 +70,12 @@ public class RestServlet extends Abstrac
     private static final Logger logger                  =
                                                             LoggerFactory
                                                                 .getLogger(RestServlet.class);
-    
-    public static final String APPLICATION_INIT_PARAM  = "javax.ws.rs.Application";          //$NON-NLS-1$
-    public static final String PROPERTIES_DEFAULT_FILE = "META-INF/wink-default.properties"; //$NON-NLS-1$
-    public static final String PROPERTIES_INIT_PARAM   = "propertiesLocation";               //$NON-NLS-1$
-    public static final String APP_LOCATION_PARAM      = "applicationConfigLocation";        //$NON-NLS-1$
-    public static final String DEPLOYMENT_CONF_PARAM    = "deploymentConfiguration";          //$NON-NLS-1$
+
+    public static final String  APPLICATION_INIT_PARAM  = "javax.ws.rs.Application";          //$NON-NLS-1$
+    public static final String  PROPERTIES_DEFAULT_FILE = "META-INF/wink-default.properties"; //$NON-NLS-1$
+    public static final String  PROPERTIES_INIT_PARAM   = "propertiesLocation";               //$NON-NLS-1$
+    public static final String  APP_LOCATION_PARAM      = "applicationConfigLocation";        //$NON-NLS-1$
+    public static final String  DEPLOYMENT_CONF_PARAM   = "deploymentConfiguration";          //$NON-NLS-1$
 
     @Override
     public void init() throws ServletException {
@@ -126,12 +128,45 @@ public class RestServlet extends Abstrac
         if (app == null) {
             app = getApplication(deploymentConfiguration);
         }
-        if (logger.isDebugEnabled()) {
-            logger.debug("RestServlet:  setting application to " + app.toString());
+        if (logger.isTraceEnabled()) {
+            logger.trace("Setting application to " + app.toString());
         }
         deploymentConfiguration.addApplication(app, false);
+
+        if (!LoggerFactory.getLogger(Resources.class).isTraceEnabled()) {
+            /*
+             * if just debug or higher is enabled, then log only user
+             * applications
+             */
+            new Resources(deploymentConfiguration.getResourceRegistry()).log();
+        }
+
+        if (!LoggerFactory.getLogger(Providers.class).isTraceEnabled()) {
+            /*
+             * if just debug or higher is enabled, then log only user
+             * applications
+             */
+            new Providers(deploymentConfiguration.getProvidersRegistry()).log();
+        }
+
         RequestProcessor requestProcessor = new RequestProcessor(deploymentConfiguration);
         logger.trace("Creating request processor {} for servlet {}", requestProcessor, this); //$NON-NLS-1$
+
+        if (LoggerFactory.getLogger(Resources.class).isTraceEnabled()) {
+            /*
+             * if full trace is enabled, then log everything
+             */
+
+            new Resources(deploymentConfiguration.getResourceRegistry()).log();
+        }
+
+        if (LoggerFactory.getLogger(Providers.class).isTraceEnabled()) {
+            /*
+             * if full trace is enabled, then log everything
+             */
+            new Providers(deploymentConfiguration.getProvidersRegistry()).log();
+        }
+
         return requestProcessor;
     }
 
@@ -146,11 +181,10 @@ public class RestServlet extends Abstrac
     }
 
     /**
-     * order of loading and property precedence:
-     * 
-     * wink-default.properties
-     * file referred to by propertiesLocation init param (may override and add to above set props)
-     * JVM system properties (only sets values for key/value pairs where the value is null or empty)
+     * order of loading and property precedence: wink-default.properties file
+     * referred to by propertiesLocation init param (may override and add to
+     * above set props) JVM system properties (only sets values for key/value
+     * pairs where the value is null or empty)
      */
     protected Properties getProperties() throws IOException {
         Properties defaultProperties = loadProperties(PROPERTIES_DEFAULT_FILE, null);
@@ -209,7 +243,7 @@ public class RestServlet extends Abstrac
             // use ClassUtils.loadClass instead of Class.forName so we have
             // classloader visibility into the Web module in J2EE environments
             appClass = (Class<? extends Application>)ClassUtils.loadClass(initParameter);
-            
+
             // let the lifecycle manager create the instance and process fields
             // for injection
             ObjectFactory of = configuration.getOfFactoryRegistry().getObjectFactory(appClass);
@@ -240,11 +274,11 @@ public class RestServlet extends Abstrac
          */
         return null;
     }
- 
+
     /**
      * loadProperties will try to load the properties from the resource,
-     * overriding existing properties in defaultProperties, and adding
-     * new ones, and return the result
+     * overriding existing properties in defaultProperties, and adding new ones,
+     * and return the result
      * 
      * @param resourceName
      * @param defaultProperties
@@ -269,7 +303,8 @@ public class RestServlet extends Abstrac
                 }
             } catch (IOException e) {
                 if (logger.isWarnEnabled()) {
-                    logger.warn(Messages.getMessage("exceptionClosingFile") + ": " + resourceName, e); //$NON-NLS-1$ //$NON-NLS-2$
+                    logger
+                        .warn(Messages.getMessage("exceptionClosingFile") + ": " + resourceName, e); //$NON-NLS-1$ //$NON-NLS-2$
                 }
             }
         }



Mime
View raw message