/*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed with
* this work for additional information regarding copyright ownership .
* The ASF licenses this file to You under the Apache License , Version 2 . 0
* ( the " License " ) ; you may not use this file except in compliance with
* the License . You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
package org.apache.coyote.ajp;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.Locale;
import javax.net.SocketFactory;
/**
* AJP client that is not ( yet ) a full AJP client implementation as it just provides the functionality required for the
* unit tests . The client uses blocking IO throughout .
*/
public class SimpleAjpClient {
private static final int DEFAULT_AJP_PACKET_SIZE = 8192 ;
private static final byte [] AJP_CPING;
static {
TesterAjpMessage ajpCping = new TesterAjpMessage(16 );
ajpCping.reset();
ajpCping.appendByte(Constants.JK_AJP13_CPING_REQUEST);
ajpCping.end();
AJP_CPING = new byte [ajpCping.getLen()];
System.arraycopy(ajpCping.getBuffer(), 0 , AJP_CPING, 0 , ajpCping.getLen());
}
private final int packetSize;
private String host = "localhost" ;
private int port = -1 ;
/* GET == 2 */
private int method = 2 ;
private String protocol = "http" ;
private String uri = "/" ;
private String remoteAddr = "192.168.0.1" ;
private String remoteHost = "client.example.com" ;
private String serverName = "www.example.com" ;
private int serverPort = 80 ;
private boolean ssl = false ;
private Socket socket = null ;
public SimpleAjpClient() {
this (DEFAULT_AJP_PACKET_SIZE);
}
public SimpleAjpClient(int packetSize) {
this .packetSize = packetSize;
}
public void setPort(int port) {
this .port = port;
}
public int getPort() {
return port;
}
public void setMethod(String method) {
method = method.toUpperCase(Locale.ENGLISH);
switch (method) {
case "OPTIONS" :
this .method = 1 ;
break ;
case "GET" :
this .method = 2 ;
break ;
case "HEAD" :
this .method = 3 ;
break ;
case "POST" :
this .method = 4 ;
break ;
case "PUT" :
this .method = 5 ;
break ;
case "DELETE" :
this .method = 6 ;
break ;
case "TRACE" :
this .method = 7 ;
break ;
case "PROPFIND" :
this .method = 8 ;
break ;
case "PROPPATCH" :
this .method = 9 ;
break ;
case "MKCOL" :
this .method = 10 ;
break ;
case "COPY" :
this .method = 11 ;
break ;
case "MOVE" :
this .method = 12 ;
break ;
case "LOCK" :
this .method = 13 ;
break ;
case "UNLOCK" :
this .method = 14 ;
break ;
case "ACL" :
this .method = 15 ;
break ;
case "REPORT" :
this .method = 16 ;
break ;
case "VERSION-CONTROL" :
this .method = 17 ;
break ;
case "CHECKIN" :
this .method = 18 ;
break ;
case "CHECKOUT" :
this .method = 19 ;
break ;
case "UNCHECKOUT" :
this .method = 20 ;
break ;
case "SEARCH" :
this .method = 21 ;
break ;
case "MKWORKSPACE" :
this .method = 22 ;
break ;
case "UPDATE" :
this .method = 23 ;
break ;
case "LABEL" :
this .method = 24 ;
break ;
case "MERGE" :
this .method = 25 ;
break ;
case "BASELINE-CONTROL" :
this .method = 26 ;
break ;
case "MKACTIVITY" :
this .method = 27 ;
break ;
default :
this .method = 99 ;
}
}
public String getMethod() {
switch (method) {
case 1 :
return "OPTIONS" ;
case 2 :
return "GET" ;
case 3 :
return "HEAD" ;
case 4 :
return "POST" ;
case 5 :
return "PUT" ;
case 6 :
return "DELETE" ;
case 7 :
return "TRACE" ;
case 8 :
return "PROPFIND" ;
case 9 :
return "PROPPATCH" ;
case 10 :
return "MKCOL" ;
case 11 :
return "COPY" ;
case 12 :
return "MOVE" ;
case 13 :
return "LOCK" ;
case 14 :
return "UNLOCK" ;
case 15 :
return "ACL" ;
case 16 :
return "REPORT" ;
case 17 :
return "VERSION-CONTROL" ;
case 18 :
return "CHECKIN" ;
case 19 :
return "CHECKOUT" ;
case 20 :
return "UNCHECKOUT" ;
case 21 :
return "SEARCH" ;
case 22 :
return "MKWORKSPACE" ;
case 23 :
return "UPDATE" ;
case 24 :
return "LABEL" ;
case 25 :
return "MERGE" ;
case 26 :
return "BASELINE-CONTROL" ;
case 27 :
return "MKACTIVITY" ;
default :
return "UNKNOWN" ;
}
}
public void setProtocol(String protocol) {
this .protocol = protocol;
}
public String getProtocol() {
return protocol;
}
public void setUri(String uri) {
this .uri = uri;
}
public String getUri() {
return uri;
}
public void setRemoteAddr(String remoteAddr) {
this .remoteAddr = remoteAddr;
}
public String getRemoteAddr() {
return remoteAddr;
}
public void setRemoteHost(String remoteHost) {
this .remoteHost = remoteHost;
}
public String getRemoteHost() {
return remoteHost;
}
public void setServerName(String serverName) {
this .serverName = serverName;
}
public String getServerName() {
return serverName;
}
public void setServerPort(int serverPort) {
this .serverPort = serverPort;
}
public int getServerPort() {
return serverPort;
}
public void setSsl(boolean ssl) {
this .ssl = ssl;
}
public boolean isSsl() {
return ssl;
}
public void connect() throws IOException {
socket = SocketFactory.getDefault().createSocket(host, port);
}
public void disconnect() throws IOException {
socket.close();
socket = null ;
}
/*
* Create a message to request the given URL .
*/
public TesterAjpMessage createForwardMessage() {
TesterAjpMessage message = new TesterAjpMessage(packetSize);
message.reset();
// Set the header bytes
message.getBuffer()[0 ] = 0 x12;
message.getBuffer()[1 ] = 0 x34;
// Code 2 for forward request
message.appendByte(Constants.JK_AJP13_FORWARD_REQUEST);
// HTTP method, GET = 2
message.appendByte(method);
// Protocol
message.appendString(protocol);
// Request URI
message.appendString(uri);
// Client address
message.appendString(remoteAddr);
// Client host
message.appendString(remoteHost);
// Server name
message.appendString(serverName);
// Server port
message.appendInt(serverPort);
// Is ssl
message.appendByte(ssl ? 0 x01 : 0 x00);
return message;
}
public TesterAjpMessage createBodyMessage(byte [] data) {
TesterAjpMessage message = new TesterAjpMessage(packetSize);
message.reset();
// Set the header bytes
message.getBuffer()[0 ] = 0 x12;
message.getBuffer()[1 ] = 0 x34;
message.appendBytes(data, 0 , data.length);
message.end();
return message;
}
/*
* Sends an TesterAjpMessage to the server and returns the response message .
*/
public TesterAjpMessage sendMessage(TesterAjpMessage headers) throws IOException {
return sendMessage(headers, null );
}
public TesterAjpMessage sendMessage(TesterAjpMessage headers, TesterAjpMessage body) throws IOException {
// Send the headers
socket.getOutputStream().write(headers.getBuffer(), 0 , headers.getLen());
if (body != null ) {
// Send the body of present
socket.getOutputStream().write(body.getBuffer(), 0 , body.getLen());
}
// Read the response
return readMessage();
}
/*
* Tests the connection to the server and returns the CPONG response .
*/
public TesterAjpMessage cping() throws IOException {
// Send the ping message
socket.getOutputStream().write(AJP_CPING);
// Read the response
return readMessage();
}
/*
* Reads a message from the server .
*/
public TesterAjpMessage readMessage() throws IOException {
InputStream is = socket.getInputStream();
TesterAjpMessage message = new TesterAjpMessage(packetSize);
byte [] buf = message.getBuffer();
read(is, buf, 0 , Constants.H_SIZE);
int messageLength = message.processHeader(false );
if (messageLength < 0 ) {
throw new IOException("Invalid AJP message length" );
} else if (messageLength == 0 ) {
return message;
} else {
if (messageLength > buf.length) {
throw new IllegalArgumentException("Message too long [" + Integer.valueOf(messageLength) +
"] for buffer length [" + Integer.valueOf(buf.length) + "]" );
}
read(is, buf, Constants.H_SIZE, messageLength);
return message;
}
}
protected boolean read(InputStream is, byte [] buf, int pos, int n) throws IOException {
int read = 0 ;
int res = 0 ;
while (read < n) {
res = is.read(buf, read + pos, n - read);
if (res > 0 ) {
read += res;
} else {
throw new IOException("Read failed" );
}
}
return true ;
}
}
Messung V0.5 in Prozent C=95 H=77 G=86
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-09-29)
¤
*© Formatika GbR, Deutschland