/* * 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(); }