Hi, This checkin makes the auth implementation depend on the Sun JAX-WS RI stack (Metro). Is it not possible to keep independence from the actual implementation (I haven't looked, not knowing JAX-WS in great detail)?
Thanks, Florent On Mon, Nov 29, 2010 at 1:09 PM, <[email protected]> wrote: > Author: fmui > Date: Mon Nov 29 12:09:34 2010 > New Revision: 1040081 > > URL: http://svn.apache.org/viewvc?rev=1040081&view=rev > Log: > - reimplemented Web Services server authentication handler - content upload > is now drastically faster > > Modified: > > incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AuthHandler.java > > incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/AbstractWriteObjectIT.java > > Modified: > incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AuthHandler.java > URL: > http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AuthHandler.java?rev=1040081&r1=1040080&r2=1040081&view=diff > ============================================================================== > --- > incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AuthHandler.java > (original) > +++ > incubator/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-bindings/src/main/java/org/apache/chemistry/opencmis/server/impl/webservices/AuthHandler.java > Mon Nov 29 12:09:34 2010 > @@ -18,36 +18,64 @@ > */ > package org.apache.chemistry.opencmis.server.impl.webservices; > > +import java.util.ArrayList; > import java.util.HashMap; > import java.util.HashSet; > +import java.util.List; > import java.util.Map; > import java.util.Set; > > +import javax.xml.bind.JAXBContext; > +import javax.xml.bind.JAXBElement; > +import javax.xml.bind.JAXBException; > +import javax.xml.bind.annotation.XmlAccessType; > +import javax.xml.bind.annotation.XmlAccessorType; > +import javax.xml.bind.annotation.XmlAnyAttribute; > +import javax.xml.bind.annotation.XmlAnyElement; > +import javax.xml.bind.annotation.XmlAttribute; > +import javax.xml.bind.annotation.XmlElement; > +import javax.xml.bind.annotation.XmlElementDecl; > +import javax.xml.bind.annotation.XmlID; > +import javax.xml.bind.annotation.XmlRegistry; > +import javax.xml.bind.annotation.XmlSchemaType; > +import javax.xml.bind.annotation.XmlSeeAlso; > +import javax.xml.bind.annotation.XmlType; > +import javax.xml.bind.annotation.XmlValue; > +import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; > +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; > import javax.xml.namespace.QName; > -import javax.xml.soap.SOAPElement; > -import javax.xml.soap.SOAPHeader; > -import javax.xml.soap.SOAPMessage; > import javax.xml.ws.handler.MessageContext; > import javax.xml.ws.handler.MessageContext.Scope; > -import javax.xml.ws.handler.soap.SOAPHandler; > -import javax.xml.ws.handler.soap.SOAPMessageContext; > > import org.apache.chemistry.opencmis.commons.server.CallContext; > > +import com.sun.xml.ws.api.handler.MessageHandler; > +import com.sun.xml.ws.api.handler.MessageHandlerContext; > +import com.sun.xml.ws.api.message.Header; > +import com.sun.xml.ws.api.message.HeaderList; > +import com.sun.xml.ws.api.message.Message; > + > /** > * This class tries to extract a user name and a password from a > UsernameToken. > - * > - * @author <a href="mailto:[email protected]">Florian Müller</a> > - * > */ > -public class AuthHandler implements SOAPHandler<SOAPMessageContext> { > +public class AuthHandler implements MessageHandler<MessageHandlerContext> { > > private static final String WSSE_NS = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; > private static final QName WSSE_SECURITY = new QName(WSSE_NS, "Security"); > private static final QName WSSE_USERNAME_TOKEN = new QName(WSSE_NS, > "UsernameToken"); > - private static final QName WSSE_USERNAME = new QName(WSSE_NS, > "Username"); > private static final QName WSSE_PASSWORD = new QName(WSSE_NS, "Password"); > > + private static final JAXBContext WSSE_CONTEXT; > + static { > + JAXBContext jc = null; > + try { > + jc = JAXBContext.newInstance(ObjectFactory.class); > + } catch (JAXBException e) { > + e.printStackTrace(); > + } > + WSSE_CONTEXT = jc; > + } > + > private static final Set<QName> HEADERS = new HashSet<QName>(); > static { > HEADERS.add(WSSE_SECURITY); > @@ -60,38 +88,216 @@ public class AuthHandler implements SOAP > public void close(MessageContext context) { > } > > - public boolean handleFault(SOAPMessageContext context) { > + public boolean handleFault(MessageHandlerContext context) { > return true; > } > > - public boolean handleMessage(SOAPMessageContext context) { > + �...@suppresswarnings("unchecked") > + public boolean handleMessage(MessageHandlerContext context) { > Boolean outboundProperty = (Boolean) > context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); > if (outboundProperty.booleanValue()) { > // we are only looking at inbound messages > return true; > } > > + String username = null; > + String password = null; > + > try { > // read the header > - SOAPMessage msg = context.getMessage(); > - SOAPHeader sh = msg.getSOAPHeader(); > - SOAPElement securityElement = (SOAPElement) > sh.getChildElements(WSSE_SECURITY).next(); > - SOAPElement tokenElement = (SOAPElement) > securityElement.getChildElements(WSSE_USERNAME_TOKEN).next(); > - SOAPElement userElement = (SOAPElement) > tokenElement.getChildElements(WSSE_USERNAME).next(); > - SOAPElement passwordElement = (SOAPElement) > tokenElement.getChildElements(WSSE_PASSWORD).next(); > - > - // add user and password to context > - Map<String, String> callContextMap = new HashMap<String, > String>(); > - callContextMap.put(CallContext.USERNAME, userElement.getValue()); > - callContextMap.put(CallContext.PASSWORD, > passwordElement.getValue()); > - > - context.put(AbstractService.CALL_CONTEXT_MAP, callContextMap); > - context.setScope(AbstractService.CALL_CONTEXT_MAP, > Scope.APPLICATION); > + Message msg = context.getMessage(); > + HeaderList hl = msg.getHeaders(); > + Header securityHeader = hl.get(WSSE_SECURITY, true); > + > + JAXBElement<SecurityHeaderType> sht = > securityHeader.readAsJAXB(WSSE_CONTEXT.createUnmarshaller()); > + > + for (Object uno : sht.getValue().getAny()) { > + if ((uno instanceof JAXBElement) && ((JAXBElement<?>) > uno).getValue() instanceof UsernameTokenType) { > + UsernameTokenType utt = (UsernameTokenType) > ((JAXBElement<UsernameTokenType>) uno).getValue(); > + username = utt.getUsername().getValue(); > + > + for (Object po : utt.getAny()) { > + if ((po instanceof JAXBElement) && ((JAXBElement<?>) > po).getValue() instanceof PasswordString) { > + password = ((JAXBElement<PasswordString>) > po).getValue().getValue(); > + break; > + } > + } > + > + break; > + } > + } > } catch (Exception e) { > // something went wrong, e.g. a part of the SOAP header wasn't set > - throw new RuntimeException("UsernameToken not set!", e); > } > > + // add user and password to context > + Map<String, String> callContextMap = new HashMap<String, String>(); > + callContextMap.put(CallContext.USERNAME, username); > + callContextMap.put(CallContext.PASSWORD, password); > + > + context.put(AbstractService.CALL_CONTEXT_MAP, callContextMap); > + context.setScope(AbstractService.CALL_CONTEXT_MAP, > Scope.APPLICATION); > + > return true; > } > + > + // --- JAXB classes --- > + > + �...@xmlregistry > + public static class ObjectFactory { > + > + public ObjectFactory() { > + } > + > + public SecurityHeaderType createSecurityHeaderType() { > + return new SecurityHeaderType(); > + } > + > + public UsernameTokenType createUsernameTokenType() { > + return new UsernameTokenType(); > + } > + > + public PasswordString createPasswordString() { > + return new PasswordString(); > + } > + > + public AttributedString createAttributedString() { > + return new AttributedString(); > + } > + > + �...@xmlelementdecl(namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", > name = "Security") > + public JAXBElement<SecurityHeaderType> > createSecurity(SecurityHeaderType value) { > + return new JAXBElement<SecurityHeaderType>(WSSE_SECURITY, > SecurityHeaderType.class, null, value); > + } > + > + �...@xmlelementdecl(namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", > name = "UsernameToken") > + public JAXBElement<UsernameTokenType> > createUsernameToken(UsernameTokenType value) { > + return new JAXBElement<UsernameTokenType>(WSSE_USERNAME_TOKEN, > UsernameTokenType.class, null, value); > + } > + > + �...@xmlelementdecl(namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", > name = "Password") > + public JAXBElement<PasswordString> createPassword(PasswordString > value) { > + return new JAXBElement<PasswordString>(WSSE_PASSWORD, > PasswordString.class, null, value); > + } > + > + } > + > + �...@xmlaccessortype(XmlAccessType.FIELD) > + �...@xmltype(name = "SecurityHeaderType", propOrder = { "any" }) > + public static class SecurityHeaderType { > + > + �...@xmlanyelement(lax = true) > + protected List<Object> any; > + �...@xmlanyattribute > + private Map<QName, String> otherAttributes = new HashMap<QName, > String>(); > + > + public List<Object> getAny() { > + if (any == null) { > + any = new ArrayList<Object>(); > + } > + return this.any; > + } > + > + public Map<QName, String> getOtherAttributes() { > + return otherAttributes; > + } > + > + } > + > + �...@xmlaccessortype(XmlAccessType.FIELD) > + �...@xmltype(name = "UsernameTokenType", propOrder = { "username", "any" > }) > + public static class UsernameTokenType { > + > + �...@xmlelement(name = "Username", namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", > required = true) > + protected AttributedString username; > + �...@xmlanyelement(lax = true) > + protected List<Object> any; > + �...@xmlattribute(name = "Id", namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") > + �...@xmljavatypeadapter(CollapsedStringAdapter.class) > + �...@xmlid > + �...@xmlschematype(name = "ID") > + protected String id; > + �...@xmlanyattribute > + private Map<QName, String> otherAttributes = new HashMap<QName, > String>(); > + > + public AttributedString getUsername() { > + return username; > + } > + > + public void setUsername(AttributedString value) { > + this.username = value; > + } > + > + public List<Object> getAny() { > + if (any == null) { > + any = new ArrayList<Object>(); > + } > + return this.any; > + } > + > + public String getId() { > + return id; > + } > + > + public void setId(String value) { > + this.id = value; > + } > + > + public Map<QName, String> getOtherAttributes() { > + return otherAttributes; > + } > + } > + > + �...@xmlaccessortype(XmlAccessType.FIELD) > + �...@xmltype(name = "PasswordString") > + public static class PasswordString extends AttributedString { > + > + �...@xmlattribute(name = "Type") > + �...@xmlschematype(name = "anyURI") > + protected String type; > + > + public String getType() { > + return type; > + } > + > + public void setType(String value) { > + this.type = value; > + } > + } > + > + �...@xmlaccessortype(XmlAccessType.FIELD) > + �...@xmltype(name = "AttributedString", propOrder = { "value" }) > + �...@xmlseealso({ PasswordString.class }) > + public static class AttributedString { > + > + �...@xmlvalue > + protected String value; > + �...@xmlattribute(name = "Id", namespace = > "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd") > + �...@xmljavatypeadapter(CollapsedStringAdapter.class) > + �...@xmlid > + �...@xmlschematype(name = "ID") > + protected String id; > + �...@xmlanyattribute > + private Map<QName, String> otherAttributes = new HashMap<QName, > String>(); > + > + public String getValue() { > + return value; > + } > + > + public void setValue(String value) { > + this.value = value; > + } > + > + public String getId() { > + return id; > + } > + > + public void setId(String value) { > + this.id = value; > + } > + > + public Map<QName, String> getOtherAttributes() { > + return otherAttributes; > + } > + } > } > > Modified: > incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/AbstractWriteObjectIT.java > URL: > http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/AbstractWriteObjectIT.java?rev=1040081&r1=1040080&r2=1040081&view=diff > ============================================================================== > --- > incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/AbstractWriteObjectIT.java > (original) > +++ > incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit/runtime/AbstractWriteObjectIT.java > Mon Nov 29 12:09:34 2010 > @@ -135,7 +135,11 @@ public abstract class AbstractWriteObjec > ContentStream contentStream = > this.session.getObjectFactory().createContentStream(filename, size, mimetype, > in); > assertNotNull(contentStream); > > + long start = System.currentTimeMillis(); > doc.setContentStream(contentStream, true); > + long end = System.currentTimeMillis(); > + > + log.info("setContentStream of " + size + " bytes:" + (end - start) + > "ms"); > } > > @Test > @@ -523,24 +527,23 @@ public abstract class AbstractWriteObjec > > ContentStream cs5 = tdoc4.getContentStream(); > assertNull(cs5); > - > + > assertEquals(false, tdoc5.isMarkedForDelete()); > - > + > tdoc5.delete(true); > > - assertEquals(true, tdoc5.isMarkedForDelete()); > + assertEquals(true, tdoc5.isMarkedForDelete()); > > ObjectId id5 = tdoc5.save(); > assertNull(id5); > - > + > // check > try { > this.session.getObject(id4, oc); > fail("CmisObjectNotFoundException expected!"); > - } > - catch (CmisObjectNotFoundException e) { > + } catch (CmisObjectNotFoundException e) { > // expected > - } > + } > } > > private byte[] readContent(ContentStream contentStream) throws Exception { > > > -- Florent Guillaume, Director of R&D, Nuxeo Open Source, Java EE based, Enterprise Content Management (ECM) http://www.nuxeo.com http://www.nuxeo.org +33 1 40 33 79 87
