Java tutorial
/** * 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.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.SourceConfiguration; import org.apache.synapse.transport.passthru.util.ControlledByteBuffer; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * This class represents the information about a TCP Connection at a given point in time. * In a Single TCP Connection there can be multiple HTTP Requests. */ public class SourceContext { public static final String CONNECTION_INFORMATION = "CONNECTION_INFORMATION"; /** logger for correlation.log */ private static final Log correlationLog = LogFactory.getLog(PassThroughConstants.CORRELATION_LOGGER); private SourceConfiguration sourceConfiguration; private ProtocolState state = ProtocolState.REQUEST_READY; private SourceRequest request; private SourceResponse response; /** Mark the connection to be shut down after the current request-response is completed. */ private boolean shutDown = false; private Pipe reader; private Pipe writer; private Lock lock = new ReentrantLock(); /** Time that state got updated*/ private long lastStateUpdatedTime; public SourceContext(SourceConfiguration sourceConfiguration) { this.sourceConfiguration = sourceConfiguration; } public SourceConfiguration getSourceConfiguration() { return sourceConfiguration; } public ProtocolState getState() { return state; } public void setState(ProtocolState state) { this.state = state; } public SourceRequest getRequest() { return request; } public void setRequest(SourceRequest request) { this.request = request; } public SourceResponse getResponse() { return response; } public void setResponse(SourceResponse response) { this.response = response; } /** * 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) { this.request = null; this.response = null; this.state = ProtocolState.REQUEST_READY; if (writer != null) { if (!isError) { // If there is an error we do not release the buffer to the factory ControlledByteBuffer buffer = writer.getBuffer(); sourceConfiguration.getBufferFactory().release(buffer); } } this.reader = null; this.writer = null; } public Lock getLock() { return lock; } public boolean isShutDown() { return shutDown; } public void setShutDown(boolean shutDown) { this.shutDown = shutDown; } public Pipe getReader() { return reader; } public void setReader(Pipe reader) { this.reader = reader; } public Pipe getWriter() { return writer; } public void setWriter(Pipe writer) { this.writer = writer; } public static void create(NHttpConnection conn, ProtocolState state, SourceConfiguration configuration) { SourceContext sourceContext = new SourceContext(configuration); conn.getContext().setAttribute(CONNECTION_INFORMATION, sourceContext); sourceContext.setState(state); if (sourceContext.getSourceConfiguration().isCorrelationLoggingEnabled()) { sourceContext.updateLastStateUpdatedTime(); } } public static void updateState(NHttpConnection conn, ProtocolState state) { SourceContext sourceContext = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); if (sourceContext != null) { if (sourceContext.getSourceConfiguration().isCorrelationLoggingEnabled()) { long lastStateUpdateTime = sourceContext.getLastStateUpdatedTime(); String url = "", method = ""; if (sourceContext.getRequest() != null) { url = sourceContext.getRequest().getUri(); method = sourceContext.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((sourceContext.updateLastStateUpdatedTime() - lastStateUpdateTime) + "|HTTP State Transition|" + conn.getContext().getAttribute("http.connection") + "|" + method + "|" + url + "|" + state.name()); MDC.remove(PassThroughConstants.CORRELATION_MDC_PROPERTY); } } sourceContext.setState(state); } else { throw new IllegalStateException("Connection information should be present"); } } public static boolean assertState(NHttpConnection conn, ProtocolState state) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); return info != null && info.getState() == state; } public static ProtocolState getState(NHttpConnection conn) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); return info != null ? info.getState() : null; } public static void setRequest(NHttpConnection conn, SourceRequest request) { SourceContext info = (SourceContext) 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, SourceResponse response) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); if (info != null) { info.setResponse(response); } else { throw new IllegalStateException("Connection information should be present"); } } public static SourceRequest getRequest(NHttpConnection conn) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); return info != null ? info.getRequest() : null; } public static SourceResponse getResponse(NHttpConnection conn) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); return info != null ? info.getResponse() : null; } public static SourceContext get(NHttpConnection conn) { return (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); } public static Lock getLock(NHttpConnection conn) { SourceContext info = (SourceContext) conn.getContext().getAttribute(CONNECTION_INFORMATION); return info != null ? info.getLock() : null; } public long getLastStateUpdatedTime() { return lastStateUpdatedTime; } public long updateLastStateUpdatedTime() { this.lastStateUpdatedTime = System.currentTimeMillis(); return this.lastStateUpdatedTime; } }