TargetContext.java
/**
* Copyright (c) 2009, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.synapse.transport.passthru;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpRequest;
import org.apache.http.nio.NHttpConnection;
import org.apache.log4j.MDC;
import org.apache.synapse.transport.passthru.config.TargetConfiguration;
import org.apache.synapse.transport.passthru.util.ControlledByteBuffer;
/**
* When a connection is created, an object of this class is stored in the Connection Context.
* It is used as a holder for information required during the life-cycle of this connection.
*/
public class TargetContext {
private TargetConfiguration targetConfiguration = null;
public static final String CONNECTION_INFORMATION = "CONNECTION_INFORMATION";
/** The request for this connection */
private TargetRequest request;
/** The response for this connection */
private TargetResponse response;
/** State of the connection */
private ProtocolState state;
/** The request message context */
private MessageContext requestMsgCtx;
/** The current reader */
private Pipe reader;
/** The current writer */
private Pipe writer;
/** logger for correlation.log */
private static final Log correlationLog = LogFactory.getLog(PassThroughConstants.CORRELATION_LOGGER);
/** Time that state got updated*/
private long lastStateUpdatedTime;
public TargetContext(TargetConfiguration targetConfiguration) {
this.targetConfiguration = targetConfiguration;
}
public ProtocolState getState() {
return state;
}
public void setState(ProtocolState state) {
this.state = state;
}
public TargetConfiguration getTargetConfiguration() {
return targetConfiguration;
}
public TargetRequest getRequest() {
return request;
}
public void setRequest(TargetRequest request) {
this.request = request;
}
public TargetResponse getResponse() {
return response;
}
public void setResponse(TargetResponse response) {
this.response = response;
}
public MessageContext getRequestMsgCtx() {
return requestMsgCtx;
}
public void setRequestMsgCtx(MessageContext requestMsgCtx) {
this.requestMsgCtx = requestMsgCtx;
}
public Pipe getReader() {
return reader;
}
public Pipe getWriter() {
return writer;
}
public void setReader(Pipe reader) {
this.reader = reader;
}
public void setWriter(Pipe writer) {
this.writer = writer;
}
/**
* Reset the resources associated with this context
*/
public void reset() {
reset(false);
}
/**
* Reset the resources associated with this context
*
* @param isError whether an error is causing this shutdown of the connection.
* It is very important to set this flag correctly.
* When an error causing the shutdown of the connections we should not
* release associated writer buffer to the pool as it might lead into
* situations like same buffer is getting released to both source and target
* buffer factories
*/
public void reset(boolean isError) {
request = null;
response = null;
if (writer != null) {
if (!isError) { // If there is an error we do not release the buffer to the factory
ControlledByteBuffer buffer = writer.getBuffer();
targetConfiguration.getBufferFactory().release(buffer);
}
}
reader = null;
writer = null;
}
public static void create(NHttpConnection conn, ProtocolState state,
TargetConfiguration configuration) {
TargetContext targetContext = new TargetContext(configuration);
conn.getContext().setAttribute(CONNECTION_INFORMATION, targetContext);
targetContext.setState(state);
if (targetContext.getTargetConfiguration().isCorrelationLoggingEnabled()) {
targetContext.updateLastStateUpdatedTime();
}
}
public static void updateState(NHttpConnection conn, ProtocolState state) {
TargetContext targetContext = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
if (targetContext != null) {
targetContext.setState(state);
if (targetContext.getTargetConfiguration().isCorrelationLoggingEnabled()
&& conn.getContext().getAttribute(PassThroughConstants.CORRELATION_ID) != null) {
long lastStateUpdateTime = targetContext.getLastStateUpdatedTime();
String url = "", method = "";
if (targetContext.getRequest() != null) {
url = targetContext.getRequest().getUrl().toString();
method = targetContext.getRequest().getMethod();
} else {
HttpRequest httpRequest = conn.getHttpRequest();
if (httpRequest != null) {
url = httpRequest.getRequestLine().getUri();
method = httpRequest.getRequestLine().getMethod();
}
}
if ((method.length() != 0) && (url.length() != 0)) {
MDC.put(PassThroughConstants.CORRELATION_MDC_PROPERTY,
conn.getContext().getAttribute(PassThroughConstants.CORRELATION_ID).toString());
correlationLog.info((targetContext.updateLastStateUpdatedTime() - lastStateUpdateTime)
+ "|HTTP State Transition|"
+ conn.getContext().getAttribute("http.connection") + "|"
+ method + "|" + url + "|"
+ state.name());
MDC.remove(PassThroughConstants.CORRELATION_MDC_PROPERTY);
}
}
} else {
throw new IllegalStateException("Connection information should be present");
}
}
public static boolean assertState(NHttpConnection conn, ProtocolState state) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
return info != null && info.getState() == state;
}
public static ProtocolState getState(NHttpConnection conn) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
return info != null ? info.getState() : null;
}
public static void setRequest(NHttpConnection conn, TargetRequest request) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
if (info != null) {
info.setRequest(request);
} else {
throw new IllegalStateException("Connection information should be present");
}
}
public static void setResponse(NHttpConnection conn, TargetResponse response) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
if (info != null) {
info.setResponse(response);
} else {
throw new IllegalStateException("Connection information should be present");
}
}
public static TargetRequest getRequest(NHttpConnection conn) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
return info != null ? info.getRequest() : null;
}
public static TargetResponse getResponse(NHttpConnection conn) {
TargetContext info = (TargetContext)
conn.getContext().getAttribute(CONNECTION_INFORMATION);
return info != null ? info.getResponse() : null;
}
public static TargetContext get(NHttpConnection conn) {
return (TargetContext) conn.getContext().getAttribute(CONNECTION_INFORMATION);
}
public long getLastStateUpdatedTime() {
return lastStateUpdatedTime;
}
public long updateLastStateUpdatedTime() {
this.lastStateUpdatedTime = System.currentTimeMillis();
return this.lastStateUpdatedTime;
}
}