Hello,
Juste a post concerning the generation of proxies client for DFS web service project due to ANT script and utilities classes.
Several steps:
- Create a project TESTWsClientGenerator
- Add the JAR emc-dfs-rt-remote.jar and emc-dfs-rt.jar (from DocumentumCoreProject\dfs6.7\emc-dfs-sdk-6.7\lib\java) in the BuildPath of your project
- Get in your workplace the CXF librairies : C:\Workspaces\HUO\ECMExternalLibraries\org\apache\cfx-3.0.3 http://cxf.apache.org/cxf-303-release-notes.html
- Create a source folder wsgenerator
- Create the package com.emc.documentum.fs.datamodel.core.content
- Create the below utilities classes BinaryContent and DataHandlerContent in this com.emc.documentum.fs.datamodel.core.content:
package com.emc.documentum.fs.datamodel.core.content; import java.io.Serializable; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for BinaryContent complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="BinaryContent"> * <complexContent> * <extension base="{http://content.core.datamodel.fs.documentum.emc.com/}Content"> * <sequence> * <element name="Value" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/> * </sequence> * </extension> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "BinaryContent", propOrder = { "value" }) public class BinaryContent extends Content implements Serializable { private final static long serialVersionUID = 1397139757393L; @XmlElement(name = "Value", required = true) protected byte[] value; /** * Gets the value of the value property. * * @return * possible object is * byte[] */ public byte[] getValue() { return value; } /** * Sets the value of the value property. * * @param value * allowed object is * byte[] */ public void setValue(byte[] value) { this.value = value; } }
package com.emc.documentum.fs.datamodel.core.content; import java.io.Serializable; import javax.activation.DataHandler; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlMimeType; import javax.xml.bind.annotation.XmlType; /** * <p>Java class for DataHandlerContent complex type. * * <p>The following schema fragment specifies the expected content contained within this class. * * <pre> * <complexType name="DataHandlerContent"> * <complexContent> * <extension base="{http://content.core.datamodel.fs.documentum.emc.com/}Content"> * <sequence> * <element name="Value" type="{http://www.w3.org/2001/XMLSchema}base64Binary"/> * </sequence> * </extension> * </complexContent> * </complexType> * </pre> * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "DataHandlerContent", propOrder = { "value" }) public class DataHandlerContent extends Content implements Serializable { private final static long serialVersionUID = 1397139757393L; @XmlElement(name = "Value", required = true) @XmlMimeType("*/*") protected DataHandler value; /** * Gets the value of the value property. * * @return * possible object is * {@link DataHandler } * */ public DataHandler getValue() { return value; } /** * Sets the value of the value property. * * @param value * allowed object is * {@link DataHandler } * */ public void setValue(DataHandler value) { this.value = value; } }
- Create the package com.emc.documentum.fs.utils
- Create the below utilities classes ContentUtil and ServiceProxyUtils in this com.emc.documentum.fs.utils:
package com.emc.documentum.fs.utils; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; import java.net.URLConnection; import java.text.MessageFormat; import javax.activation.DataHandler; import javax.activation.DataSource; import com.emc.documentum.fs.datamodel.core.content.BinaryContent; import com.emc.documentum.fs.datamodel.core.content.Content; import com.emc.documentum.fs.datamodel.core.content.DataHandlerContent; import com.emc.documentum.fs.datamodel.core.content.UrlContent; public class ContentUtil { private static class InputStreamDataSource implements DataSource { private final InputStream inputStream; private final String type; public InputStreamDataSource(InputStream inputStream) throws IOException { this(inputStream, URLConnection.guessContentTypeFromStream(inputStream)); } public InputStreamDataSource(InputStream inputStream, String type) { this.inputStream = inputStream; this.type = type; } @Override public String getContentType() { if (this.type == null) { return "application/octet-stream"; } return this.type; } @Override public InputStream getInputStream() throws IOException { return inputStream; } @Override public String getName() { return InputStreamDataSource.class.getSimpleName(); } @Override public OutputStream getOutputStream() throws IOException { throw new IOException("Not Supported"); } } private static DataHandlerContent getDataHandlerContent(DataSource dataSource, String format) { DataHandlerContent dataHandlerContent = new DataHandlerContent(); dataHandlerContent.setFormat(format); dataHandlerContent.setValue(new DataHandler(dataSource)); return dataHandlerContent; } public static DataHandlerContent getDataHandlerContent(File file, String format) throws FileNotFoundException, IOException { return getDataHandlerContent(new InputStreamDataSource(new FileInputStream(file), URLConnection.guessContentTypeFromName(file.getAbsolutePath())), format); } public static DataHandlerContent getDataHandlerContent(InputStream inputStream, String format) throws IOException { return getDataHandlerContent(new InputStreamDataSource(inputStream), format); } public static InputStream getInputStream(Content content) throws MalformedURLException, IOException { if (content == null) { throw new IllegalArgumentException("content cannot be null"); } if (content instanceof UrlContent) { UrlContent urlContent = (UrlContent) content; URL url = new URL(urlContent.getUrl()); URLConnection urlConnection = url.openConnection(Proxy.NO_PROXY); InputStream inputStream = urlConnection.getInputStream(); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); return bufferedInputStream; } else if (content instanceof BinaryContent) { BinaryContent binaryContent = (BinaryContent) content; byte[] data = binaryContent.getValue(); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(data); return byteArrayInputStream; } else if (content instanceof DataHandlerContent) { DataHandlerContent dataHandlerContent = (DataHandlerContent) content; DataHandler dataHandler = dataHandlerContent.getValue(); InputStream inputStream = dataHandler.getInputStream(); return inputStream; } throw new RuntimeException(MessageFormat.format("{0} content is not supported", content)); } }
package com.emc.documentum.fs.utils; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.text.MessageFormat; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import org.w3c.dom.Document; import org.w3c.dom.Element; public class ServiceProxyUtils { private static final Logger logger = Logger.getLogger(ServiceProxyUtils.class.getName()); public static Element getSecurityHeaderForRegisteredToken(String token) throws ParserConfigurationException { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element wsseSecurity = document.createElementNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:Security"); Element wsseToken = (Element) wsseSecurity.appendChild(document.createElementNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "wsse:BinarySecurityToken")); wsseToken.setAttribute("QualificationValueType", "http://schemas.emc.com/documentum#ResourceAccessToken"); wsseToken.setAttributeNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "wsu:Id", "RAD"); wsseToken.setTextContent(token); return wsseSecurity; } public static Element getSecurityHeaderForKerberosToken(String token) throws ParserConfigurationException { Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element securityElement = (Element) document.createElementNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "ns3:Security"); securityElement.setAttribute("xmlns:ns1", "http://www.w3.org/2003/05/soap-envelope"); securityElement.setAttribute("xmlns:ns2", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); Element wsseToken = (Element) securityElement.appendChild(document.createElement("ns3:BinarySecurityToken")); wsseToken.setAttribute("ValueType", "http://docs.oasis-open.org/wss/oasis-wss-kerberos-token-profile-1.1#Kerberosv5_AP_REQ"); wsseToken.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); wsseToken.setTextContent(token); return securityElement; } public static Element getSecurityHeaderForJAXBObject(Object object) throws JAXBException, ParserConfigurationException { javax.xml.bind.JAXBContext j = javax.xml.bind.JAXBContext.newInstance(object.getClass()); org.w3c.dom.Document document = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); j.createMarshaller().marshal(object, document); return document.getDocumentElement(); } public static void addBasicSecurity(javax.xml.ws.Service service, final String userName, final String password) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { service.setHandlerResolver(new javax.xml.ws.handler.HandlerResolver() { @SuppressWarnings("rawtypes") @Override public java.util.List<javax.xml.ws.handler.Handler> getHandlerChain(javax.xml.ws.handler.PortInfo portInfo) { java.util.List<javax.xml.ws.handler.Handler> handlerList = new java.util.ArrayList<javax.xml.ws.handler.Handler>(); handlerList.add(new javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>() { public void close(javax.xml.ws.handler.MessageContext context) { } public java.util.Set<javax.xml.namespace.QName> getHeaders() { return new java.util.TreeSet<javax.xml.namespace.QName>(); } public boolean handleFault(javax.xml.ws.handler.soap.SOAPMessageContext context) { return true; } public boolean handleMessage(javax.xml.ws.handler.soap.SOAPMessageContext context) { Boolean outboundProperty = (Boolean) context.get(javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outboundProperty.booleanValue()) { try { javax.xml.soap.SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope(); javax.xml.soap.SOAPHeader header = envelope.addHeader(); SOAPElement serviceContextElement = javax.xml.soap.SOAPFactory.newInstance().createElement(new QName("http://context.core.datamodel.fs.documentum.emc.com/", "ServiceContext")); SOAPElement basicIdentityElement = serviceContextElement.addChildElement(javax.xml.soap.SOAPFactory.newInstance().createElement("Identities")); basicIdentityElement.setAttribute("xsi:type", "BasicIdentity"); basicIdentityElement.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); basicIdentityElement.setAttribute("userName", userName); basicIdentityElement.setAttribute("password", password); header.addChildElement(serviceContextElement); } catch (Exception e) { throw new RuntimeException("SOAPException in handler => unable to add security layer in header", e); } } else { // inbound => Nothing to do } return true; } }); return handlerList; } }); } public static <T extends javax.xml.ws.Service> T getService(Class<T> clazz, java.net.URL wsdlLocation) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { return getService(clazz, wsdlLocation, null); } public static <T extends javax.xml.ws.Service> T getService(Class<T> clazz, java.net.URL wsdlLocation, final org.w3c.dom.Element wsseSecurity) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { javax.xml.ws.WebServiceClient webServiceClient = clazz.getAnnotation(javax.xml.ws.WebServiceClient.class); return getService(clazz, wsdlLocation, new javax.xml.namespace.QName(webServiceClient.targetNamespace(), webServiceClient.name()), wsseSecurity); } public static <T extends javax.xml.ws.Service> T getService(Class<T> clazz, java.net.URL wsdlLocation, javax.xml.namespace.QName serviceName, final org.w3c.dom.Element wsseSecurity) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Constructor<T> constructor = clazz.getConstructor(java.net.URL.class, javax.xml.namespace.QName.class); T result = constructor.newInstance(wsdlLocation, serviceName); if (wsseSecurity != null) { result.setHandlerResolver(new javax.xml.ws.handler.HandlerResolver() { @SuppressWarnings("rawtypes") @Override public java.util.List<javax.xml.ws.handler.Handler> getHandlerChain(javax.xml.ws.handler.PortInfo portInfo) { java.util.List<javax.xml.ws.handler.Handler> handlerList = new java.util.ArrayList<javax.xml.ws.handler.Handler>(); handlerList.add(new javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>() { public void close(javax.xml.ws.handler.MessageContext context) { } public java.util.Set<javax.xml.namespace.QName> getHeaders() { return new java.util.TreeSet<javax.xml.namespace.QName>(); } public boolean handleFault(javax.xml.ws.handler.soap.SOAPMessageContext context) { return true; } public boolean handleMessage(javax.xml.ws.handler.soap.SOAPMessageContext context) { Boolean outboundProperty = (Boolean) context.get(javax.xml.ws.handler.MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (outboundProperty.booleanValue()) { try { javax.xml.soap.SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope(); javax.xml.soap.SOAPHeader header = envelope.addHeader(); header.addChildElement(javax.xml.soap.SOAPFactory.newInstance().createElement(wsseSecurity)); } catch (SOAPException e) { logger.log(Level.SEVERE, MessageFormat.format("SOAPException in handler => unable to add security layer {0} in header", wsseSecurity), e); } } else { // inbound => Nothing to do } return true; } }); return handlerList; } }); } return result; } private ServiceProxyUtils() { super(); } }
- Create a file build.properties:
application.version=1 build.vendor=JavaBlog.fr - Java.lu
- Create a file simple-binding.xjb:
<?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc"> <jaxb:globalBindings> <xjc:simple /> <xjc:serializable uid="1397139757393" /> </jaxb:globalBindings> </jaxb:bindings>
- Create a file wsdllist.txt:
https://ws.java.lu/services/mycontext/MyWebServiceForECMService?wsdl https://ws.java.lu/services/mycontext/runtime/ContextRegistryService?wsdl
- Create an ANT script build.xml. Modify the folder of CXF home in script cxf.home:
<property name="cxf.home" location="C:\Workspaces\HUO\ECMExternalLibraries\org\apache\cfx-3.0.3" />
<?xml version="1.0" encoding="UTF-8"?> <project name="TESTWsClientGenerator" default="dist" basedir="."> <property file="build.properties" /> <property name="build" value="build" /> <property name="src" value="src" /> <property name="build.src" value="${build}\${src}" /> <property name="build.classes" value="${build}\classes" /> <property name="build.lib" value="lib" /> <property name="build.dist" location="${build}/dist" /> <property name="build.ClientAcceptanceProxy.jar" location="${build.dist}/${ant.project.name}.jar" /> <property name="cxf.home" location="C:\Workspaces\HUO\ECMExternalLibraries\org\apache\cfx-3.0.3" /> <target name="dist" depends="create_proxy, build"> <jar basedir="${build.classes}" destfile="${build.ClientAcceptanceProxy.jar}" manifest="${build}/MANIFEST.MF" /> </target> <target name="build" depends="javac" /> <target name="init"> <delete dir="${build}" failonerror="false" /> <mkdir dir="${build}" /> <mkdir dir="${build.lib}" /> <mkdir dir="${build.src}" /> </target> <target name="javac" depends="javaclasspath" description="compile the source"> <delete dir="${build.classes}" /> <mkdir dir="${build.classes}" /> <!-- compile --> <javac destdir="${build.classes}" debug="true" srcdir="${build.src}" source="1.5" target="1.5" encoding="8859_1"> <classpath refid="classpath.compile" /> </javac> <!-- copy all resources to the classes directory --> <copy todir="${build.classes}"> <fileset dir="${build.src}"> <include name="**/*" /> <exclude name="**/*.java" /> </fileset> </copy> <tstamp> <format property="build.time" pattern="dd/MM/yyyy HH:mm:ss" /> </tstamp> <buildnumber file="${ant.project.name}.buildnumber" /> <property name="build.version" value="${application.version}.${build.number}" /> <manifest file="${build}/MANIFEST.MF"> <attribute name="Created-By" value="${user.name}" /> <attribute name="Product-Name" value="${ant.project.name}" /> <attribute name="Product-Version" value="${application.version}" /> <attribute name="Build-Version" value="${build.version}" /> <attribute name="Build-Date" value="${build.time}" /> <attribute name="Vendor-Name" value="${build.vendor}" /> </manifest> </target> <target name="javaclasspath" description="Configure classpath"> <!-- define classpath --> <path id="classpath.compile"> <fileset dir="${build.lib}"> <include name="**/*.jar" /> </fileset> </path> </target> <path id="cxf.classpath"> <fileset dir="${cxf.home}/lib"> <include name="*.jar" /> </fileset> </path> <target name="prepare"> <mkdir dir="${build}" /> <mkdir dir="${build.src}" /> <mkdir dir="${build.classes}" /> <mkdir dir="${build.dist}" /> </target> <target name="clean"> <delete dir="${build}" includeemptydirs="true" /> </target> <target name="create_proxy" depends="init,prepare"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-autoNameResolution" /> <arg value="-verbose" /> <arg value="-fe" /> <arg value="jaxws21" /> <arg value="-d" /> <arg value="${build.src}" /> <arg value="-b" /> <arg value="simple-binding.xjb" /> <arg value="-wsdlList" /> <arg value="wsdllist.txt" /> <classpath> <path refid="cxf.classpath" /> </classpath> </java> <mkdir dir="${build.src}/com/emc/documentum/fs/utils" /> <copy todir="${build.src}/com/emc/documentum/fs/utils"> <fileset dir="${basedir}"> <include name="*.java" /> </fileset> </copy> <delete dir="${basedir}/src" includeemptydirs="true" /> <copy todir="${basedir}/src"> <fileset dir="${build}/src"> <include name="**/*.java" /> </fileset> </copy> </target> </project>
- Execute the ANT script – Warning: Use the JDK version JavaSE-1.7 – :
Buildfile: C:\Workspaces\HUO\TESTWsClientGenerator\build.xml init: [delete] Deleting directory C:\Workspaces\HUO\TESTWsClientGenerator\build [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build\src prepare: [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build\classes [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build\dist create_proxy: Loading FrontEnd jaxws21 ... Loading DataBinding jaxb ... wsdl2java -autoNameResolution -verbose -fe jaxws21 -d build\src -b simple-binding.xjb -wsdlList wsdllist.txt wsdl2java - Apache CXF 3.0.3 [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build\src\com\emc\documentum\fs\utils [delete] Deleting directory C:\Workspaces\HUO\TESTWsClientGenerator\src [copy] Copying 139 files to C:\Workspaces\HUO\TESTWsClientGenerator\src javaclasspath: javac: [delete] Deleting directory C:\Workspaces\HUO\TESTWsClientGenerator\build\classes [mkdir] Created dir: C:\Workspaces\HUO\TESTWsClientGenerator\build\classes [javac] Compiling 139 source files to C:\Workspaces\HUO\TESTWsClientGenerator\build\classes [javac] warning: [options] bootstrap class path not set in conjunction with -source 1.5 [javac] 1 warning [copy] Copied 1 empty directory to 1 empty directory under C:\Workspaces\HUO\TESTWsClientGenerator\build\classes build: dist: [jar] Building jar: C:\Workspaces\HUO\TESTWsClientGenerator\build\dist\TESTWsClientGenerator.jar BUILD SUCCESSFUL Total time: 12 seconds
- Result : The folder src contains the proxies classes in order to request the DFS web services. A file TESTWsClientGenerator.buildnumber is generated with the build number:
#Build Number for ANT. Do not edit! #Thu Oct 05 11:55:44 CEST 2017 build.number=2
Warning : The BinaryContent and DataHandlerContent classes are double. so, it is possible to remove the package wsgenerator\com\emc\documentum\fs\datamodel\core\content. You could execute again the ANT script.
That’s all!
Huseyin OZVEREN