    public synchronized void start() {
        xnio = Xnio.getInstance(Undertow.class.getClassLoader());
        channels = new ArrayList<>();
        try {
            worker = xnio.createWorker(OptionMap.builder()
                    .set(Options.WORKER_IO_THREADS, ioThreads)
                    .set(Options.CONNECTION_HIGH_WATER, 1000000)
                    .set(Options.CONNECTION_LOW_WATER, 1000000)
                    .set(Options.WORKER_TASK_CORE_THREADS, workerThreads)
                    .set(Options.WORKER_TASK_MAX_THREADS, workerThreads)
                    .set(Options.TCP_NODELAY, true)
                    .set(Options.CORK, true)
                    .addAll(workerOptions)
                    .getMap());

            OptionMap socketOptions = OptionMap.builder()
                    .set(Options.WORKER_IO_THREADS, ioThreads)
                    .set(Options.TCP_NODELAY, true)
                    .set(Options.REUSE_ADDRESSES, true)
                    .set(Options.BALANCING_TOKENS, 1)
                    .set(Options.BALANCING_CONNECTIONS, 2)
                    .addAll(this.socketOptions)
                    .getMap();

            Pool<ByteBuffer> buffers = new ByteBufferSlicePool(directBuffers ? BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR : BufferAllocator.BYTE_BUFFER_ALLOCATOR, bufferSize, bufferSize * buffersPerRegion);

            for (ListenerConfig listener : listeners) {
                if (listener.type == ListenerType.AJP) {
                    AjpOpenListener openListener = new AjpOpenListener(buffers, serverOptions, bufferSize);
                    openListener.setRootHandler(rootHandler);
                    ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                    AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions);
                    server.resumeAccepts();
                    channels.add(server);
                } else {
                    OptionMap undertowOptions = OptionMap.builder().set(UndertowOptions.BUFFER_PIPELINED_DATA, true).addAll(serverOptions).getMap();
                    if (listener.type == ListenerType.HTTP) {
                        HttpOpenListener openListener = new HttpOpenListener(buffers, undertowOptions, bufferSize);
                        openListener.setRootHandler(rootHandler);
                        ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                        AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions);
                        server.resumeAccepts();
                        channels.add(server);
                    } else if (listener.type == ListenerType.HTTPS) {
                        OpenListener openListener = new HttpOpenListener(buffers, undertowOptions, bufferSize);
                        if(serverOptions.get(UndertowOptions.ENABLE_SPDY, false)) {
                            openListener = new SpdyOpenListener(buffers, new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 1024, 1024), undertowOptions, bufferSize, (HttpOpenListener) openListener);
                        }
                        openListener.setRootHandler(rootHandler);
                        ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                        XnioSsl xnioSsl;
                        if (listener.sslContext != null) {
                            xnioSsl = new JsseXnioSsl(xnio, OptionMap.create(Options.USE_DIRECT_BUFFERS, true), listener.sslContext);
                        } else {
                            xnioSsl = xnio.getSslProvider(listener.keyManagers, listener.trustManagers, OptionMap.create(Options.USE_DIRECT_BUFFERS, true));
                        }
                        AcceptingChannel<SslConnection> sslServer = xnioSsl.createSslConnectionServer(worker, new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), (ChannelListener) acceptListener, socketOptions);
                        sslServer.resumeAccepts();
                        channels.add(sslServer);
                    }
                }

            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public synchronized void start() {
        xnio = Xnio.getInstance(Undertow.class.getClassLoader());
        channels = new ArrayList<AcceptingChannel<? extends StreamConnection>>();
        try {
            worker = xnio.createWorker(OptionMap.builder()
                    .set(Options.WORKER_IO_THREADS, ioThreads)
                    .set(Options.CONNECTION_HIGH_WATER, 1000000)
                    .set(Options.CONNECTION_LOW_WATER, 1000000)
                    .set(Options.WORKER_TASK_CORE_THREADS, workerThreads)
                    .set(Options.WORKER_TASK_MAX_THREADS, workerThreads)
                    .set(Options.TCP_NODELAY, true)
                    .set(Options.CORK, true)
                    .addAll(workerOptions)
                    .getMap());

            OptionMap socketOptions = OptionMap.builder()
                    .set(Options.WORKER_IO_THREADS, ioThreads)
                    .set(Options.TCP_NODELAY, true)
                    .set(Options.REUSE_ADDRESSES, true)
                    .set(Options.BALANCING_TOKENS, 1)
                    .set(Options.BALANCING_CONNECTIONS, 2)
                    .addAll(this.socketOptions)
                    .getMap();

            Pool<ByteBuffer> buffers = new ByteBufferSlicePool(directBuffers ? BufferAllocator.DIRECT_BYTE_BUFFER_ALLOCATOR : BufferAllocator.BYTE_BUFFER_ALLOCATOR, bufferSize, bufferSize * buffersPerRegion);

            for (ListenerConfig listener : listeners) {
                if (listener.type == ListenerType.AJP) {
                    AjpOpenListener openListener = new AjpOpenListener(buffers, serverOptions, bufferSize);
                    openListener.setRootHandler(rootHandler);
                    ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                    AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions);
                    server.resumeAccepts();
                    channels.add(server);
                } else {
                    OptionMap undertowOptions = OptionMap.builder().set(UndertowOptions.BUFFER_PIPELINED_DATA, true).addAll(serverOptions).getMap();
                    if (listener.type == ListenerType.HTTP) {
                        HttpOpenListener openListener = new HttpOpenListener(buffers, undertowOptions, bufferSize);
                        openListener.setRootHandler(rootHandler);
                        ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                        AcceptingChannel<? extends StreamConnection> server = worker.createStreamConnectionServer(new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), acceptListener, socketOptions);
                        server.resumeAccepts();
                        channels.add(server);
                    } else if (listener.type == ListenerType.HTTPS) {
                        OpenListener openListener = new HttpOpenListener(buffers, undertowOptions, bufferSize);
                        if(serverOptions.get(UndertowOptions.ENABLE_SPDY, false)) {
                            openListener = new SpdyOpenListener(buffers, new ByteBufferSlicePool(BufferAllocator.BYTE_BUFFER_ALLOCATOR, 1024, 1024), undertowOptions, bufferSize, (HttpOpenListener) openListener);
                        }
                        openListener.setRootHandler(rootHandler);
                        ChannelListener<AcceptingChannel<StreamConnection>> acceptListener = ChannelListeners.openListenerAdapter(openListener);
                        XnioSsl xnioSsl;
                        if (listener.sslContext != null) {
                            xnioSsl = new JsseXnioSsl(xnio, OptionMap.create(Options.USE_DIRECT_BUFFERS, true), listener.sslContext);
                        } else {
                            xnioSsl = xnio.getSslProvider(listener.keyManagers, listener.trustManagers, OptionMap.create(Options.USE_DIRECT_BUFFERS, true));
                        }
                        AcceptingChannel<SslConnection> sslServer = xnioSsl.createSslConnectionServer(worker, new InetSocketAddress(Inet4Address.getByName(listener.host), listener.port), (ChannelListener) acceptListener, socketOptions);
                        sslServer.resumeAccepts();
                        channels.add(sslServer);
                    }
                }

            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

Replace Generic With Diamond ArrayList<AcceptingChannel<? extends StreamConnection>> with ArrayList<> in method public start() : void from class io.undertow.Undertow


    ExchangeAttributeParser(final ClassLoader classLoader, List<ExchangeAttributeWrapper> wrappers) {
        this.wrappers = wrappers;
        ServiceLoader<ExchangeAttributeBuilder> loader = ServiceLoader.load(ExchangeAttributeBuilder.class, classLoader);
        final List<ExchangeAttributeBuilder> builders = new ArrayList<>();
        for (ExchangeAttributeBuilder instance : loader) {
            builders.add(instance);
        }
        this.builders = Collections.unmodifiableList(builders);

    }

    ExchangeAttributeParser(final ClassLoader classLoader, List<ExchangeAttributeWrapper> wrappers) {
        this.wrappers = wrappers;
        ServiceLoader<ExchangeAttributeBuilder> loader = ServiceLoader.load(ExchangeAttributeBuilder.class, classLoader);
        final List<ExchangeAttributeBuilder> builders = new ArrayList<ExchangeAttributeBuilder>();
        for (ExchangeAttributeBuilder instance : loader) {
            builders.add(instance);
        }
        this.builders = Collections.unmodifiableList(builders);

    }

Replace Generic With Diamond ArrayList<ExchangeAttributeBuilder> with ArrayList<> in method package ExchangeAttributeParser(classLoader ClassLoader, wrappers List<ExchangeAttributeWrapper>) from class io.undertow.attribute.ExchangeAttributeParser


/**
     * Parses the provided value string, and turns it into a list of exchange attributes.
     *

     * Tokens are created according to the following rules:
     *

     * %a - % followed by single character. %% is an escape for a literal %
     * %{.*}a? - % plus curly braces with any amount of content inside, followed by an optional character
     * ${.*} - $ followed by a curly braces to reference an item from the predicate context
     *
     * @param valueString
     * @return
     */
    public ExchangeAttribute parse(final String valueString) {
        final List<ExchangeAttribute> attributes = new ArrayList<>();
        int pos = 0;
        int state = 0; //0 = literal, 1 = %, 2 = %{, 3 = $, 4 = ${
        for (int i = 0; i < valueString.length(); ++i) {
            char c = valueString.charAt(i);
            switch (state) {
                case 0: {
                    if (c == '%' || c == '$') {
                        if (pos != i) {
                            attributes.add(wrap(parseSingleToken(valueString.substring(pos, i))));
                            pos = i;
                        }
                        if (c == '%') {
                            state = 1;
                        } else {
                            state = 3;
                        }
                    }
                    break;
                }
                case 1: {
                    if (c == '{') {
                        state = 2;
                    } else if (c == '%') {
                        //literal percent
                        attributes.add(wrap(new ConstantExchangeAttribute("%")));
                        pos = i + 1;
                        state = 0;
                    } else {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 2: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 3: {
                    if (c == '{') {
                        state = 4;
                    } else {
                        state = 0;
                    }
                    break;
                }
                case 4: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }

            }
        }
        switch (state) {
            case 0:
            case 1:
            case 3:{
                if(pos != valueString.length()) {
                    attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
                }
                break;
            }
            case 2:
            case 4: {
                throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
            }
        }
        if(attributes.size() == 1) {
            return attributes.get(0);
        }
        return new CompositeExchangeAttribute(attributes.toArray(new ExchangeAttribute[attributes.size()]));
    }

/**
     * Parses the provided value string, and turns it into a list of exchange attributes.
     *

     * Tokens are created according to the following rules:
     *

     * %a - % followed by single character. %% is an escape for a literal %
     * %{.*}a? - % plus curly braces with any amount of content inside, followed by an optional character
     * ${.*} - $ followed by a curly braces to reference an item from the predicate context
     *
     * @param valueString
     * @return
     */
    public ExchangeAttribute parse(final String valueString) {
        final List<ExchangeAttribute> attributes = new ArrayList<ExchangeAttribute>();
        int pos = 0;
        int state = 0; //0 = literal, 1 = %, 2 = %{, 3 = $, 4 = ${
        for (int i = 0; i < valueString.length(); ++i) {
            char c = valueString.charAt(i);
            switch (state) {
                case 0: {
                    if (c == '%' || c == '$') {
                        if (pos != i) {
                            attributes.add(wrap(parseSingleToken(valueString.substring(pos, i))));
                            pos = i;
                        }
                        if (c == '%') {
                            state = 1;
                        } else {
                            state = 3;
                        }
                    }
                    break;
                }
                case 1: {
                    if (c == '{') {
                        state = 2;
                    } else if (c == '%') {
                        //literal percent
                        attributes.add(wrap(new ConstantExchangeAttribute("%")));
                        pos = i + 1;
                        state = 0;
                    } else {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 2: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }
                case 3: {
                    if (c == '{') {
                        state = 4;
                    } else {
                        state = 0;
                    }
                    break;
                }
                case 4: {
                    if (c == '}') {
                        attributes.add(wrap(parseSingleToken(valueString.substring(pos, i + 1))));
                        pos = i + 1;
                        state = 0;
                    }
                    break;
                }

            }
        }
        switch (state) {
            case 0:
            case 1:
            case 3:{
                if(pos != valueString.length()) {
                    attributes.add(wrap(parseSingleToken(valueString.substring(pos))));
                }
                break;
            }
            case 2:
            case 4: {
                throw UndertowMessages.MESSAGES.mismatchedBraces(valueString);
            }
        }
        if(attributes.size() == 1) {
            return attributes.get(0);
        }
        return new CompositeExchangeAttribute(attributes.toArray(new ExchangeAttribute[attributes.size()]));
    }

Replace Generic With Diamond ArrayList<ExchangeAttribute> with ArrayList<> in method public parse(valueString String) : ExchangeAttribute from class io.undertow.attribute.ExchangeAttributeParser


    @Override
    public void writeAttribute(final HttpServerExchange exchange, final String newValue) throws ReadOnlyAttributeException {
        final ArrayDeque<String> value = new ArrayDeque<>();
        value.add(newValue);
        exchange.getQueryParameters().put(parameter, value);
    }

    @Override
    public void writeAttribute(final HttpServerExchange exchange, final String newValue) throws ReadOnlyAttributeException {
        final ArrayDeque<String> value = new ArrayDeque<String>();
        value.add(newValue);
        exchange.getQueryParameters().put(parameter, value);
    }

Replace Generic With Diamond ArrayDeque<String> with ArrayDeque<> in method public writeAttribute(exchange HttpServerExchange, newValue String) : void from class io.undertow.attribute.QueryParameterAttribute


    @Override
    public ChannelListener.Setter<? extends StreamSinkChannel> getWriteSetter() {
        if (writeSetter == null) {
            writeSetter = new ChannelListener.SimpleSetter<>();
            if (!isFinished()) {
                delegate.setWriteListener(ChannelListeners.delegatingChannelListener(this, writeSetter));
            }
        }
        return writeSetter;
    }

    @Override
    public ChannelListener.Setter<? extends StreamSinkChannel> getWriteSetter() {
        if (writeSetter == null) {
            writeSetter = new ChannelListener.SimpleSetter<DetachableStreamSinkChannel>();
            if (!isFinished()) {
                delegate.setWriteListener(ChannelListeners.delegatingChannelListener(this, writeSetter));
            }
        }
        return writeSetter;
    }

Replace Generic With Diamond ChannelListener.SimpleSetter<DetachableStreamSinkChannel> with ChannelListener.SimpleSetter<> in method public getWriteSetter() : ChannelListener.Setter<? extends StreamSinkChannel> from class io.undertow.channels.DetachableStreamSinkChannel


    @Override
    public ChannelListener.Setter<? extends StreamSinkChannel> getCloseSetter() {
        if (closeSetter == null) {
            closeSetter = new ChannelListener.SimpleSetter<>();
            if (!isFinished()) {
                delegate.setCloseListener(ChannelListeners.delegatingChannelListener(this, closeSetter));
            }
        }
        return closeSetter;
    }

    @Override
    public ChannelListener.Setter<? extends StreamSinkChannel> getCloseSetter() {
        if (closeSetter == null) {
            closeSetter = new ChannelListener.SimpleSetter<DetachableStreamSinkChannel>();
            if (!isFinished()) {
                delegate.setCloseListener(ChannelListeners.delegatingChannelListener(this, closeSetter));
            }
        }
        return closeSetter;
    }

Replace Generic With Diamond ChannelListener.SimpleSetter<DetachableStreamSinkChannel> with ChannelListener.SimpleSetter<> in method public getCloseSetter() : ChannelListener.Setter<? extends StreamSinkChannel> from class io.undertow.channels.DetachableStreamSinkChannel


    public ChannelListener.Setter<? extends StreamSourceChannel> getReadSetter() {
        if (readSetter == null) {
            readSetter = new ChannelListener.SimpleSetter<>();
            if (!isFinished()) {
                delegate.setReadListener(ChannelListeners.delegatingChannelListener(this, readSetter));
            }
        }
        return readSetter;
    }

    public ChannelListener.Setter<? extends StreamSourceChannel> getReadSetter() {
        if (readSetter == null) {
            readSetter = new ChannelListener.SimpleSetter<DetachableStreamSourceChannel>();
            if (!isFinished()) {
                delegate.setReadListener(ChannelListeners.delegatingChannelListener(this, readSetter));
            }
        }
        return readSetter;
    }

Replace Generic With Diamond ChannelListener.SimpleSetter<DetachableStreamSourceChannel> with ChannelListener.SimpleSetter<> in method public getReadSetter() : ChannelListener.Setter<? extends StreamSourceChannel> from class io.undertow.channels.DetachableStreamSourceChannel


    public ChannelListener.Setter<? extends StreamSourceChannel> getCloseSetter() {
        if (closeSetter == null) {
            closeSetter = new ChannelListener.SimpleSetter<>();
            if (!isFinished()) {
                delegate.setCloseListener(ChannelListeners.delegatingChannelListener(this, closeSetter));
            }
        }
        return closeSetter;
    }

    public ChannelListener.Setter<? extends StreamSourceChannel> getCloseSetter() {
        if (closeSetter == null) {
            closeSetter = new ChannelListener.SimpleSetter<DetachableStreamSourceChannel>();
            if (!isFinished()) {
                delegate.setCloseListener(ChannelListeners.delegatingChannelListener(this, closeSetter));
            }
        }
        return closeSetter;
    }

Replace Generic With Diamond ChannelListener.SimpleSetter<DetachableStreamSourceChannel> with ChannelListener.SimpleSetter<> in method public getCloseSetter() : ChannelListener.Setter<? extends StreamSourceChannel> from class io.undertow.channels.DetachableStreamSourceChannel


    private UndertowClient(final ClassLoader classLoader) {
        ServiceLoader<ClientProvider> providers = ServiceLoader.load(ClientProvider.class, classLoader);
        final Map<String, ClientProvider> map = new HashMap<>();
        for (ClientProvider provider : providers) {
            for (String scheme : provider.handlesSchemes()) {
                map.put(scheme, provider);
            }
        }
        this.clientProviders = Collections.unmodifiableMap(map);
    }

    private UndertowClient(final ClassLoader classLoader) {
        ServiceLoader<ClientProvider> providers = ServiceLoader.load(ClientProvider.class, classLoader);
        final Map<String, ClientProvider> map = new HashMap<String, ClientProvider>();
        for (ClientProvider provider : providers) {
            for (String scheme : provider.handlesSchemes()) {
                map.put(scheme, provider);
            }
        }
        this.clientProviders = Collections.unmodifiableMap(map);
    }

Replace Generic With Diamond HashMap<String,ClientProvider> with HashMap<> in method private UndertowClient(classLoader ClassLoader) from class io.undertow.client.UndertowClient


    public IoFuture<ClientConnection> connect(InetSocketAddress bindAddress, final URI uri, final XnioWorker worker, XnioSsl ssl, Pool<ByteBuffer> bufferPool, OptionMap options) {
        ClientProvider provider = getClientProvider(uri);
        final FutureResult<ClientConnection> result = new FutureResult<>();
        provider.connect(new ClientCallback<ClientConnection>() {
            @Override
            public void completed(ClientConnection r) {
                result.setResult(r);
            }

            @Override
            public void failed(IOException e) {
                result.setException(e);
            }
        }, bindAddress, uri, worker, ssl, bufferPool, options);
        return result.getIoFuture();
    }

    public IoFuture<ClientConnection> connect(InetSocketAddress bindAddress, final URI uri, final XnioWorker worker, XnioSsl ssl, Pool<ByteBuffer> bufferPool, OptionMap options) {
        ClientProvider provider = getClientProvider(uri);
        final FutureResult<ClientConnection> result = new FutureResult<ClientConnection>();
        provider.connect(new ClientCallback<ClientConnection>() {
            @Override
            public void completed(ClientConnection r) {
                result.setResult(r);
            }

            @Override
            public void failed(IOException e) {
                result.setException(e);
            }
        }, bindAddress, uri, worker, ssl, bufferPool, options);
        return result.getIoFuture();
    }

Replace Generic With Diamond FutureResult<ClientConnection> with FutureResult<> in method public connect(bindAddress InetSocketAddress, uri URI, worker XnioWorker, ssl XnioSsl, bufferPool Pool<ByteBuffer>, options OptionMap) : IoFuture<ClientConnection> from class io.undertow.client.UndertowClient


    public IoFuture<ClientConnection> connect(InetSocketAddress bindAddress, final URI uri, final XnioIoThread ioThread, XnioSsl ssl, Pool<ByteBuffer> bufferPool, OptionMap options) {
        ClientProvider provider = getClientProvider(uri);
        final FutureResult<ClientConnection> result = new FutureResult<>();
        provider.connect(new ClientCallback<ClientConnection>() {
            @Override
            public void completed(ClientConnection r) {
                result.setResult(r);
            }

            @Override
            public void failed(IOException e) {
                result.setException(e);
            }
        }, bindAddress, uri, ioThread, ssl, bufferPool, options);
        return result.getIoFuture();
    }

    public IoFuture<ClientConnection> connect(InetSocketAddress bindAddress, final URI uri, final XnioIoThread ioThread, XnioSsl ssl, Pool<ByteBuffer> bufferPool, OptionMap options) {
        ClientProvider provider = getClientProvider(uri);
        final FutureResult<ClientConnection> result = new FutureResult<ClientConnection>();
        provider.connect(new ClientCallback<ClientConnection>() {
            @Override
            public void completed(ClientConnection r) {
                result.setResult(r);
            }

            @Override
            public void failed(IOException e) {
                result.setException(e);
            }
        }, bindAddress, uri, ioThread, ssl, bufferPool, options);
        return result.getIoFuture();
    }

Replace Generic With Diamond FutureResult<ClientConnection> with FutureResult<> in method public connect(bindAddress InetSocketAddress, uri URI, ioThread XnioIoThread, ssl XnioSsl, bufferPool Pool<ByteBuffer>, options OptionMap) : IoFuture<ClientConnection> from class io.undertow.client.UndertowClient


    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<>(Arrays.asList(new String[]{"ajp"}));
    }

    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<String>(Arrays.asList(new String[]{"ajp"}));
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public handlesSchemes() : Set<String> from class io.undertow.client.ajp.AjpClientProvider


    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<>(Arrays.asList(new String[]{"http", "https"}));
    }

    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<String>(Arrays.asList(new String[]{"http", "https"}));
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public handlesSchemes() : Set<String> from class io.undertow.client.http.HttpClientProvider


    /**
     * This is a bit of hack to enable the parser to get access to the HttpString's that are sorted
     * in the static fields of the relevant classes. This means that in most cases a HttpString comparison
     * will take the fast path == route, as they will be the same object
     *
     * @return
     */
    protected static Map<String, HttpString> httpStrings() {
        final Map<String, HttpString> results = new HashMap<>();
        final Class[] classs = {Headers.class, Methods.class, Protocols.class};

        for (Class<?> c : classs) {
            for (Field field : c.getDeclaredFields()) {
                if (field.getType().equals(HttpString.class)) {
                    field.setAccessible(true);
                    HttpString result = null;
                    try {
                        result = (HttpString) field.get(null);
                        results.put(result.toString(), result);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return results;

    }

    /**
     * This is a bit of hack to enable the parser to get access to the HttpString's that are sorted
     * in the static fields of the relevant classes. This means that in most cases a HttpString comparison
     * will take the fast path == route, as they will be the same object
     *
     * @return
     */
    protected static Map<String, HttpString> httpStrings() {
        final Map<String, HttpString> results = new HashMap<String, HttpString>();
        final Class[] classs = {Headers.class, Methods.class, Protocols.class};

        for (Class<?> c : classs) {
            for (Field field : c.getDeclaredFields()) {
                if (field.getType().equals(HttpString.class)) {
                    field.setAccessible(true);
                    HttpString result = null;
                    try {
                        result = (HttpString) field.get(null);
                        results.put(result.toString(), result);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return results;

    }

Replace Generic With Diamond HashMap<String,HttpString> with HashMap<> in method protected httpStrings() : Map<String,HttpString> from class io.undertow.client.http.HttpResponseParser


    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<>(Arrays.asList(new String[]{"spdy"}));
    }

    @Override
    public Set<String> handlesSchemes() {
        return new HashSet<String>(Arrays.asList(new String[]{"spdy"}));
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public handlesSchemes() : Set<String> from class io.undertow.client.spdy.SpdyClientProvider


                    @Override
                    public void handleEvent(StreamSourceChannel channel) {

                        if (spdySelectionProvider.selected != null) {
                            if (spdySelectionProvider.selected.equals(HTTP_1_1)) {
                                sslConnection.getSourceChannel().suspendReads();
                                spdyFailedListener.handleEvent(sslConnection);
                                return;
                            } else if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                listener.completed(createSpdyChannel(connection, bufferPool));
                            }
                        } else {
                            ByteBuffer buf = ByteBuffer.allocate(100);
                            try {
                                int read = channel.read(buf);
                                if (read > 0) {
                                    PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(connection.getSourceChannel().getConduit());
                                    pb.pushBack(new ImmediatePooled<>(buf));
                                    connection.getSourceChannel().setConduit(pb);
                                }
                                if ((spdySelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(spdySelectionProvider.selected)) {
                                    sslConnection.getSourceChannel().suspendReads();
                                    spdyFailedListener.handleEvent(sslConnection);
                                    return;
                                } else if (spdySelectionProvider.selected != null) {
                                    //we have spdy
                                    if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                        listener.completed(createSpdyChannel(connection, bufferPool));
                                    }
                                }
                            } catch (IOException e) {
                                listener.failed(e);
                            }
                        }
                    }

                    @Override
                    public void handleEvent(StreamSourceChannel channel) {

                        if (spdySelectionProvider.selected != null) {
                            if (spdySelectionProvider.selected.equals(HTTP_1_1)) {
                                sslConnection.getSourceChannel().suspendReads();
                                spdyFailedListener.handleEvent(sslConnection);
                                return;
                            } else if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                listener.completed(createSpdyChannel(connection, bufferPool));
                            }
                        } else {
                            ByteBuffer buf = ByteBuffer.allocate(100);
                            try {
                                int read = channel.read(buf);
                                if (read > 0) {
                                    PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(connection.getSourceChannel().getConduit());
                                    pb.pushBack(new ImmediatePooled<ByteBuffer>(buf));
                                    connection.getSourceChannel().setConduit(pb);
                                }
                                if ((spdySelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(spdySelectionProvider.selected)) {
                                    sslConnection.getSourceChannel().suspendReads();
                                    spdyFailedListener.handleEvent(sslConnection);
                                    return;
                                } else if (spdySelectionProvider.selected != null) {
                                    //we have spdy
                                    if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                        listener.completed(createSpdyChannel(connection, bufferPool));
                                    }
                                }
                            } catch (IOException e) {
                                listener.failed(e);
                            }
                        }
                    }

Replace Generic With Diamond ImmediatePooled<ByteBuffer> with ImmediatePooled<> in method public handleEvent(channel StreamSourceChannel) : void from class io.undertow.client.spdy.SpdyClientProvider.handlePotentialSpdyConnection.set.new ChannelListener<StreamSourceChannel>


    /**
     * Not really part of the public API, but is used by the HTTP client to initiate a SPDY connection for HTTPS requests.
     */
    public static void handlePotentialSpdyConnection(final StreamConnection connection, final ClientCallback<ClientConnection> listener, final Pool<ByteBuffer> bufferPool, final OptionMap options, final ChannelListener<SslConnection> spdyFailedListener) {

        final SslConnection sslConnection = (SslConnection) connection;
        final SSLEngine sslEngine = JsseXnioSsl.getSslEngine(sslConnection);

        String existing = (String) sslEngine.getSession().getValue(PROTOCOL_KEY);
        if(existing != null) {
            if (existing.equals(SPDY_3) || existing.equals(SPDY_3_1)) {
                listener.completed(createSpdyChannel(connection, bufferPool));
            } else {
                sslConnection.getSourceChannel().suspendReads();
                spdyFailedListener.handleEvent(sslConnection);
            }
        } else {

            final SpdySelectionProvider spdySelectionProvider = new SpdySelectionProvider(sslEngine);
            try {
                NPN_PUT_METHOD.invoke(null, sslEngine, spdySelectionProvider);
            } catch (Exception e) {
                spdyFailedListener.handleEvent(sslConnection);
                return;
            }

            try {
                sslConnection.startHandshake();
                sslConnection.getSourceChannel().getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
                    @Override
                    public void handleEvent(StreamSourceChannel channel) {

                        if (spdySelectionProvider.selected != null) {
                            if (spdySelectionProvider.selected.equals(HTTP_1_1)) {
                                sslConnection.getSourceChannel().suspendReads();
                                spdyFailedListener.handleEvent(sslConnection);
                                return;
                            } else if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                listener.completed(createSpdyChannel(connection, bufferPool));
                            }
                        } else {
                            ByteBuffer buf = ByteBuffer.allocate(100);
                            try {
                                int read = channel.read(buf);
                                if (read > 0) {
                                    PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(connection.getSourceChannel().getConduit());
                                    pb.pushBack(new ImmediatePooled<>(buf));
                                    connection.getSourceChannel().setConduit(pb);
                                }
                                if ((spdySelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(spdySelectionProvider.selected)) {
                                    sslConnection.getSourceChannel().suspendReads();
                                    spdyFailedListener.handleEvent(sslConnection);
                                    return;
                                } else if (spdySelectionProvider.selected != null) {
                                    //we have spdy
                                    if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                        listener.completed(createSpdyChannel(connection, bufferPool));
                                    }
                                }
                            } catch (IOException e) {
                                listener.failed(e);
                            }
                        }
                    }

                });
                sslConnection.getSourceChannel().resumeReads();
            } catch (IOException e) {
                listener.failed(e);
            }
        }

    }

    /**
     * Not really part of the public API, but is used by the HTTP client to initiate a SPDY connection for HTTPS requests.
     */
    public static void handlePotentialSpdyConnection(final StreamConnection connection, final ClientCallback<ClientConnection> listener, final Pool<ByteBuffer> bufferPool, final OptionMap options, final ChannelListener<SslConnection> spdyFailedListener) {

        final SslConnection sslConnection = (SslConnection) connection;
        final SSLEngine sslEngine = JsseXnioSsl.getSslEngine(sslConnection);

        String existing = (String) sslEngine.getSession().getValue(PROTOCOL_KEY);
        if(existing != null) {
            if (existing.equals(SPDY_3) || existing.equals(SPDY_3_1)) {
                listener.completed(createSpdyChannel(connection, bufferPool));
            } else {
                sslConnection.getSourceChannel().suspendReads();
                spdyFailedListener.handleEvent(sslConnection);
            }
        } else {

            final SpdySelectionProvider spdySelectionProvider = new SpdySelectionProvider(sslEngine);
            try {
                NPN_PUT_METHOD.invoke(null, sslEngine, spdySelectionProvider);
            } catch (Exception e) {
                spdyFailedListener.handleEvent(sslConnection);
                return;
            }

            try {
                sslConnection.startHandshake();
                sslConnection.getSourceChannel().getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
                    @Override
                    public void handleEvent(StreamSourceChannel channel) {

                        if (spdySelectionProvider.selected != null) {
                            if (spdySelectionProvider.selected.equals(HTTP_1_1)) {
                                sslConnection.getSourceChannel().suspendReads();
                                spdyFailedListener.handleEvent(sslConnection);
                                return;
                            } else if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                listener.completed(createSpdyChannel(connection, bufferPool));
                            }
                        } else {
                            ByteBuffer buf = ByteBuffer.allocate(100);
                            try {
                                int read = channel.read(buf);
                                if (read > 0) {
                                    PushBackStreamSourceConduit pb = new PushBackStreamSourceConduit(connection.getSourceChannel().getConduit());
                                    pb.pushBack(new ImmediatePooled<ByteBuffer>(buf));
                                    connection.getSourceChannel().setConduit(pb);
                                }
                                if ((spdySelectionProvider.selected == null && read > 0) || HTTP_1_1.equals(spdySelectionProvider.selected)) {
                                    sslConnection.getSourceChannel().suspendReads();
                                    spdyFailedListener.handleEvent(sslConnection);
                                    return;
                                } else if (spdySelectionProvider.selected != null) {
                                    //we have spdy
                                    if (spdySelectionProvider.selected.equals(SPDY_3) || spdySelectionProvider.selected.equals(SPDY_3_1)) {
                                        listener.completed(createSpdyChannel(connection, bufferPool));
                                    }
                                }
                            } catch (IOException e) {
                                listener.failed(e);
                            }
                        }
                    }

                });
                sslConnection.getSourceChannel().resumeReads();
            } catch (IOException e) {
                listener.failed(e);
            }
        }

    }

Replace Generic With Diamond ImmediatePooled<ByteBuffer> with ImmediatePooled<> in method public handlePotentialSpdyConnection(connection StreamConnection, listener ClientCallback<ClientConnection>, bufferPool Pool<ByteBuffer>, options OptionMap, spdyFailedListener ChannelListener<SslConnection>) : void from class io.undertow.client.spdy.SpdyClientProvider


    private void createLastChunk(final boolean writeFinal) throws UnsupportedEncodingException {
        Pooled<ByteBuffer> lastChunkBufferPooled =  bufferPool.allocate();
        ByteBuffer lastChunkBuffer = lastChunkBufferPooled.getResource();
        if (writeFinal) {
            lastChunkBuffer.put(CRLF);
        } else if(chunkingSepBuffer.hasRemaining()) {
            //the end of chunk /r/n has not been written yet
            //just add it to this buffer to make managing state easier
            lastChunkBuffer.put(chunkingSepBuffer);
        }
        lastChunkBuffer.put(LAST_CHUNK);
        //we just assume it will fit
        HeaderMap trailers = attachable.getAttachment(HttpAttachments.RESPONSE_TRAILERS);
        if (trailers != null && trailers.size() != 0) {
            for (HeaderValues trailer : trailers) {
                for (String val : trailer) {
                    trailer.getHeaderName().appendTo(lastChunkBuffer);
                    lastChunkBuffer.put((byte) ':');
                    lastChunkBuffer.put((byte) ' ');
                    lastChunkBuffer.put(val.getBytes("US-ASCII"));
                    lastChunkBuffer.put(CRLF);
                }
            }
            lastChunkBuffer.put(CRLF);
        } else {
            lastChunkBuffer.put(CRLF);
        }
        //horrible hack
        //there is a situation where we can get a buffer leak here if the connection is terminated abnormaly
        //this should be fixed once this channel has its lifecycle tied to the connection, same as fixed length
        lastChunkBuffer.flip();
        ByteBuffer data = ByteBuffer.allocate(lastChunkBuffer.remaining());
        data.put(lastChunkBuffer);
        data.flip();
        this.lastChunkBuffer = new ImmediatePooled<>(data);

        lastChunkBufferPooled.free();
    }

    private void createLastChunk(final boolean writeFinal) throws UnsupportedEncodingException {
        Pooled<ByteBuffer> lastChunkBufferPooled =  bufferPool.allocate();
        ByteBuffer lastChunkBuffer = lastChunkBufferPooled.getResource();
        if (writeFinal) {
            lastChunkBuffer.put(CRLF);
        } else if(chunkingSepBuffer.hasRemaining()) {
            //the end of chunk /r/n has not been written yet
            //just add it to this buffer to make managing state easier
            lastChunkBuffer.put(chunkingSepBuffer);
        }
        lastChunkBuffer.put(LAST_CHUNK);
        //we just assume it will fit
        HeaderMap trailers = attachable.getAttachment(HttpAttachments.RESPONSE_TRAILERS);
        if (trailers != null && trailers.size() != 0) {
            for (HeaderValues trailer : trailers) {
                for (String val : trailer) {
                    trailer.getHeaderName().appendTo(lastChunkBuffer);
                    lastChunkBuffer.put((byte) ':');
                    lastChunkBuffer.put((byte) ' ');
                    lastChunkBuffer.put(val.getBytes("US-ASCII"));
                    lastChunkBuffer.put(CRLF);
                }
            }
            lastChunkBuffer.put(CRLF);
        } else {
            lastChunkBuffer.put(CRLF);
        }
        //horrible hack
        //there is a situation where we can get a buffer leak here if the connection is terminated abnormaly
        //this should be fixed once this channel has its lifecycle tied to the connection, same as fixed length
        lastChunkBuffer.flip();
        ByteBuffer data = ByteBuffer.allocate(lastChunkBuffer.remaining());
        data.put(lastChunkBuffer);
        data.flip();
        this.lastChunkBuffer = new ImmediatePooled<ByteBuffer>(data);

        lastChunkBufferPooled.free();
    }

Replace Generic With Diamond ImmediatePooled<ByteBuffer> with ImmediatePooled<> in method private createLastChunk(writeFinal boolean) : void from class io.undertow.conduits.ChunkedStreamSinkConduit


    protected ChunkedStreamSourceConduit(final StreamSourceConduit next, final BufferWrapper bufferWrapper, final ConduitListener<? super ChunkedStreamSourceConduit> finishListener, final Attachable attachable, final HttpServerExchange exchange) {
        super(next);
        this.bufferWrapper = bufferWrapper;
        this.finishListener = finishListener;
        this.remainingAllowed = Long.MIN_VALUE;
        this.chunkReader = new ChunkReader<>(attachable, HttpAttachments.REQUEST_TRAILERS, finishListener, this);
        this.exchange = exchange;
    }

    protected ChunkedStreamSourceConduit(final StreamSourceConduit next, final BufferWrapper bufferWrapper, final ConduitListener<? super ChunkedStreamSourceConduit> finishListener, final Attachable attachable, final HttpServerExchange exchange) {
        super(next);
        this.bufferWrapper = bufferWrapper;
        this.finishListener = finishListener;
        this.remainingAllowed = Long.MIN_VALUE;
        this.chunkReader = new ChunkReader<ChunkedStreamSourceConduit>(attachable, HttpAttachments.REQUEST_TRAILERS, finishListener, this);
        this.exchange = exchange;
    }

Replace Generic With Diamond ChunkReader<ChunkedStreamSourceConduit> with ChunkReader<> in method protected ChunkedStreamSourceConduit(next StreamSourceConduit, bufferWrapper BufferWrapper, finishListener ConduitListener<? super ChunkedStreamSourceConduit>, attachable Attachable, exchange HttpServerExchange) from class io.undertow.conduits.ChunkedStreamSourceConduit


    /**
     * Construct a new instance.
     *
     * @param next           the channel to wrap
     * @param finishListener The finish listener
     * @param attachable     The attachable
     */
    public PreChunkedStreamSinkConduit(final StreamSinkConduit next, final ConduitListener<? super PreChunkedStreamSinkConduit> finishListener, final Attachable attachable) {
        super(next);
        //we don't want the reader to call the finish listener, so we pass null
        this.chunkReader = new ChunkReader<>(attachable, HttpAttachments.RESPONSE_TRAILERS, null, this);
        this.finishListener = finishListener;
    }

    /**
     * Construct a new instance.
     *
     * @param next           the channel to wrap
     * @param finishListener The finish listener
     * @param attachable     The attachable
     */
    public PreChunkedStreamSinkConduit(final StreamSinkConduit next, final ConduitListener<? super PreChunkedStreamSinkConduit> finishListener, final Attachable attachable) {
        super(next);
        //we don't want the reader to call the finish listener, so we pass null
        this.chunkReader = new ChunkReader<PreChunkedStreamSinkConduit>(attachable, HttpAttachments.RESPONSE_TRAILERS, null, this);
        this.finishListener = finishListener;
    }

Replace Generic With Diamond ChunkReader<PreChunkedStreamSinkConduit> with ChunkReader<> in method public PreChunkedStreamSinkConduit(next StreamSinkConduit, finishListener ConduitListener<? super PreChunkedStreamSinkConduit>, attachable Attachable) from class io.undertow.conduits.PreChunkedStreamSinkConduit


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.AuthenticationRequiredPredicate.Builder


        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<>();
            return params;
        }

        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<String>();
            return params;
        }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public requiredParameters() : Set<String> from class io.undertow.predicate.AuthenticationRequiredPredicate.Builder


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            params.put("value", ExchangeAttribute.class);
            params.put("search", String[].class);
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            params.put("value", ExchangeAttribute.class);
            params.put("search", String[].class);
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.ContainsPredicate.Builder


        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<>();
            params.add("value");
            params.add("search");
            return params;
        }

        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<String>();
            params.add("value");
            params.add("search");
            return params;
        }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public requiredParameters() : Set<String> from class io.undertow.predicate.ContainsPredicate.Builder


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            params.put("value", ExchangeAttribute[].class);
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            params.put("value", ExchangeAttribute[].class);
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.EqualsPredicate.Builder


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            params.put("value", ExchangeAttribute.class);
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            params.put("value", ExchangeAttribute.class);
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.ExistsPredicate.Builder


    public PathMatchPredicate(final String... paths) {
        PathMatcher<Boolean> matcher = new PathMatcher<>();
        for(String path : paths) {
            if(!path.startsWith("/")) {
                matcher.addExactPath("/" + path, Boolean.TRUE);
            } else {
                matcher.addExactPath(path, Boolean.TRUE);
            }
        }
        this.pathMatcher = matcher;
    }

    public PathMatchPredicate(final String... paths) {
        PathMatcher<Boolean> matcher = new PathMatcher<Boolean>();
        for(String path : paths) {
            if(!path.startsWith("/")) {
                matcher.addExactPath("/" + path, Boolean.TRUE);
            } else {
                matcher.addExactPath(path, Boolean.TRUE);
            }
        }
        this.pathMatcher = matcher;
    }

Replace Generic With Diamond PathMatcher<Boolean> with PathMatcher<> in method public PathMatchPredicate(paths String...) from class io.undertow.predicate.PathMatchPredicate


    public PathPrefixPredicate(final String... paths) {
        PathMatcher<Boolean> matcher = new PathMatcher<>();
        for(String path : paths) {
            if(!path.startsWith("/")) {
                matcher.addPrefixPath("/" + path, Boolean.TRUE);
            } else {
                matcher.addPrefixPath(path, Boolean.TRUE);
            }
        }
        this.pathMatcher = matcher;
    }

    public PathPrefixPredicate(final String... paths) {
        PathMatcher<Boolean> matcher = new PathMatcher<Boolean>();
        for(String path : paths) {
            if(!path.startsWith("/")) {
                matcher.addPrefixPath("/" + path, Boolean.TRUE);
            } else {
                matcher.addPrefixPath(path, Boolean.TRUE);
            }
        }
        this.pathMatcher = matcher;
    }

Replace Generic With Diamond PathMatcher<Boolean> with PathMatcher<> in method public PathPrefixPredicate(paths String...) from class io.undertow.predicate.PathPrefixPredicate


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            params.put("value", String.class);
            params.put("match", ExchangeAttribute.class);
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            params.put("value", String.class);
            params.put("match", ExchangeAttribute.class);
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.PathTemplatePredicate.Builder


        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<>();
            params.add("value");
            return params;
        }

        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<String>();
            params.add("value");
            return params;
        }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public requiredParameters() : Set<String> from class io.undertow.predicate.PathTemplatePredicate.Builder


    @Override
    public boolean resolve(final HttpServerExchange exchange) {
        final Map<String, String> params = new HashMap<>();
        boolean result = this.value.matches(attribute.readAttribute(exchange), params);
        if (result) {
            Map<String, Object> context = exchange.getAttachment(PREDICATE_CONTEXT);
            if (context != null) {
                context.putAll(params);
            }
        }
        return result;
    }

    @Override
    public boolean resolve(final HttpServerExchange exchange) {
        final Map<String, String> params = new HashMap<String, String>();
        boolean result = this.value.matches(attribute.readAttribute(exchange), params);
        if (result) {
            Map<String, Object> context = exchange.getAttachment(PREDICATE_CONTEXT);
            if (context != null) {
                context.putAll(params);
            }
        }
        return result;
    }

Replace Generic With Diamond HashMap<String,String> with HashMap<> in method public resolve(exchange HttpServerExchange) : boolean from class io.undertow.predicate.PathTemplatePredicate


    private static Map<String, PredicateBuilder> loadBuilders(final ClassLoader classLoader) {
        ServiceLoader<PredicateBuilder> loader = ServiceLoader.load(PredicateBuilder.class, classLoader);
        final Map<String, PredicateBuilder> ret = new HashMap<>();
        for (PredicateBuilder builder : loader) {
            if (ret.containsKey(builder.name())) {
                if (ret.get(builder.name()).getClass() != builder.getClass()) {
                    throw UndertowMessages.MESSAGES.moreThanOnePredicateWithName(builder.name(), builder.getClass(), ret.get(builder.name()).getClass());
                }
            } else {
                ret.put(builder.name(), builder);
            }
        }
        return ret;
    }

    private static Map<String, PredicateBuilder> loadBuilders(final ClassLoader classLoader) {
        ServiceLoader<PredicateBuilder> loader = ServiceLoader.load(PredicateBuilder.class, classLoader);
        final Map<String, PredicateBuilder> ret = new HashMap<String, PredicateBuilder>();
        for (PredicateBuilder builder : loader) {
            if (ret.containsKey(builder.name())) {
                if (ret.get(builder.name()).getClass() != builder.getClass()) {
                    throw UndertowMessages.MESSAGES.moreThanOnePredicateWithName(builder.name(), builder.getClass(), ret.get(builder.name()).getClass());
                }
            } else {
                ret.put(builder.name(), builder);
            }
        }
        return ret;
    }

Replace Generic With Diamond HashMap<String,PredicateBuilder> with HashMap<> in method private loadBuilders(classLoader ClassLoader) : Map<String,PredicateBuilder> from class io.undertow.predicate.PredicateParser


    private static Object parsePredicate(final String string, final Token token, final Deque<Token> tokens, final Map<String, PredicateBuilder> builders, final ExchangeAttributeParser attributeParser) {
        if (token.token.equals("true")) {
            return new PredicateNode(TruePredicate.instance());
        } else if (token.token.equals("false")) {
            return new PredicateNode(FalsePredicate.instance());
        } else {
            PredicateBuilder builder = builders.get(token.token);
            if (builder == null) {

                throw error(string, token.position, "no predicate named " + token.token + " known predicates: " + builders.keySet());
            }
            Token next = tokens.peek();
            if (next.token.equals("[")) {
                final Map<String, Object> values = new HashMap<>();

                tokens.poll();
                next = tokens.poll();
                if (next == null) {
                    throw error(string, string.length(), "Unexpected end of input");
                }
                if (next.token.equals("{")) {
                    return handleSingleArrayValue(string, builder, tokens, next, attributeParser);
                }
                while (!next.token.equals("]")) {
                    Token equals = tokens.poll();
                    if (!equals.token.equals("=")) {
                        if (equals.token.equals("]") && values.isEmpty()) {
                            //single value case
                            return handleSingleValue(string, builder, next, attributeParser);
                        } else if (equals.token.equals(",")) {
                            tokens.push(equals);
                            tokens.push(next);
                            return handleSingleVarArgsValue(string, builder, tokens, next, attributeParser);
                        }
                        throw error(string, equals.position, "Unexpected token");
                    }
                    Token value = tokens.poll();
                    if (value == null) {
                        throw error(string, string.length(), "Unexpected end of input");
                    }
                    if (value.token.equals("{")) {
                        values.put(next.token, readArrayType(string, tokens, next, builder, attributeParser, "}"));
                    } else {
                        if (isOperator(value.token) || isSpecialChar(value.token)) {
                            throw error(string, value.position, "Unexpected token");
                        }

                        Class<?> type = builder.parameters().get(next.token);
                        if (type == null) {
                            throw error(string, next.position, "Unexpected parameter " + next.token);
                        }
                        values.put(next.token, coerceToType(string, value, type, attributeParser));
                    }

                    next = tokens.poll();
                    if (next == null) {
                        throw error(string, string.length(), "Unexpected end of input");
                    }
                    if (!next.token.equals("]")) {
                        if (!next.token.equals(",")) {
                            throw error(string, string.length(), "Expecting , or ]");
                        }
                        next = tokens.poll();
                        if (next == null) {
                            throw error(string, string.length(), "Unexpected end of input");
                        }
                    }
                }
                checkParameters(string, next.position, values, builder);
                return new BuilderNode(builder, values);

            } else {
                if (isSpecialChar(next.token)) {
                    throw error(string, next.position, "Unexpected character");
                }
                return new BuilderNode(builder);
            }
        }
    }

    private static Object parsePredicate(final String string, final Token token, final Deque<Token> tokens, final Map<String, PredicateBuilder> builders, final ExchangeAttributeParser attributeParser) {
        if (token.token.equals("true")) {
            return new PredicateNode(TruePredicate.instance());
        } else if (token.token.equals("false")) {
            return new PredicateNode(FalsePredicate.instance());
        } else {
            PredicateBuilder builder = builders.get(token.token);
            if (builder == null) {

                throw error(string, token.position, "no predicate named " + token.token + " known predicates: " + builders.keySet());
            }
            Token next = tokens.peek();
            if (next.token.equals("[")) {
                final Map<String, Object> values = new HashMap<String, Object>();

                tokens.poll();
                next = tokens.poll();
                if (next == null) {
                    throw error(string, string.length(), "Unexpected end of input");
                }
                if (next.token.equals("{")) {
                    return handleSingleArrayValue(string, builder, tokens, next, attributeParser);
                }
                while (!next.token.equals("]")) {
                    Token equals = tokens.poll();
                    if (!equals.token.equals("=")) {
                        if (equals.token.equals("]") && values.isEmpty()) {
                            //single value case
                            return handleSingleValue(string, builder, next, attributeParser);
                        } else if (equals.token.equals(",")) {
                            tokens.push(equals);
                            tokens.push(next);
                            return handleSingleVarArgsValue(string, builder, tokens, next, attributeParser);
                        }
                        throw error(string, equals.position, "Unexpected token");
                    }
                    Token value = tokens.poll();
                    if (value == null) {
                        throw error(string, string.length(), "Unexpected end of input");
                    }
                    if (value.token.equals("{")) {
                        values.put(next.token, readArrayType(string, tokens, next, builder, attributeParser, "}"));
                    } else {
                        if (isOperator(value.token) || isSpecialChar(value.token)) {
                            throw error(string, value.position, "Unexpected token");
                        }

                        Class<?> type = builder.parameters().get(next.token);
                        if (type == null) {
                            throw error(string, next.position, "Unexpected parameter " + next.token);
                        }
                        values.put(next.token, coerceToType(string, value, type, attributeParser));
                    }

                    next = tokens.poll();
                    if (next == null) {
                        throw error(string, string.length(), "Unexpected end of input");
                    }
                    if (!next.token.equals("]")) {
                        if (!next.token.equals(",")) {
                            throw error(string, string.length(), "Expecting , or ]");
                        }
                        next = tokens.poll();
                        if (next == null) {
                            throw error(string, string.length(), "Unexpected end of input");
                        }
                    }
                }
                checkParameters(string, next.position, values, builder);
                return new BuilderNode(builder, values);

            } else {
                if (isSpecialChar(next.token)) {
                    throw error(string, next.position, "Unexpected character");
                }
                return new BuilderNode(builder);
            }
        }
    }

Replace Generic With Diamond HashMap<String,Object> with HashMap<> in method private parsePredicate(string String, token Token, tokens Deque<Token>, builders Map<String,PredicateBuilder>, attributeParser ExchangeAttributeParser) : Object from class io.undertow.predicate.PredicateParser


    private static Object readArrayType(final String string, final Deque<Token> tokens, Token paramName, PredicateBuilder builder, final ExchangeAttributeParser attributeParser, String expectedEndToken) {
        Class<?> type = builder.parameters().get(paramName.token);
        if (type == null) {
            throw error(string, paramName.position, "no parameter called " + paramName.token);
        } else if (!type.isArray()) {
            throw error(string, paramName.position, "parameter is not an array type " + paramName.token);
        }

        Class<?> componentType = type.getComponentType();
        final List<Object> values = new ArrayList<>();
        Token token = tokens.poll();
        while (token != null) {
            Token commaOrEnd = tokens.poll();
            values.add(coerceToType(string, token, componentType, attributeParser));
            if (commaOrEnd.token.equals(expectedEndToken)) {
                Object array = Array.newInstance(componentType, values.size());
                for (int i = 0; i < values.size(); ++i) {
                    Array.set(array, i, values.get(i));
                }
                return array;
            } else if (!commaOrEnd.token.equals(",")) {
                throw error(string, commaOrEnd.position, "expected either , or }");
            }
            token = tokens.poll();
        }
        throw error(string, string.length(), "unexpected end of input in array");
    }

    private static Object readArrayType(final String string, final Deque<Token> tokens, Token paramName, PredicateBuilder builder, final ExchangeAttributeParser attributeParser, String expectedEndToken) {
        Class<?> type = builder.parameters().get(paramName.token);
        if (type == null) {
            throw error(string, paramName.position, "no parameter called " + paramName.token);
        } else if (!type.isArray()) {
            throw error(string, paramName.position, "parameter is not an array type " + paramName.token);
        }

        Class<?> componentType = type.getComponentType();
        final List<Object> values = new ArrayList<Object>();
        Token token = tokens.poll();
        while (token != null) {
            Token commaOrEnd = tokens.poll();
            values.add(coerceToType(string, token, componentType, attributeParser));
            if (commaOrEnd.token.equals(expectedEndToken)) {
                Object array = Array.newInstance(componentType, values.size());
                for (int i = 0; i < values.size(); ++i) {
                    Array.set(array, i, values.get(i));
                }
                return array;
            } else if (!commaOrEnd.token.equals(",")) {
                throw error(string, commaOrEnd.position, "expected either , or }");
            }
            token = tokens.poll();
        }
        throw error(string, string.length(), "unexpected end of input in array");
    }

Replace Generic With Diamond ArrayList<Object> with ArrayList<> in method private readArrayType(string String, tokens Deque<Token>, paramName Token, builder PredicateBuilder, attributeParser ExchangeAttributeParser, expectedEndToken String) : Object from class io.undertow.predicate.PredicateParser


    private static void checkParameters(final String string, int pos, final Map<String, Object> values, final PredicateBuilder builder) {
        final Set<String> required = new HashSet<>(builder.requiredParameters());
        for (String key : values.keySet()) {
            required.remove(key);
        }
        if (!required.isEmpty()) {
            throw error(string, pos, "Missing required parameters " + required);
        }
    }

    private static void checkParameters(final String string, int pos, final Map<String, Object> values, final PredicateBuilder builder) {
        final Set<String> required = new HashSet<String>(builder.requiredParameters());
        for (String key : values.keySet()) {
            required.remove(key);
        }
        if (!required.isEmpty()) {
            throw error(string, pos, "Missing required parameters " + required);
        }
    }

Replace Generic With Diamond HashSet<String> with HashSet<> in method private checkParameters(string String, pos int, values Map<String,Object>, builder PredicateBuilder) : void from class io.undertow.predicate.PredicateParser


    static Deque<Token> tokenize(final String string) {
        char currentStringDelim = 0;
        boolean inVariable = false;

        int pos = 0;
        StringBuilder current = new StringBuilder();
        Deque<Token> ret = new ArrayDeque<>();
        while (pos < string.length()) {
            char c = string.charAt(pos);
            if (currentStringDelim != 0) {
                if (c == currentStringDelim && current.charAt(current.length() - 1) != '\\') {
                    ret.add(new Token(current.toString(), pos));
                    current.setLength(0);
                    currentStringDelim = 0;
                } else {
                    current.append(c);
                }
            } else {
                switch (c) {
                    case ' ':
                    case '\t': {
                        if (current.length() != 0) {
                            ret.add(new Token(current.toString(), pos));
                            current.setLength(0);
                        }
                        break;
                    }
                    case '(':
                    case ')':
                    case ',':
                    case '=':
                    case '[':
                    case ']':
                    case '{':
                    case '}': {
                        if (inVariable) {
                            current.append(c);
                            if (c == '}') {
                                inVariable = false;
                            }
                        } else {
                            if (current.length() != 0) {
                                ret.add(new Token(current.toString(), pos));
                                current.setLength(0);
                            }
                            ret.add(new Token("" + c, pos));
                        }
                        break;
                    }
                    case '"':
                    case '\'': {
                        if (current.length() != 0) {
                            throw error(string, pos, "Unexpected token");
                        }
                        currentStringDelim = c;
                        break;
                    }
                    case '%': {
                        current.append(c);
                        if (string.charAt(pos + 1) == '{') {
                            inVariable = true;
                        }
                        break;
                    }
                    default:
                        current.append(c);
                }
            }
            ++pos;
        }
        if (current.length() > 0) {
            ret.add(new Token(current.toString(), string.length()));
        }
        return ret;
    }

    static Deque<Token> tokenize(final String string) {
        char currentStringDelim = 0;
        boolean inVariable = false;

        int pos = 0;
        StringBuilder current = new StringBuilder();
        Deque<Token> ret = new ArrayDeque<Token>();
        while (pos < string.length()) {
            char c = string.charAt(pos);
            if (currentStringDelim != 0) {
                if (c == currentStringDelim && current.charAt(current.length() - 1) != '\\') {
                    ret.add(new Token(current.toString(), pos));
                    current.setLength(0);
                    currentStringDelim = 0;
                } else {
                    current.append(c);
                }
            } else {
                switch (c) {
                    case ' ':
                    case '\t': {
                        if (current.length() != 0) {
                            ret.add(new Token(current.toString(), pos));
                            current.setLength(0);
                        }
                        break;
                    }
                    case '(':
                    case ')':
                    case ',':
                    case '=':
                    case '[':
                    case ']':
                    case '{':
                    case '}': {
                        if (inVariable) {
                            current.append(c);
                            if (c == '}') {
                                inVariable = false;
                            }
                        } else {
                            if (current.length() != 0) {
                                ret.add(new Token(current.toString(), pos));
                                current.setLength(0);
                            }
                            ret.add(new Token("" + c, pos));
                        }
                        break;
                    }
                    case '"':
                    case '\'': {
                        if (current.length() != 0) {
                            throw error(string, pos, "Unexpected token");
                        }
                        currentStringDelim = c;
                        break;
                    }
                    case '%': {
                        current.append(c);
                        if (string.charAt(pos + 1) == '{') {
                            inVariable = true;
                        }
                        break;
                    }
                    default:
                        current.append(c);
                }
            }
            ++pos;
        }
        if (current.length() > 0) {
            ret.add(new Token(current.toString(), string.length()));
        }
        return ret;
    }

Replace Generic With Diamond ArrayDeque<Token> with ArrayDeque<> in method package tokenize(string String) : Deque<Token> from class io.undertow.predicate.PredicateParser


        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<>();
            params.put("pattern", String.class);
            params.put("value", ExchangeAttribute.class);
            params.put("full-match", Boolean.class);
            return params;
        }

        @Override
        public Map<String, Class<?>> parameters() {
            final Map<String, Class<?>> params = new HashMap<String, Class<?>>();
            params.put("pattern", String.class);
            params.put("value", ExchangeAttribute.class);
            params.put("full-match", Boolean.class);
            return params;
        }

Replace Generic With Diamond HashMap<String,Class<?>> with HashMap<> in method public parameters() : Map<String,Class<?>> from class io.undertow.predicate.RegularExpressionPredicate.Builder


        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<>();
            params.add("pattern");
            return params;
        }

        @Override
        public Set<String> requiredParameters() {
            final Set<String> params = new HashSet<String>();
            params.add("pattern");
            return params;
        }

Replace Generic With Diamond HashSet<String> with HashSet<> in method public requiredParameters() : Set<String> from class io.undertow.predicate.RegularExpressionPredicate.Builder


    public AuthenticationMechanismOutcome handleDigestHeader(HttpServerExchange exchange, final SecurityContext securityContext) {
        DigestContext context = exchange.getAttachment(DigestContext.ATTACHMENT_KEY);
        Map<DigestAuthorizationToken, String> parsedHeader = context.getParsedHeader();
        // Step 1 - Verify the set of tokens received to ensure valid values.
        Set<DigestAuthorizationToken> mandatoryTokens = new HashSet<>(MANDATORY_REQUEST_TOKENS);
        if (!supportedAlgorithms.contains(DigestAlgorithm.MD5)) {
            // If we don't support MD5 then the client must choose an algorithm as we can not fall back to MD5.
            mandatoryTokens.add(DigestAuthorizationToken.ALGORITHM);
        }
        if (!supportedQops.isEmpty() && !supportedQops.contains(DigestQop.AUTH)) {
            // If we do not support auth then we are mandating auth-int so force the client to send a QOP
            mandatoryTokens.add(DigestAuthorizationToken.MESSAGE_QOP);
        }

        DigestQop qop = null;
        // This check is early as is increases the list of mandatory tokens.
        if (parsedHeader.containsKey(DigestAuthorizationToken.MESSAGE_QOP)) {
            qop = DigestQop.forName(parsedHeader.get(DigestAuthorizationToken.MESSAGE_QOP));
            if (qop == null || !supportedQops.contains(qop)) {
                // We are also ensuring the client is not trying to force a qop that has been disabled.
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.MESSAGE_QOP.getName(),
                        parsedHeader.get(DigestAuthorizationToken.MESSAGE_QOP));
                // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
            context.setQop(qop);
            mandatoryTokens.add(DigestAuthorizationToken.CNONCE);
            mandatoryTokens.add(DigestAuthorizationToken.NONCE_COUNT);
        }

        // Check all mandatory tokens are present.
        mandatoryTokens.removeAll(parsedHeader.keySet());
        if (mandatoryTokens.size() > 0) {
            for (DigestAuthorizationToken currentToken : mandatoryTokens) {
                // TODO - Need a better check and possible concatenate the list of tokens - however
                // even having one missing token is not something we should routinely expect.
                REQUEST_LOGGER.missingAuthorizationToken(currentToken.getName());
            }
            // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // Perform some validation of the remaining tokens.
        if (!realmName.equals(parsedHeader.get(DigestAuthorizationToken.REALM))) {
            REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.REALM.getName(),
                    parsedHeader.get(DigestAuthorizationToken.REALM));
            // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // TODO - Validate the URI

        if (parsedHeader.containsKey(DigestAuthorizationToken.OPAQUE)) {
            if (!OPAQUE_VALUE.equals(parsedHeader.get(DigestAuthorizationToken.OPAQUE))) {
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.OPAQUE.getName(),
                        parsedHeader.get(DigestAuthorizationToken.OPAQUE));
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }

        DigestAlgorithm algorithm;
        if (parsedHeader.containsKey(DigestAuthorizationToken.ALGORITHM)) {
            algorithm = DigestAlgorithm.forName(parsedHeader.get(DigestAuthorizationToken.ALGORITHM));
            if (algorithm == null || !supportedAlgorithms.contains(algorithm)) {
                // We are also ensuring the client is not trying to force an algorithm that has been disabled.
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.ALGORITHM.getName(),
                        parsedHeader.get(DigestAuthorizationToken.ALGORITHM));
                // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        } else {
            // We know this is safe as the algorithm token was made mandatory
            // if MD5 is not supported.
            algorithm = DigestAlgorithm.MD5;
        }

        try {
            context.setAlgorithm(algorithm);
        } catch (NoSuchAlgorithmException e) {
            /*
             * This should not be possible in a properly configured installation.
             */
            REQUEST_LOGGER.exceptionProcessingRequest(e);
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        final String userName = parsedHeader.get(DigestAuthorizationToken.USERNAME);
        final IdentityManager identityManager = securityContext.getIdentityManager();
        final Account account;

        if (algorithm.isSession()) {
            /* This can follow one of the following: -
             *   1 - New session so use DigestCredentialImpl with the IdentityManager to
             *       create a new session key.
             *   2 - Obtain the existing session key from the session store and validate it, just use
             *       IdentityManager to validate account is still active and the current role assignment.
             */
            throw new IllegalStateException("Not yet implemented.");
        } else {
            final DigestCredential credential = new DigestCredentialImpl(context);
            account = identityManager.verify(userName, credential);
        }

        if (account == null) {
            // Authentication has failed, this could either be caused by the user not-existing or it
            // could be caused due to an invalid hash.
            securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), mechanismName);
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // Step 3 - Verify that the nonce was eligible to be used.
        if (!validateNonceUse(context, parsedHeader, exchange)) {
            // TODO - This is the right place to make use of the decision but the check needs to be much much sooner
            // otherwise a failure server
            // side could leave a packet that could be 're-played' after the failed auth.
            // The username and password verification passed but for some reason we do not like the nonce.
            context.markStale();
            // We do not mark as a failure on the security context as this is not quite a failure, a client with a cached nonce
            // can easily hit this point.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // We have authenticated the remote user.

        sendAuthenticationInfoHeader(exchange);
        securityContext.authenticationComplete(account, mechanismName, false);
        return AuthenticationMechanismOutcome.AUTHENTICATED;

        // Step 4 - Set up any QOP related requirements.

        // TODO - Do QOP
    }

    public AuthenticationMechanismOutcome handleDigestHeader(HttpServerExchange exchange, final SecurityContext securityContext) {
        DigestContext context = exchange.getAttachment(DigestContext.ATTACHMENT_KEY);
        Map<DigestAuthorizationToken, String> parsedHeader = context.getParsedHeader();
        // Step 1 - Verify the set of tokens received to ensure valid values.
        Set<DigestAuthorizationToken> mandatoryTokens = new HashSet<DigestAuthorizationToken>(MANDATORY_REQUEST_TOKENS);
        if (!supportedAlgorithms.contains(DigestAlgorithm.MD5)) {
            // If we don't support MD5 then the client must choose an algorithm as we can not fall back to MD5.
            mandatoryTokens.add(DigestAuthorizationToken.ALGORITHM);
        }
        if (!supportedQops.isEmpty() && !supportedQops.contains(DigestQop.AUTH)) {
            // If we do not support auth then we are mandating auth-int so force the client to send a QOP
            mandatoryTokens.add(DigestAuthorizationToken.MESSAGE_QOP);
        }

        DigestQop qop = null;
        // This check is early as is increases the list of mandatory tokens.
        if (parsedHeader.containsKey(DigestAuthorizationToken.MESSAGE_QOP)) {
            qop = DigestQop.forName(parsedHeader.get(DigestAuthorizationToken.MESSAGE_QOP));
            if (qop == null || !supportedQops.contains(qop)) {
                // We are also ensuring the client is not trying to force a qop that has been disabled.
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.MESSAGE_QOP.getName(),
                        parsedHeader.get(DigestAuthorizationToken.MESSAGE_QOP));
                // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
            context.setQop(qop);
            mandatoryTokens.add(DigestAuthorizationToken.CNONCE);
            mandatoryTokens.add(DigestAuthorizationToken.NONCE_COUNT);
        }

        // Check all mandatory tokens are present.
        mandatoryTokens.removeAll(parsedHeader.keySet());
        if (mandatoryTokens.size() > 0) {
            for (DigestAuthorizationToken currentToken : mandatoryTokens) {
                // TODO - Need a better check and possible concatenate the list of tokens - however
                // even having one missing token is not something we should routinely expect.
                REQUEST_LOGGER.missingAuthorizationToken(currentToken.getName());
            }
            // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // Perform some validation of the remaining tokens.
        if (!realmName.equals(parsedHeader.get(DigestAuthorizationToken.REALM))) {
            REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.REALM.getName(),
                    parsedHeader.get(DigestAuthorizationToken.REALM));
            // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // TODO - Validate the URI

        if (parsedHeader.containsKey(DigestAuthorizationToken.OPAQUE)) {
            if (!OPAQUE_VALUE.equals(parsedHeader.get(DigestAuthorizationToken.OPAQUE))) {
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.OPAQUE.getName(),
                        parsedHeader.get(DigestAuthorizationToken.OPAQUE));
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        }

        DigestAlgorithm algorithm;
        if (parsedHeader.containsKey(DigestAuthorizationToken.ALGORITHM)) {
            algorithm = DigestAlgorithm.forName(parsedHeader.get(DigestAuthorizationToken.ALGORITHM));
            if (algorithm == null || !supportedAlgorithms.contains(algorithm)) {
                // We are also ensuring the client is not trying to force an algorithm that has been disabled.
                REQUEST_LOGGER.invalidTokenReceived(DigestAuthorizationToken.ALGORITHM.getName(),
                        parsedHeader.get(DigestAuthorizationToken.ALGORITHM));
                // TODO - This actually needs to result in a HTTP 400 Bad Request response and not a new challenge.
                return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
            }
        } else {
            // We know this is safe as the algorithm token was made mandatory
            // if MD5 is not supported.
            algorithm = DigestAlgorithm.MD5;
        }

        try {
            context.setAlgorithm(algorithm);
        } catch (NoSuchAlgorithmException e) {
            /*
             * This should not be possible in a properly configured installation.
             */
            REQUEST_LOGGER.exceptionProcessingRequest(e);
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        final String userName = parsedHeader.get(DigestAuthorizationToken.USERNAME);
        final IdentityManager identityManager = securityContext.getIdentityManager();
        final Account account;

        if (algorithm.isSession()) {
            /* This can follow one of the following: -
             *   1 - New session so use DigestCredentialImpl with the IdentityManager to
             *       create a new session key.
             *   2 - Obtain the existing session key from the session store and validate it, just use
             *       IdentityManager to validate account is still active and the current role assignment.
             */
            throw new IllegalStateException("Not yet implemented.");
        } else {
            final DigestCredential credential = new DigestCredentialImpl(context);
            account = identityManager.verify(userName, credential);
        }

        if (account == null) {
            // Authentication has failed, this could either be caused by the user not-existing or it
            // could be caused due to an invalid hash.
            securityContext.authenticationFailed(MESSAGES.authenticationFailed(userName), mechanismName);
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // Step 3 - Verify that the nonce was eligible to be used.
        if (!validateNonceUse(context, parsedHeader, exchange)) {
            // TODO - This is the right place to make use of the decision but the check needs to be much much sooner
            // otherwise a failure server
            // side could leave a packet that could be 're-played' after the failed auth.
            // The username and password verification passed but for some reason we do not like the nonce.
            context.markStale();
            // We do not mark as a failure on the security context as this is not quite a failure, a client with a cached nonce
            // can easily hit this point.
            return AuthenticationMechanismOutcome.NOT_AUTHENTICATED;
        }

        // We have authenticated the remote user.

        sendAuthenticationInfoHeader(exchange);
        securityContext.authenticationComplete(account, mechanismName, false);
        return AuthenticationMechanismOutcome.AUTHENTICATED;

        // Step 4 - Set up any QOP related requirements.

        // TODO - Do QOP
    }

Replace Generic With Diamond HashSet<DigestAuthorizationToken> with HashSet<> in method public handleDigestHeader(exchange HttpServerExchange, securityContext SecurityContext) : AuthenticationMechanismOutcome from class io.undertow.security.impl.DigestAuthenticationMechanism


    /**
     * Returns a mutable map of query parameters.
     *
     * @return The query parameters
     */
    public Map<String, Deque<String>> getQueryParameters() {
        if (queryParameters == null) {
            queryParameters = new TreeMap<>();
        }
        return queryParameters;
    }

    /**
     * Returns a mutable map of query parameters.
     *
     * @return The query parameters
     */
    public Map<String, Deque<String>> getQueryParameters() {
        if (queryParameters == null) {
            queryParameters = new TreeMap<String, Deque<String>>();
        }
        return queryParameters;
    }

Replace Generic With Diamond TreeMap<String,Deque<String>> with TreeMap<> in method public getQueryParameters() : Map<String,Deque<String>> from class io.undertow.server.HttpServerExchange


    /**
     * Returns a mutable map of path parameters
     *
     * @return The path parameters
     */
    public Map<String, Deque<String>> getPathParameters() {
        if (pathParameters == null) {
            pathParameters = new TreeMap<>();
        }
        return pathParameters;
    }

    /**
     * Returns a mutable map of path parameters
     *
     * @return The path parameters
     */
    public Map<String, Deque<String>> getPathParameters() {
        if (pathParameters == null) {
            pathParameters = new TreeMap<String, Deque<String>>();
        }
        return pathParameters;
    }

Replace Generic With Diamond TreeMap<String,Deque<String>> with TreeMap<> in method public getPathParameters() : Map<String,Deque<String>> from class io.undertow.server.HttpServerExchange


    /**
     * Sets a response cookie
     *
     * @param cookie The cookie
     */
    public HttpServerExchange setResponseCookie(final Cookie cookie) {
        if (responseCookies == null) {
            responseCookies = new TreeMap<>(); //hashmap is slow to allocate in JDK7
        }
        responseCookies.put(cookie.getName(), cookie);
        return this;
    }

    /**
     * Sets a response cookie
     *
     * @param cookie The cookie
     */
    public HttpServerExchange setResponseCookie(final Cookie cookie) {
        if (responseCookies == null) {
            responseCookies = new TreeMap<String, Cookie>(); //hashmap is slow to allocate in JDK7
        }
        responseCookies.put(cookie.getName(), cookie);
        return this;
    }

Replace Generic With Diamond TreeMap<String,Cookie> with TreeMap<> in method public setResponseCookie(cookie Cookie) : HttpServerExchange from class io.undertow.server.HttpServerExchange


    /**
     * @return A mutable map of response cookies
     */
    public Map<String, Cookie> getResponseCookies() {
        if (responseCookies == null) {
            responseCookies = new TreeMap<>();
        }
        return responseCookies;
    }

    /**
     * @return A mutable map of response cookies
     */
    public Map<String, Cookie> getResponseCookies() {
        if (responseCookies == null) {
            responseCookies = new TreeMap<String, Cookie>();
        }
        return responseCookies;
    }

Replace Generic With Diamond TreeMap<String,Cookie> with TreeMap<> in method public getResponseCookies() : Map<String,Cookie> from class io.undertow.server.HttpServerExchange