You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fx-dev@ws.apache.org by ch...@apache.org on 2006/02/06 15:55:50 UTC
svn commit: r375294 - in
/webservices/sandesha/trunk/src/org/apache/sandesha2: ./ handlers/
msgprocessors/ storage/inmemory/ transport/ util/ workers/
Author: chamikara
Date: Mon Feb 6 06:55:49 2006
New Revision: 375294
URL: http://svn.apache.org/viewcvs?rev=375294&view=rev
Log:
Updated the RMMessageCreater to copy properties from the reference message. This is useful when other modules are present (e.g. security).
Modified:
webservices/sandesha/trunk/src/org/apache/sandesha2/TerminateManager.java
webservices/sandesha/trunk/src/org/apache/sandesha2/handlers/SandeshaOutHandler.java
webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/AcknowledgementProcessor.java
webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/ApplicationMsgProcessor.java
webservices/sandesha/trunk/src/org/apache/sandesha2/storage/inmemory/InMemoryStorageManager.java
webservices/sandesha/trunk/src/org/apache/sandesha2/transport/Sandesha2TransportSender.java
webservices/sandesha/trunk/src/org/apache/sandesha2/util/RMMsgCreator.java
webservices/sandesha/trunk/src/org/apache/sandesha2/workers/Sender.java
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/TerminateManager.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/TerminateManager.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/TerminateManager.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/TerminateManager.java Mon Feb 6 06:55:49 2006
@@ -137,7 +137,7 @@
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
NextMsgBean nextMsgBean = (NextMsgBean) iterator.next();
- nextMsgBeanMgr.delete(nextMsgBean.getSequenceID());
+ //nextMsgBeanMgr.delete(nextMsgBean.getSequenceID());
}
removeReceivingSideProperties(configContext,sequenceID);
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/handlers/SandeshaOutHandler.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/handlers/SandeshaOutHandler.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/handlers/SandeshaOutHandler.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/handlers/SandeshaOutHandler.java Mon Feb 6 06:55:49 2006
@@ -464,7 +464,6 @@
.getRetransmitterBeanMgr();
String key = SandeshaUtil.getUUID();
- //storageManager.storeMessageContext(key, createSeqMsg);
SenderBean createSeqEntry = new SenderBean();
createSeqEntry.setMessageContextRefKey(key);
@@ -480,6 +479,9 @@
createSeqEntry
.setMessageType(Sandesha2Constants.MessageTypes.CREATE_SEQ);
retransmitterMgr.insert(createSeqEntry);
+
+ storageManager.storeMessageContext(key,createSeqMsg);
+
createSeqTransaction.commit();
// sending the message once through our sender.
@@ -720,6 +722,9 @@
}
appMsgEntry.setInternalSequenceID(internalSequenceId);
+
+ storageManager.storeMessageContext(storageKey,msg);
+
retransmitterMgr.insert(appMsgEntry);
msg.setProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING,
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/AcknowledgementProcessor.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/AcknowledgementProcessor.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/AcknowledgementProcessor.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/AcknowledgementProcessor.java Mon Feb 6 06:55:49 2006
@@ -307,7 +307,7 @@
terminateBean.setMessageContextRefKey(key);
- //storageManager.storeMessageContext(key,terminateRMMessage.getMessageContext());
+ storageManager.storeMessageContext(key,terminateRMMessage.getMessageContext());
//Set a retransmitter lastSentTime so that terminate will be send with
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/ApplicationMsgProcessor.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/ApplicationMsgProcessor.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/ApplicationMsgProcessor.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/msgprocessors/ApplicationMsgProcessor.java Mon Feb 6 06:55:49 2006
@@ -466,6 +466,8 @@
ackBean.setTimeToSend(timeToSend);
+ storageManager.storeMessageContext(key,ackMsgCtx);
+
//inserting the new ack.
retransmitterBeanMgr.insert(ackBean);
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/storage/inmemory/InMemoryStorageManager.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/storage/inmemory/InMemoryStorageManager.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/storage/inmemory/InMemoryStorageManager.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/storage/inmemory/InMemoryStorageManager.java Mon Feb 6 06:55:49 2006
@@ -305,7 +305,7 @@
Object oldEntry = storageMap.get(key);
if (oldEntry==null)
- throw new SandeshaStorageException ("En try is not present for updating");
+ throw new SandeshaStorageException ("Entry is not present for updating");
storeMessageContext(key,msgContext);
}
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/transport/Sandesha2TransportSender.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/transport/Sandesha2TransportSender.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/transport/Sandesha2TransportSender.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/transport/Sandesha2TransportSender.java Mon Feb 6 06:55:49 2006
@@ -44,7 +44,7 @@
StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configurationContext);
Transaction messageStoreTransaction = storageManager.getTransaction();
- storageManager.storeMessageContext(key,msgContext);
+ storageManager.updateMessageContext(key,msgContext);
messageStoreTransaction.commit();
Transaction transaction = storageManager.getTransaction();
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/util/RMMsgCreator.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/util/RMMsgCreator.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/util/RMMsgCreator.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/util/RMMsgCreator.java Mon Feb 6 06:55:49 2006
@@ -19,17 +19,22 @@
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.EndpointReference;
+import org.apache.axis2.client.Options;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.AxisOperationFactory;
import org.apache.axis2.description.Parameter;
+import org.apache.axis2.description.ParameterImpl;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.ws.commons.soap.SOAPEnvelope;
import org.apache.ws.commons.soap.SOAPFactory;
import org.apache.sandesha2.RMMsgContext;
@@ -54,31 +59,154 @@
/**
* Used to create new RM messages.
+ *
* @author Chamikara Jayalath <ch...@gmail.com>
*/
public class RMMsgCreator {
- private static void setUpMessage(MessageContext relatedMessage, MessageContext newMessage) throws SandeshaException {
- //Seting RMPolicyBean
-// if (rmMsgCtx.getProperty(Sandesha2Constants.WSP.RM_POLICY_BEAN)==null)
-// rmMsgCtx.setProperty(Sandesha2Constants.WSP.RM_POLICY_BEAN, PropertyManager.getInstance().getRMPolicyBean());
+ private static Log log = LogFactory.getLog(RMMsgCreator.class);
+
- Parameter policyParam = relatedMessage.getParameter(Sandesha2Constants.SANDESHA2_POLICY_BEAN);
-// if (propertyParam!=null)
-// newMessage.setProperty(propertyParam.getName(),propertyParam.getValue());
-
- if (policyParam!=null) {
-
+ private static void initializeCreation1(MessageContext relatedMessage,
+ MessageContext newMessage) {
+ }
+
+ private static void finalizeCreation1(MessageContext relatedMessage,
+ MessageContext newMessage) throws SandeshaException {
+
+ }
+
+
+
+
+ private static void initializeCreation(MessageContext relatedMessage,
+ MessageContext newMessage) throws SandeshaException {
+ // Seting RMPolicyBean
+ // if
+ // (rmMsgCtx.getProperty(Sandesha2Constants.WSP.RM_POLICY_BEAN)==null)
+ // rmMsgCtx.setProperty(Sandesha2Constants.WSP.RM_POLICY_BEAN,
+ // PropertyManager.getInstance().getRMPolicyBean());
+
+ Parameter policyParam = relatedMessage
+ .getParameter(Sandesha2Constants.SANDESHA2_POLICY_BEAN);
+ // if (propertyParam!=null)
+ // newMessage.setProperty(propertyParam.getName(),propertyParam.getValue());
+
+ if (policyParam != null) {
+
try {
- //TODO this should be added to the AxisMessage
- if (newMessage.getAxisOperation()!=null)
+ // TODO this should be added to the AxisMessage
+ if (newMessage.getAxisOperation() != null)
newMessage.getAxisOperation().addParameter(policyParam);
- else if (newMessage.getAxisService()!=null) {
+ else if (newMessage.getAxisService() != null) {
newMessage.getAxisService().addParameter(policyParam);
+
}
} catch (AxisFault e) {
- throw new SandeshaException (e.getMessage());
+ throw new SandeshaException(e.getMessage());
+ }
+ }
+
+ }
+
+ private static void finalizeCreation(MessageContext relatedMessage,
+ MessageContext newMessage) throws SandeshaException {
+
+ newMessage.setServerSide(relatedMessage.isServerSide());
+
+ // adding all parameters from old message to the new one.
+ try {
+ // axisOperation parameters
+ AxisOperation oldAxisOperation = relatedMessage.getAxisOperation();
+ if (oldAxisOperation != null) {
+ ArrayList axisOpParams = oldAxisOperation.getParameters();
+ if (axisOpParams != null) {
+ AxisOperation newAxisOperation = newMessage
+ .getAxisOperation();
+ Iterator iter = axisOpParams.iterator();
+ while (iter.hasNext()) {
+ Parameter nextParam = (Parameter) iter.next();
+ Parameter newParam = new ParameterImpl();
+
+ newParam.setName(nextParam.getName());
+ newParam.setValue(nextParam.getValue());
+
+ newAxisOperation.addParameter(newParam);
+ }
+ }
+ }
+
+ } catch (AxisFault e) {
+ log
+ .error("Could not copy parameters when creating the new RM Message");
+ throw new SandeshaException(e.getMessage());
+ }
+
+ // TODO optimize by cloning the Map rather than copying one by one.
+
+ // operationContext properties
+ OperationContext oldOpContext = relatedMessage.getOperationContext();
+ if (oldOpContext != null) {
+ Map oldOpContextProperties = oldOpContext.getProperties();
+ if (oldOpContextProperties != null) {
+ OperationContext newOpContext = newMessage
+ .getOperationContext();
+ Iterator keyIter = oldOpContextProperties.keySet().iterator();
+ while (keyIter.hasNext()) {
+ String key = (String) keyIter.next();
+ newOpContext.setProperty(key, oldOpContextProperties
+ .get(key));
+ // newAxisOperation.addParameter(new ParameterImpl
+ // (nextParam.getName(),(String) nextParam.getValue()));
+ }
+ }
+ }
+
+ // MessageContext properties
+ if (relatedMessage != null && newMessage != null) {
+ Map oldMsgContextProperties = relatedMessage.getProperties();
+ if (oldMsgContextProperties != null) {
+ Iterator keyIter = oldMsgContextProperties.keySet().iterator();
+ while (keyIter.hasNext()) {
+ String key = (String) keyIter.next();
+ newMessage.setProperty(key, oldMsgContextProperties
+ .get(key));
+ // newAxisOperation.addParameter(new ParameterImpl
+ // (nextParam.getName(),(String) nextParam.getValue()));
+ }
+ }
+ }
+
+ // setting an options with properties copied from the old one.
+ Options relatesMessageOptions = relatedMessage.getOptions();
+ if (relatesMessageOptions != null) {
+ Options newMessageOptions = newMessage.getOptions();
+ if (newMessageOptions == null) {
+ newMessageOptions = new Options();
+ newMessage.setOptions(newMessageOptions);
+ }
+
+
+ Map relatedMessageProperties = relatesMessageOptions
+ .getProperties();
+ Iterator keys = relatedMessageProperties.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ newMessageOptions.setProperty(key, relatedMessageProperties
+ .get(key));
+ }
+
+ Options relatedMessageParentOptions = relatesMessageOptions
+ .getParent();
+ if (relatedMessageParentOptions != null) {
+ Map relatedMessageParentProperties = relatedMessageParentOptions.getProperties();
+ keys = relatedMessageParentProperties.keySet().iterator();
+ while (keys.hasNext()) {
+ String key = (String) keys.next();
+ newMessageOptions.setProperty(key,
+ relatedMessageParentProperties.get(key));
+ }
}
}
}
@@ -93,14 +221,15 @@
* @throws SandeshaException
*/
public static RMMsgContext createCreateSeqMsg(
- RMMsgContext applicationRMMsg, String internalSequenceId, String acksTo)
- throws SandeshaException {
+ RMMsgContext applicationRMMsg, String internalSequenceId,
+ String acksTo) throws SandeshaException {
MessageContext applicationMsgContext = applicationRMMsg
.getMessageContext();
if (applicationMsgContext == null)
throw new SandeshaException("Application message is null");
- ConfigurationContext context = applicationMsgContext.getConfigurationContext();
+ ConfigurationContext context = applicationMsgContext
+ .getConfigurationContext();
if (context == null)
throw new SandeshaException("Configuration Context is null");
@@ -113,13 +242,16 @@
.getSequencePropretyBeanMgr();
MessageContext createSeqmsgContext;
try {
- //creating by copying common contents. (this will not set contexts
+ // creating by copying common contents. (this will not set contexts
// except for configCtx).
AxisOperation createSequenceOperation = AxisOperationFactory
.getAxisOperation(AxisOperation.MEP_CONSTANT_OUT_IN);
-
+
createSeqmsgContext = SandeshaUtil.createNewRelatedMessageContext(
applicationRMMsg, createSequenceOperation);
+
+ initializeCreation(applicationMsgContext, createSeqmsgContext);
+
OperationContext createSeqOpCtx = createSeqmsgContext
.getOperationContext();
String createSeqMsgId = SandeshaUtil.getUUID();
@@ -130,7 +262,7 @@
throw new SandeshaException(e.getMessage());
}
- setUpMessage(applicationMsgContext, createSeqmsgContext);
+ // setUpMessage(applicationMsgContext, createSeqmsgContext);
AxisOperation appMsgOperationDesc = applicationMsgContext
.getAxisOperation();
@@ -158,7 +290,7 @@
CreateSequence createSequencePart = new CreateSequence(factory);
- //Adding sequence offer - if present
+ // Adding sequence offer - if present
OperationContext operationcontext = applicationMsgContext
.getOperationContext();
if (operationcontext != null) {
@@ -173,7 +305,8 @@
}
}
- SequencePropertyBean replyToBean = seqPropMgr.retrieve(internalSequenceId,
+ SequencePropertyBean replyToBean = seqPropMgr.retrieve(
+ internalSequenceId,
Sandesha2Constants.SequenceProperties.REPLY_TO_EPR);
SequencePropertyBean toBean = seqPropMgr.retrieve(internalSequenceId,
Sandesha2Constants.SequenceProperties.TO_EPR);
@@ -181,7 +314,7 @@
if (toBean == null || toBean.getValue() == null)
throw new SandeshaException("To EPR is not set.");
- EndpointReference toEPR = new EndpointReference (toBean.getValue());
+ EndpointReference toEPR = new EndpointReference(toBean.getValue());
EndpointReference replyToEPR = null;
EndpointReference acksToEPR = null;
@@ -191,19 +324,19 @@
acksToEPR = new EndpointReference(acksTo);
if (replyToBean != null && replyToBean.getValue() != null)
- replyToEPR = new EndpointReference (replyToBean.getValue());
+ replyToEPR = new EndpointReference(replyToBean.getValue());
createSeqRMMsg.setTo(toEPR);
- //ReplyTo will be set only if not null.
+ // ReplyTo will be set only if not null.
if (replyToEPR != null)
createSeqRMMsg.setReplyTo(replyToEPR);
createSequencePart.setAcksTo(new AcksTo(
new Address(acksToEPR, factory), factory));
- createSeqRMMsg.setMessagePart(Sandesha2Constants.MessageParts.CREATE_SEQ,
- createSequencePart);
+ createSeqRMMsg.setMessagePart(
+ Sandesha2Constants.MessageParts.CREATE_SEQ, createSequencePart);
try {
createSeqRMMsg.addSOAPEnvelope();
@@ -211,10 +344,13 @@
throw new SandeshaException(e1.getMessage());
}
- createSeqRMMsg.setAction(Sandesha2Constants.WSRM.Actions.ACTION_CREATE_SEQUENCE);
+ createSeqRMMsg
+ .setAction(Sandesha2Constants.WSRM.Actions.ACTION_CREATE_SEQUENCE);
createSeqRMMsg
.setSOAPAction(Sandesha2Constants.WSRM.Actions.SOAP_ACTION_CREATE_SEQUENCE);
+ finalizeCreation(applicationMsgContext, createSeqmsgContext);
+
return createSeqRMMsg;
}
@@ -249,20 +385,24 @@
MessageContext terminateMessage = SandeshaUtil
.createNewRelatedMessageContext(referenceRMMessage,
terminateOperation);
+
+ initializeCreation(referenceMessage, terminateMessage);
+
RMMsgContext terminateRMMessage = MsgInitializer
.initializeMessage(terminateMessage);
if (terminateMessage == null)
throw new SandeshaException("MessageContext is null");
- setUpMessage(referenceMessage, terminateMessage);
+ // setUpMessage(referenceMessage, terminateMessage);
SOAPFactory factory = SOAPAbstractFactory.getSOAPFactory(SandeshaUtil
.getSOAPVersion(referenceMessage.getEnvelope()));
terminateMessage.setMessageID(SandeshaUtil.getUUID());
- ConfigurationContext configCtx = referenceMessage.getConfigurationContext();
+ ConfigurationContext configCtx = referenceMessage
+ .getConfigurationContext();
if (configCtx == null)
throw new SandeshaException("Configuration Context is null");
@@ -283,9 +423,12 @@
Identifier identifier = new Identifier(factory);
identifier.setIndentifer(sequenceId);
terminateSequencePart.setIdentifier(identifier);
- terminateRMMessage.setMessagePart(Sandesha2Constants.MessageParts.TERMINATE_SEQ,
+ terminateRMMessage.setMessagePart(
+ Sandesha2Constants.MessageParts.TERMINATE_SEQ,
terminateSequencePart);
+ finalizeCreation(referenceMessage, terminateMessage);
+
return terminateRMMessage;
}
@@ -346,7 +489,7 @@
outMessage.setEnvelope(envelope);
- setUpMessage(createSeqMessage.getMessageContext(), outMessage);
+ initializeCreation(createSeqMessage.getMessageContext(), outMessage);
RMMsgContext createSeqResponse = null;
try {
@@ -355,6 +498,8 @@
throw new AxisFault("Cant initialize the message");
}
+ finalizeCreation(createSeqMessage.getMessageContext(), outMessage);
+
return createSeqResponse;
}
@@ -395,10 +540,12 @@
Sandesha2Constants.SequenceProperties.COMPLETED_MESSAGES);
String msgNoList = (String) seqBean.getValue();
- ArrayList ackRangeArrayList = SandeshaUtil.getAckRangeArrayList(msgNoList,factory);
+ ArrayList ackRangeArrayList = SandeshaUtil.getAckRangeArrayList(
+ msgNoList, factory);
Iterator iterator = ackRangeArrayList.iterator();
while (iterator.hasNext()) {
- AcknowledgementRange ackRange = (AcknowledgementRange) iterator.next();
+ AcknowledgementRange ackRange = (AcknowledgementRange) iterator
+ .next();
sequenceAck.addAcknowledgementRanges(ackRange);
}
@@ -433,7 +580,7 @@
RMMsgContext ackRMMsgCtx = MsgInitializer
.initializeMessage(ackMsgCtx);
- setUpMessage(applicationMsgCtx, ackMsgCtx);
+ initializeCreation(applicationMsgCtx, ackMsgCtx);
Sequence reqSequence = (Sequence) applicationRMMsgCtx
.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
@@ -444,6 +591,9 @@
String sequenceId = reqSequence.getIdentifier().getIdentifier();
addAckMessage(ackRMMsgCtx, sequenceId);
+
+ finalizeCreation(applicationMsgCtx, ackMsgCtx);
+
return ackRMMsgCtx;
} catch (AxisFault e) {
throw new SandeshaException(e.getMessage());
Modified: webservices/sandesha/trunk/src/org/apache/sandesha2/workers/Sender.java
URL: http://svn.apache.org/viewcvs/webservices/sandesha/trunk/src/org/apache/sandesha2/workers/Sender.java?rev=375294&r1=375293&r2=375294&view=diff
==============================================================================
--- webservices/sandesha/trunk/src/org/apache/sandesha2/workers/Sender.java (original)
+++ webservices/sandesha/trunk/src/org/apache/sandesha2/workers/Sender.java Mon Feb 6 06:55:49 2006
@@ -126,10 +126,14 @@
String key = (String) bean.getMessageContextRefKey();
MessageContext msgCtx = storageManager.retrieveMessageContext(key,context);
+ if (msgCtx==null) {
+ String message = "Message context is not present in the storage";
+ }
//sender will not send the message if following property is set and not true.
//But it will set if it is not set (null)
//This is used to make sure that the mesage get passed the Sandesha2TransportSender.
+
String qualifiedForSending = (String) msgCtx.getProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING);
if (qualifiedForSending!=null && !qualifiedForSending.equals(Sandesha2Constants.VALUE_TRUE)) {
continue;
@@ -275,7 +279,7 @@
} catch (AxisFault e1) {
e1.printStackTrace();
- } catch (Exception e3) {
+ } catch (Throwable e3) {
e3.printStackTrace();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: sandesha-dev-unsubscribe@ws.apache.org
For additional commands, e-mail: sandesha-dev-help@ws.apache.org