You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by jr...@apache.org on 2010/10/26 21:52:56 UTC
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...
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$
}
}
}