/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the license at
* https://glassfish.dev.java.net/public/CDDLv1.0.html or
* glassfish/bootstrap/legal/CDDLv1.0.txt.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at glassfish/bootstrap/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* you own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
*/
package com.sun.grizzly.filter;
import com.sun.grizzly.Context;
import com.sun.grizzly.ProtocolFilter;
import com.sun.grizzly.ProtocolParser;
import com.sun.grizzly.util.WorkerThread;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import static com.sun.grizzly.Controller.Protocol.TCP;
import static com.sun.grizzly.Controller.Protocol.UDP;
import static com.sun.grizzly.Controller.Protocol;
import com.sun.grizzly.util.ThreadAttachment;
/**
* Simple ProtocolFilter implementation which read the available bytes
* and delegate the decision of reading more bytes or not to a ProtocolParser.
* The ProtocolParser will decide if more bytes are required before continuing
* the invokation of the ProtocolChain.
*
*
*
* @author Jeanfrancois Arcand
*/
public abstract class ParserProtocolFilter extends ReadFilter{
public ParserProtocolFilter(){
}
/**
* Read available bytes and delegate the processing of them to the next
* ProtocolFilter in the ProtocolChain.
* @return true if the next ProtocolFilter on the ProtocolChain
* need to be invoked.
*/
@Override
public boolean execute(Context ctx) throws IOException {
ProtocolParser parser = (ProtocolParser)
ctx.getAttribute(ProtocolParser.PARSER);
if (parser == null) {
parser = newProtocolParser();
ctx.setAttribute(ProtocolParser.PARSER, parser);
}
if (!parser.hasMoreBytesToParse() || parser.isExpectingMoreData()) {
boolean continueExecution = super.execute(ctx);
WorkerThread workerThread = (WorkerThread)Thread.currentThread();
ByteBuffer byteBuffer = workerThread.getByteBuffer();
parser.startBuffer(byteBuffer);
if (!continueExecution){
return continueExecution;
}
}
if (!parser.hasNextMessage()) {
return false;
}
return invokeProtocolParser(ctx, parser);
}
/**
* Invoke the ProtocolParser
. If more bytes are required,
* register the SelectionKey
back to its associated
* SelectorHandler
* @param ctx the Context object.
* @return true if no more bytes are needed.
*/
private boolean invokeProtocolParser(Context ctx, ProtocolParser parser) {
if (parser == null){
throw new IllegalStateException("ProcotolParser cannot be null");
}
boolean continueExecution = true;
Object o = parser.getNextMessage();
ctx.setAttribute(ProtocolParser.MESSAGE, o);
return true;
}
public boolean postExecute(Context context) throws IOException {
ProtocolParser parser = (ProtocolParser)
context.getAttribute(ProtocolParser.PARSER);
if (parser != null && parser.hasMoreBytesToParse()) {
// Need to say that we read successfully since bytes are left
context.setAttribute(ProtocolFilter.SUCCESSFUL_READ, Boolean.TRUE);
return true;
}
if (parser.isExpectingMoreData()) {
parser.releaseBuffer();
WorkerThread workerThread = (WorkerThread)Thread.currentThread();
SelectionKey key = context.getSelectionKey();
// Detach the current Thread data.
ThreadAttachment threadAttachment = workerThread.detach(true);
// Attach it to the SelectionKey so the it can be resumed latter.
key.attach(threadAttachment);
// Register to get more bytes.
context.getSelectorHandler().register(key,SelectionKey.OP_READ);
return false;
}
parser.releaseBuffer();
return super.postExecute(context);
}
/**
* Return a new or cached ProtocolParser instance.
*/
public abstract ProtocolParser newProtocolParser();
}