/*
 * ProcessorServer.java February 2007
 *
 * Copyright (C) 2007, Niall Gallagher <niallg@users.sf.net>
 *
 * 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.simpleframework.transport;

import java.io.IOException;

import org.simpleframework.transport.reactor.Operation;
import org.simpleframework.util.thread.Daemon;

/**
 * The <code>ProcessorServer</code> is used to convert pipelines
 * to transports. This simply acts as an adapter to a processor
 * which converts a connected pipeline to a <code>Transport</code>
 * which can be used to read and write data. Conversion of the
 * pipeline is performed only once per connection.
 * 
 * @author Niall Gallagher
 */
public class ProcessorServer implements Server {

   /**
    * This is the factory used to create the required operations.
    */
   private final OperationFactory factory;
   
   /**
    * This is the processor used to process transport objects.
    */
   private final Negotiator negotiator;
   
   /**
    * This is used to terminate the internals of the processor.
    */
   private final Daemon trigger;

   /**
    * Constructor for the <code>ProcessorServer</code> object. 
    * The transport processor is used to process plain connections
    * and wrap those connections in a <code>Transport</code> that
    * can be used to send and receive data to and from.
    * 
    * @param processor this is used to process transports
    */
   public ProcessorServer(Processor processor) throws IOException {
      this(processor, 8);
   }
   
   /**
    * Constructor for the <code>ProcessorServer</code> object. 
    * The transport processor is used to process plain connections
    * and wrap those connections in a <code>Transport</code> that
    * can be used to send and receive data to and from.
    * 
    * @param processor this is used to process transports
    * @param count this is the number of threads this will use
    */
   public ProcessorServer(Processor processor, int count) throws IOException {
      this(processor, count, 20480);
   }
      
   /**
    * Constructor for the <code>ProcessorServer</code> object. 
    * The transport processor is used to process plain connections
    * and wrap those connections in a <code>Transport</code> that
    * can be used to send and receive data to and from.
    * 
    * @param processor this is used to process transports
    * @param count this is the number of threads this will use
    * @param limit this is the threshold for asynchronous buffers
    */
   public ProcessorServer(Processor processor, int count, int limit) throws IOException {
      this.negotiator = new SecureNegotiator(processor, count);
      this.factory = new OperationFactory(negotiator, limit);
      this.trigger = new StopTrigger(processor, negotiator);
   }

   /**
    * Used to process the <code>Pipeline</code> which is a full duplex 
    * communication link that may contain several HTTP requests. This 
    * will be used to read the requests from the <code>Pipeline</code> 
    * and to pass these requests to a <code>Container</code> for 
    * processing.
    * <p>
    * Typical usage of this method is to accept multiple pipeline 
    * objects, each representing a unique HTTP channel to the client,
    * and process requests from those pipelines concurrently.  
    *
    * @param socket this is the connected HTTP pipeline to process
    */    
   public void process(Socket socket) throws IOException {
      Operation task = factory.getInstance(socket);
      
      if(task != null) {
         negotiator.process(task);
      }
   }
   
   /**
    * This method is used to stop the <code>Processor</code> such that
    * it will accept no more pipelines. Stopping the processor ensures
    * that all resources occupied will be released. This is required
    * so that all threads are stopped, and all memory is released.
    * <p>
    * Typically this method is called once all connections to the
    * server have been stopped. As a final act of shutting down the
    * entire server all threads must be stopped, this allows collection
    * of unused memory and the closing of file and socket resources.
    * <p>
    * This is implemented to shut down the server asynchronously. It 
    * will start a process to perform the shutdown. Asynchronous
    * shutdown allows a server resource executed via a HTTP request
    * can stop the server without any danger of killing itself or
    * even worse causing a deadlock.
    */    
   public void stop() throws IOException {
      trigger.start();
   }
 }
