All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.redkale.net.PrepareServlet Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.redkale.net;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.atomic.*;
import java.util.function.Predicate;
import java.util.logging.*;
import org.redkale.util.*;

/**
 * 根Servlet, 一个Server只能存在一个根Servlet
 *
 * 用于分发Request请求
 *
 * 

* 详情见: https://redkale.org * * @author zhangjx * @param SessionID的类型 * @param Context的子类型 * @param Request的子类型 * @param

Response的子类型 * @param Servlet的子类型 */ public abstract class PrepareServlet, P extends Response, S extends Servlet> extends Servlet { protected final AtomicLong executeCounter = new AtomicLong(); //执行请求次数 protected final AtomicLong illRequestCounter = new AtomicLong(); //错误请求次数 private final Object lock1 = new Object(); private Set servlets = new HashSet<>(); private final Object lock2 = new Object(); private Map mappings = new HashMap<>(); private final List> filters = new ArrayList<>(); protected Filter headFilter; protected void putServlet(S servlet) { synchronized (lock1) { Set newservlets = new HashSet<>(servlets); newservlets.add(servlet); this.servlets = newservlets; } } protected void removeServlet(S servlet) { synchronized (lock1) { Set newservlets = new HashSet<>(servlets); newservlets.remove(servlet); this.servlets = newservlets; } } public boolean containsServlet(Class servletClass) { synchronized (lock1) { for (S servlet : new HashSet<>(servlets)) { if (servlet.getClass().equals(servletClass)) return true; } return false; } } public boolean containsServlet(String servletClassName) { synchronized (lock1) { for (S servlet : new HashSet<>(servlets)) { if (servlet.getClass().getName().equals(servletClassName)) return true; } return false; } } protected void putMapping(K key, S servlet) { synchronized (lock2) { Map newmappings = new HashMap<>(mappings); newmappings.put(key, servlet); this.mappings = newmappings; } } protected void removeMapping(K key) { synchronized (lock2) { if (mappings.containsKey(key)) { Map newmappings = new HashMap<>(mappings); newmappings.remove(key); this.mappings = newmappings; } } } protected void removeMapping(S servlet) { synchronized (lock2) { List keys = new ArrayList<>(); Map newmappings = new HashMap<>(mappings); for (Map.Entry en : newmappings.entrySet()) { if (en.getValue().equals(servlet)) { keys.add(en.getKey()); } } for (K key : keys) newmappings.remove(key); this.mappings = newmappings; } } protected S mappingServlet(K key) { return mappings.get(key); } @Override @SuppressWarnings("unchecked") public void init(C context, AnyValue config) { synchronized (filters) { if (!filters.isEmpty()) { Collections.sort(filters); for (Filter filter : filters) { filter.init(context, config); } this.headFilter = filters.get(0); Filter filter = this.headFilter; for (int i = 1; i < filters.size(); i++) { filter._next = filters.get(i); filter = filter._next; } } } } @Override @SuppressWarnings("unchecked") public void destroy(C context, AnyValue config) { synchronized (filters) { if (!filters.isEmpty()) { for (Filter filter : filters) { filter.destroy(context, config); } } } } @SuppressWarnings("unchecked") public void addFilter(Filter filter, AnyValue conf) { filter._conf = conf; synchronized (filters) { this.filters.add(filter); Collections.sort(this.filters); } } public > T removeFilter(Class filterClass) { return removeFilter(f -> filterClass.equals(f.getClass())); } public boolean containsFilter(Class filterClass) { if (this.headFilter == null || filterClass == null) return false; Filter filter = this.headFilter; do { if (filter.getClass().equals(filterClass)) return true; } while ((filter = filter._next) != null); return false; } public boolean containsFilter(String filterClassName) { if (this.headFilter == null || filterClassName == null) return false; Filter filter = this.headFilter; do { if (filter.getClass().getName().equals(filterClassName)) return true; } while ((filter = filter._next) != null); return false; } @SuppressWarnings("unchecked") public > T removeFilter(Predicate predicate) { if (this.headFilter == null || predicate == null) return null; synchronized (filters) { Filter filter = this.headFilter; Filter prev = null; do { if (predicate.test((T) filter)) break; prev = filter; } while ((filter = filter._next) != null); if (filter != null) { if (prev == null) { this.headFilter = filter._next; } else { prev._next = filter._next; } filter._next = null; this.filters.remove(filter); } return (T) filter; } } @SuppressWarnings("unchecked") public > List getFilters() { return (List) new ArrayList<>(filters); } @SuppressWarnings("unchecked") public abstract void addServlet(S servlet, Object attachment, AnyValue conf, K... mappings); public void prepare(final ByteBuffer buffer, final R request, final P response) throws IOException { executeCounter.incrementAndGet(); final int rs = request.readHeader(buffer); if (rs < 0) { request.offerReadBuffer(buffer); if (rs != Integer.MIN_VALUE) illRequestCounter.incrementAndGet(); response.finish(true); } else if (rs == 0) { if (buffer.hasRemaining()) { request.setMoredata(buffer); } else { request.offerReadBuffer(buffer); } request.prepare(); response.filter = this.headFilter; response.servlet = this; response.nextEvent(); } else { buffer.clear(); final AtomicInteger ai = new AtomicInteger(rs); request.channel.read(buffer, buffer, new CompletionHandler() { @Override public void completed(Integer result, ByteBuffer attachment) { buffer.flip(); ai.addAndGet(-request.readBody(buffer)); if (ai.get() > 0) { buffer.clear(); request.channel.read(buffer, buffer, this); } else { if (buffer.hasRemaining()) { request.setMoredata(buffer); } else { request.offerReadBuffer(buffer); } request.prepare(); try { response.filter = PrepareServlet.this.headFilter; response.servlet = PrepareServlet.this; response.nextEvent(); } catch (Exception e) { illRequestCounter.incrementAndGet(); response.finish(true); request.context.logger.log(Level.WARNING, "prepare servlet abort, forece to close channel ", e); } } } @Override public void failed(Throwable exc, ByteBuffer attachment) { illRequestCounter.incrementAndGet(); request.offerReadBuffer(buffer); response.finish(true); if (exc != null) request.context.logger.log(Level.FINER, "Servlet read channel erroneous, forece to close channel ", exc); } }); } } protected AnyValue getServletConf(Servlet servlet) { return servlet._conf; } protected void setServletConf(Servlet servlet, AnyValue conf) { servlet._conf = conf; } public List getServlets() { return new ArrayList<>(servlets); } }