Search in sources :

Example 21 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class AjpProcessor method prepareRequest.

/**
     * After reading the request headers, we have to setup the request filters.
     */
private void prepareRequest() {
    // Translate the HTTP method code to a String.
    byte methodCode = requestHeaderMessage.getByte();
    if (methodCode != Constants.SC_M_JK_STORED) {
        String methodName = Constants.getMethodForCode(methodCode - 1);
        request.method().setString(methodName);
    }
    requestHeaderMessage.getBytes(request.protocol());
    requestHeaderMessage.getBytes(request.requestURI());
    requestHeaderMessage.getBytes(request.remoteAddr());
    requestHeaderMessage.getBytes(request.remoteHost());
    requestHeaderMessage.getBytes(request.localName());
    request.setLocalPort(requestHeaderMessage.getInt());
    boolean isSSL = requestHeaderMessage.getByte() != 0;
    if (isSSL) {
        request.scheme().setString("https");
    }
    // Decode headers
    MimeHeaders headers = request.getMimeHeaders();
    // Set this every time in case limit has been changed via JMX
    headers.setLimit(protocol.getMaxHeaderCount());
    boolean contentLengthSet = false;
    int hCount = requestHeaderMessage.getInt();
    for (int i = 0; i < hCount; i++) {
        String hName = null;
        // Header names are encoded as either an integer code starting
        // with 0xA0, or as a normal string (in which case the first
        // two bytes are the length).
        int isc = requestHeaderMessage.peekInt();
        int hId = isc & 0xFF;
        MessageBytes vMB = null;
        isc &= 0xFF00;
        if (0xA000 == isc) {
            // To advance the read position
            requestHeaderMessage.getInt();
            hName = Constants.getHeaderForCode(hId - 1);
            vMB = headers.addValue(hName);
        } else {
            // reset hId -- if the header currently being read
            // happens to be 7 or 8 bytes long, the code below
            // will think it's the content-type header or the
            // content-length header - SC_REQ_CONTENT_TYPE=7,
            // SC_REQ_CONTENT_LENGTH=8 - leading to unexpected
            // behaviour.  see bug 5861 for more information.
            hId = -1;
            requestHeaderMessage.getBytes(tmpMB);
            ByteChunk bc = tmpMB.getByteChunk();
            vMB = headers.addValue(bc.getBuffer(), bc.getStart(), bc.getLength());
        }
        requestHeaderMessage.getBytes(vMB);
        if (hId == Constants.SC_REQ_CONTENT_LENGTH || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Length"))) {
            long cl = vMB.getLong();
            if (contentLengthSet) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                setErrorState(ErrorState.CLOSE_CLEAN, null);
            } else {
                contentLengthSet = true;
                // Set the content-length header for the request
                request.setContentLength(cl);
            }
        } else if (hId == Constants.SC_REQ_CONTENT_TYPE || (hId == -1 && tmpMB.equalsIgnoreCase("Content-Type"))) {
            // just read the content-type header, so set it
            ByteChunk bchunk = vMB.getByteChunk();
            request.contentType().setBytes(bchunk.getBytes(), bchunk.getOffset(), bchunk.getLength());
        }
    }
    // Decode extra attributes
    String requiredSecret = protocol.getRequiredSecret();
    boolean secret = false;
    byte attributeCode;
    while ((attributeCode = requestHeaderMessage.getByte()) != Constants.SC_A_ARE_DONE) {
        switch(attributeCode) {
            case Constants.SC_A_REQ_ATTRIBUTE:
                requestHeaderMessage.getBytes(tmpMB);
                String n = tmpMB.toString();
                requestHeaderMessage.getBytes(tmpMB);
                String v = tmpMB.toString();
                /*
                 * AJP13 misses to forward the local IP address and the
                 * remote port. Allow the AJP connector to add this info via
                 * private request attributes.
                 * We will accept the forwarded data and remove it from the
                 * public list of request attributes.
                 */
                if (n.equals(Constants.SC_A_REQ_LOCAL_ADDR)) {
                    request.localAddr().setString(v);
                } else if (n.equals(Constants.SC_A_REQ_REMOTE_PORT)) {
                    try {
                        request.setRemotePort(Integer.parseInt(v));
                    } catch (NumberFormatException nfe) {
                    // Ignore invalid value
                    }
                } else if (n.equals(Constants.SC_A_SSL_PROTOCOL)) {
                    request.setAttribute(SSLSupport.PROTOCOL_VERSION_KEY, v);
                } else {
                    request.setAttribute(n, v);
                }
                break;
            case Constants.SC_A_CONTEXT:
                requestHeaderMessage.getBytes(tmpMB);
                // nothing
                break;
            case Constants.SC_A_SERVLET_PATH:
                requestHeaderMessage.getBytes(tmpMB);
                // nothing
                break;
            case Constants.SC_A_REMOTE_USER:
                boolean tomcatAuthorization = protocol.getTomcatAuthorization();
                if (tomcatAuthorization || !protocol.getTomcatAuthentication()) {
                    // Implies tomcatAuthentication == false
                    requestHeaderMessage.getBytes(request.getRemoteUser());
                    request.setRemoteUserNeedsAuthorization(tomcatAuthorization);
                } else {
                    // Ignore user information from reverse proxy
                    requestHeaderMessage.getBytes(tmpMB);
                }
                break;
            case Constants.SC_A_AUTH_TYPE:
                if (protocol.getTomcatAuthentication()) {
                    // ignore server
                    requestHeaderMessage.getBytes(tmpMB);
                } else {
                    requestHeaderMessage.getBytes(request.getAuthType());
                }
                break;
            case Constants.SC_A_QUERY_STRING:
                requestHeaderMessage.getBytes(request.queryString());
                break;
            case Constants.SC_A_JVM_ROUTE:
                requestHeaderMessage.getBytes(tmpMB);
                // nothing
                break;
            case Constants.SC_A_SSL_CERT:
                // SSL certificate extraction is lazy, moved to JkCoyoteHandler
                requestHeaderMessage.getBytes(certificates);
                break;
            case Constants.SC_A_SSL_CIPHER:
                requestHeaderMessage.getBytes(tmpMB);
                request.setAttribute(SSLSupport.CIPHER_SUITE_KEY, tmpMB.toString());
                break;
            case Constants.SC_A_SSL_SESSION:
                requestHeaderMessage.getBytes(tmpMB);
                request.setAttribute(SSLSupport.SESSION_ID_KEY, tmpMB.toString());
                break;
            case Constants.SC_A_SSL_KEY_SIZE:
                request.setAttribute(SSLSupport.KEY_SIZE_KEY, Integer.valueOf(requestHeaderMessage.getInt()));
                break;
            case Constants.SC_A_STORED_METHOD:
                requestHeaderMessage.getBytes(request.method());
                break;
            case Constants.SC_A_SECRET:
                requestHeaderMessage.getBytes(tmpMB);
                if (requiredSecret != null) {
                    secret = true;
                    if (!tmpMB.equals(requiredSecret)) {
                        response.setStatus(403);
                        setErrorState(ErrorState.CLOSE_CLEAN, null);
                    }
                }
                break;
            default:
                // Ignore unknown attribute for backward compatibility
                break;
        }
    }
    // Check if secret was submitted if required
    if ((requiredSecret != null) && !secret) {
        response.setStatus(403);
        setErrorState(ErrorState.CLOSE_CLEAN, null);
    }
    // Check for a full URI (including protocol://host:port/)
    ByteChunk uriBC = request.requestURI().getByteChunk();
    if (uriBC.startsWithIgnoreCase("http", 0)) {
        int pos = uriBC.indexOf("://", 0, 3, 4);
        int uriBCStart = uriBC.getStart();
        int slashPos = -1;
        if (pos != -1) {
            byte[] uriB = uriBC.getBytes();
            slashPos = uriBC.indexOf('/', pos + 3);
            if (slashPos == -1) {
                slashPos = uriBC.getLength();
                // Set URI as "/"
                request.requestURI().setBytes(uriB, uriBCStart + pos + 1, 1);
            } else {
                request.requestURI().setBytes(uriB, uriBCStart + slashPos, uriBC.getLength() - slashPos);
            }
            MessageBytes hostMB = headers.setValue("host");
            hostMB.setBytes(uriB, uriBCStart + pos + 3, slashPos - pos - 3);
        }
    }
    MessageBytes valueMB = request.getMimeHeaders().getValue("host");
    parseHost(valueMB);
    if (getErrorState().isError()) {
        getAdapter().log(request, response, 0);
    }
}
Also used : MimeHeaders(org.apache.tomcat.util.http.MimeHeaders) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 22 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method prepareRequest.

/**
     * After reading the request headers, we have to setup the request filters.
     */
private void prepareRequest() {
    http11 = true;
    http09 = false;
    contentDelimitation = false;
    sendfileData = null;
    if (protocol.isSSLEnabled()) {
        request.scheme().setString("https");
    }
    MessageBytes protocolMB = request.protocol();
    if (protocolMB.equals(Constants.HTTP_11)) {
        http11 = true;
        protocolMB.setString(Constants.HTTP_11);
    } else if (protocolMB.equals(Constants.HTTP_10)) {
        http11 = false;
        keepAlive = false;
        protocolMB.setString(Constants.HTTP_10);
    } else if (protocolMB.equals("")) {
        // HTTP/0.9
        http09 = true;
        http11 = false;
        keepAlive = false;
    } else {
        // Unsupported protocol
        http11 = false;
        // Send 505; Unsupported HTTP version
        response.setStatus(505);
        setErrorState(ErrorState.CLOSE_CLEAN, null);
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("http11processor.request.prepare") + " Unsupported HTTP version \"" + protocolMB + "\"");
        }
    }
    MimeHeaders headers = request.getMimeHeaders();
    // Check connection header
    MessageBytes connectionValueMB = headers.getValue(Constants.CONNECTION);
    if (connectionValueMB != null) {
        ByteChunk connectionValueBC = connectionValueMB.getByteChunk();
        if (findBytes(connectionValueBC, Constants.CLOSE_BYTES) != -1) {
            keepAlive = false;
        } else if (findBytes(connectionValueBC, Constants.KEEPALIVE_BYTES) != -1) {
            keepAlive = true;
        }
    }
    if (http11) {
        MessageBytes expectMB = headers.getValue("expect");
        if (expectMB != null) {
            if (expectMB.indexOfIgnoreCase("100-continue", 0) != -1) {
                inputBuffer.setSwallowInput(false);
                request.setExpectation(true);
            } else {
                response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
                setErrorState(ErrorState.CLOSE_CLEAN, null);
            }
        }
    }
    // Check user-agent header
    Pattern restrictedUserAgents = protocol.getRestrictedUserAgentsPattern();
    if (restrictedUserAgents != null && (http11 || keepAlive)) {
        MessageBytes userAgentValueMB = headers.getValue("user-agent");
        // and keepAlive flags accordingly
        if (userAgentValueMB != null) {
            String userAgentValue = userAgentValueMB.toString();
            if (restrictedUserAgents.matcher(userAgentValue).matches()) {
                http11 = false;
                keepAlive = false;
            }
        }
    }
    // Check for a full URI (including protocol://host:port/)
    ByteChunk uriBC = request.requestURI().getByteChunk();
    if (uriBC.startsWithIgnoreCase("http", 0)) {
        int pos = uriBC.indexOf("://", 0, 3, 4);
        int uriBCStart = uriBC.getStart();
        int slashPos = -1;
        if (pos != -1) {
            byte[] uriB = uriBC.getBytes();
            slashPos = uriBC.indexOf('/', pos + 3);
            if (slashPos == -1) {
                slashPos = uriBC.getLength();
                // Set URI as "/"
                request.requestURI().setBytes(uriB, uriBCStart + pos + 1, 1);
            } else {
                request.requestURI().setBytes(uriB, uriBCStart + slashPos, uriBC.getLength() - slashPos);
            }
            MessageBytes hostMB = headers.setValue("host");
            hostMB.setBytes(uriB, uriBCStart + pos + 3, slashPos - pos - 3);
        }
    }
    // Input filter setup
    InputFilter[] inputFilters = inputBuffer.getFilters();
    // Parse transfer-encoding header
    if (http11) {
        MessageBytes transferEncodingValueMB = headers.getValue("transfer-encoding");
        if (transferEncodingValueMB != null) {
            String transferEncodingValue = transferEncodingValueMB.toString();
            // Parse the comma separated list. "identity" codings are ignored
            int startPos = 0;
            int commaPos = transferEncodingValue.indexOf(',');
            String encodingName = null;
            while (commaPos != -1) {
                encodingName = transferEncodingValue.substring(startPos, commaPos);
                addInputFilter(inputFilters, encodingName);
                startPos = commaPos + 1;
                commaPos = transferEncodingValue.indexOf(',', startPos);
            }
            encodingName = transferEncodingValue.substring(startPos);
            addInputFilter(inputFilters, encodingName);
        }
    }
    // Parse content-length header
    long contentLength = request.getContentLengthLong();
    if (contentLength >= 0) {
        if (contentDelimitation) {
            // contentDelimitation being true at this point indicates that
            // chunked encoding is being used but chunked encoding should
            // not be used with a content length. RFC 2616, section 4.4,
            // bullet 3 states Content-Length must be ignored in this case -
            // so remove it.
            headers.removeHeader("content-length");
            request.setContentLength(-1);
        } else {
            inputBuffer.addActiveFilter(inputFilters[Constants.IDENTITY_FILTER]);
            contentDelimitation = true;
        }
    }
    MessageBytes valueMB = headers.getValue("host");
    // Check host header
    if (http11 && (valueMB == null)) {
        // 400 - Bad request
        response.setStatus(400);
        setErrorState(ErrorState.CLOSE_CLEAN, null);
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("http11processor.request.prepare") + " host header missing");
        }
    }
    parseHost(valueMB);
    if (!contentDelimitation) {
        // If there's no content length
        // (broken HTTP/1.0 or HTTP/1.1), assume
        // the client is not broken and didn't send a body
        inputBuffer.addActiveFilter(inputFilters[Constants.VOID_FILTER]);
        contentDelimitation = true;
    }
    if (getErrorState().isError()) {
        getAdapter().log(request, response, 0);
    }
}
Also used : MimeHeaders(org.apache.tomcat.util.http.MimeHeaders) Pattern(java.util.regex.Pattern) VoidInputFilter(org.apache.coyote.http11.filters.VoidInputFilter) BufferedInputFilter(org.apache.coyote.http11.filters.BufferedInputFilter) IdentityInputFilter(org.apache.coyote.http11.filters.IdentityInputFilter) ChunkedInputFilter(org.apache.coyote.http11.filters.ChunkedInputFilter) SavedRequestInputFilter(org.apache.coyote.http11.filters.SavedRequestInputFilter) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 23 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method isCompressable.

/**
     * Check if the resource could be compressed, if the client supports it.
     */
private boolean isCompressable() {
    // Check if content is not already gzipped
    MessageBytes contentEncodingMB = response.getMimeHeaders().getValue("Content-Encoding");
    if ((contentEncodingMB != null) && (contentEncodingMB.indexOf("gzip") != -1)) {
        return false;
    }
    // If force mode, always compress (test purposes only)
    if (protocol.getCompressionLevel() == 2) {
        return true;
    }
    // Check if sufficient length to trigger the compression
    long contentLength = response.getContentLengthLong();
    if ((contentLength == -1) || (contentLength > protocol.getCompressionMinSize())) {
        // Check for compatible MIME-TYPE
        String[] compressableMimeTypes = protocol.getCompressableMimeTypes();
        if (compressableMimeTypes != null) {
            return (startsWithStringArray(compressableMimeTypes, response.getContentType()));
        }
    }
    return false;
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 24 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method useCompression.

/**
     * Check if compression should be used for this resource. Already checked
     * that the resource could be compressed if the client supports it.
     */
private boolean useCompression() {
    // Check if browser support gzip encoding
    MessageBytes acceptEncodingMB = request.getMimeHeaders().getValue("accept-encoding");
    if ((acceptEncodingMB == null) || (acceptEncodingMB.indexOf("gzip") == -1)) {
        return false;
    }
    // If force mode, always compress (test purposes only)
    if (protocol.getCompressionLevel() == 2) {
        return true;
    }
    // Check for incompatible Browser
    Pattern noCompressionUserAgents = protocol.getNoCompressionUserAgentsPattern();
    if (noCompressionUserAgents != null) {
        MessageBytes userAgentValueMB = request.getMimeHeaders().getValue("user-agent");
        if (userAgentValueMB != null) {
            String userAgentValue = userAgentValueMB.toString();
            if (noCompressionUserAgents.matcher(userAgentValue).matches()) {
                return false;
            }
        }
    }
    return true;
}
Also used : Pattern(java.util.regex.Pattern) MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 25 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method prepareResponse.

/**
     * When committing the response, we have to validate the set of headers, as
     * well as setup the response filters.
     */
@Override
protected final void prepareResponse() throws IOException {
    boolean entityBody = true;
    contentDelimitation = false;
    OutputFilter[] outputFilters = outputBuffer.getFilters();
    if (http09 == true) {
        // HTTP/0.9
        outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
        outputBuffer.commit();
        return;
    }
    int statusCode = response.getStatus();
    if (statusCode < 200 || statusCode == 204 || statusCode == 205 || statusCode == 304) {
        // No entity body
        outputBuffer.addActiveFilter(outputFilters[Constants.VOID_FILTER]);
        entityBody = false;
        contentDelimitation = true;
    }
    MessageBytes methodMB = request.method();
    if (methodMB.equals("HEAD")) {
        // No entity body
        outputBuffer.addActiveFilter(outputFilters[Constants.VOID_FILTER]);
        contentDelimitation = true;
    }
    // Sendfile support
    boolean sendingWithSendfile = false;
    if (protocol.getUseSendfile()) {
        sendingWithSendfile = prepareSendfile(outputFilters);
    }
    // Check for compression
    boolean isCompressable = false;
    boolean useCompression = false;
    if (entityBody && (protocol.getCompressionLevel() > 0) && !sendingWithSendfile) {
        isCompressable = isCompressable();
        if (isCompressable) {
            useCompression = useCompression();
        }
        // Change content-length to -1 to force chunking
        if (useCompression) {
            response.setContentLength(-1);
        }
    }
    MimeHeaders headers = response.getMimeHeaders();
    if (!entityBody) {
        response.setContentLength(-1);
    }
    // A SC_NO_CONTENT response may include entity headers
    if (entityBody || statusCode == HttpServletResponse.SC_NO_CONTENT) {
        String contentType = response.getContentType();
        if (contentType != null) {
            headers.setValue("Content-Type").setString(contentType);
        }
        String contentLanguage = response.getContentLanguage();
        if (contentLanguage != null) {
            headers.setValue("Content-Language").setString(contentLanguage);
        }
    }
    long contentLength = response.getContentLengthLong();
    boolean connectionClosePresent = false;
    if (contentLength != -1) {
        headers.setValue("Content-Length").setLong(contentLength);
        outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
        contentDelimitation = true;
    } else {
        // If the response code supports an entity body and we're on
        // HTTP 1.1 then we chunk unless we have a Connection: close header
        connectionClosePresent = isConnectionClose(headers);
        if (entityBody && http11 && !connectionClosePresent) {
            outputBuffer.addActiveFilter(outputFilters[Constants.CHUNKED_FILTER]);
            contentDelimitation = true;
            headers.addValue(Constants.TRANSFERENCODING).setString(Constants.CHUNKED);
        } else {
            outputBuffer.addActiveFilter(outputFilters[Constants.IDENTITY_FILTER]);
        }
    }
    if (useCompression) {
        outputBuffer.addActiveFilter(outputFilters[Constants.GZIP_FILTER]);
        headers.setValue("Content-Encoding").setString("gzip");
    }
    // If it might be compressed, set the Vary header
    if (isCompressable) {
        // Make Proxies happy via Vary (from mod_deflate)
        MessageBytes vary = headers.getValue("Vary");
        if (vary == null) {
            // Add a new Vary header
            headers.setValue("Vary").setString("Accept-Encoding");
        } else if (vary.equals("*")) {
        // No action required
        } else {
            // Merge into current header
            headers.setValue("Vary").setString(vary.getString() + ",Accept-Encoding");
        }
    }
    // Caching Filter)
    if (headers.getValue("Date") == null) {
        headers.addValue("Date").setString(FastHttpDateFormat.getCurrentDate());
    }
    if ((entityBody) && (!contentDelimitation)) {
        // Mark as close the connection after the request, and add the
        // connection: close header
        keepAlive = false;
    }
    // This may disabled keep-alive to check before working out the
    // Connection header.
    checkExpectationAndResponseStatus();
    // Connection: close header.
    if (keepAlive && statusDropsConnection(statusCode)) {
        keepAlive = false;
    }
    if (!keepAlive) {
        // Avoid adding the close header twice
        if (!connectionClosePresent) {
            headers.addValue(Constants.CONNECTION).setString(Constants.CLOSE);
        }
    } else if (!http11 && !getErrorState().isError()) {
        headers.addValue(Constants.CONNECTION).setString(Constants.KEEPALIVE);
    }
    // Add server header
    String server = protocol.getServer();
    if (server == null) {
        if (protocol.getServerRemoveAppProvidedValues()) {
            headers.removeHeader("server");
        }
    } else {
        // server always overrides anything the app might set
        headers.setValue("Server").setString(server);
    }
    // Build the response header
    try {
        outputBuffer.sendStatus();
        int size = headers.size();
        for (int i = 0; i < size; i++) {
            outputBuffer.sendHeader(headers.getName(i), headers.getValue(i));
        }
        outputBuffer.endHeaders();
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        // If something goes wrong, reset the header buffer so the error
        // response can be written instead.
        outputBuffer.resetHeaderBuffer();
        throw t;
    }
    outputBuffer.commit();
}
Also used : ChunkedOutputFilter(org.apache.coyote.http11.filters.ChunkedOutputFilter) IdentityOutputFilter(org.apache.coyote.http11.filters.IdentityOutputFilter) GzipOutputFilter(org.apache.coyote.http11.filters.GzipOutputFilter) VoidOutputFilter(org.apache.coyote.http11.filters.VoidOutputFilter) MimeHeaders(org.apache.tomcat.util.http.MimeHeaders) MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Aggregations

MessageBytes (org.apache.tomcat.util.buf.MessageBytes)32 ByteChunk (org.apache.tomcat.util.buf.ByteChunk)7 Context (org.apache.catalina.Context)6 MimeHeaders (org.apache.tomcat.util.http.MimeHeaders)6 Test (org.junit.Test)6 IOException (java.io.IOException)4 Host (org.apache.catalina.Host)4 LoggingBaseTest (org.apache.catalina.startup.LoggingBaseTest)4 Pattern (java.util.regex.Pattern)3 ServletException (javax.servlet.ServletException)3 Cookie (javax.servlet.http.Cookie)3 Wrapper (org.apache.catalina.Wrapper)3 StandardContext (org.apache.catalina.core.StandardContext)3 StandardHost (org.apache.catalina.core.StandardHost)3 CharChunk (org.apache.tomcat.util.buf.CharChunk)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 Principal (java.security.Principal)2 MappingData (org.apache.catalina.mapper.MappingData)2 InputStream (java.io.InputStream)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1