You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2016/05/26 21:46:04 UTC
[36/50] [abbrv] cxf git commit: Squash commit of ws-transfer
implementation from Erich Duda (dudaerich) This closes #33
Squash commit of ws-transfer implementation from Erich Duda (dudaerich)
This closes #33
Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/517ef67f
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/517ef67f
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/517ef67f
Branch: refs/heads/master-jaxrs-2.1
Commit: 517ef67f1a69d386de44153e5e09d51cb47bf4d7
Parents: e158c96
Author: Daniel Kulp <dk...@apache.org>
Authored: Tue May 24 09:26:41 2016 -0400
Committer: Daniel Kulp <dk...@apache.org>
Committed: Tue May 24 09:26:41 2016 -0400
----------------------------------------------------------------------
rt/ws/pom.xml | 1 +
rt/ws/transfer/pom.xml | 91 +++
.../apache/cxf/ws/transfer/dialect/Dialect.java | 64 ++
.../dialect/fragment/FragmentDialect.java | 622 +++++++++++++++++++
.../fragment/FragmentDialectConstants.java | 51 ++
.../dialect/fragment/faults/FragmentFault.java | 44 ++
.../fragment/faults/InvalidExpression.java | 42 ++
.../fragment/faults/UnsupportedLanguage.java | 41 ++
.../fragment/faults/UnsupportedMode.java | 42 ++
.../language/FragmentDialectLanguage.java | 37 ++
.../language/FragmentDialectLanguageQName.java | 134 ++++
.../FragmentDialectLanguageXPath10.java | 160 +++++
.../transfer/manager/MemoryResourceManager.java | 160 +++++
.../ws/transfer/manager/ResourceManager.java | 59 ++
.../cxf/ws/transfer/resource/Resource.java | 101 +++
.../cxf/ws/transfer/resource/ResourceLocal.java | 191 ++++++
.../ws/transfer/resource/ResourceRemote.java | 49 ++
.../resourcefactory/ResourceFactory.java | 61 ++
.../resourcefactory/ResourceFactoryImpl.java | 153 +++++
.../resolver/ResourceReference.java | 61 ++
.../resolver/ResourceResolver.java | 39 ++
.../resolver/SimpleResourceResolver.java | 69 ++
.../ws/transfer/shared/TransferConstants.java | 60 ++
.../shared/faults/InvalidRepresentation.java | 41 ++
.../ws/transfer/shared/faults/PutDenied.java | 44 ++
.../transfer/shared/faults/UnknownDialect.java | 43 ++
.../transfer/shared/faults/UnknownResource.java | 42 ++
.../transfer/shared/faults/WSTransferFault.java | 45 ++
.../ResourceTransformer.java | 30 +
.../ResourceTypeIdentifier.java | 36 ++
.../ResourceTypeIdentifierResult.java | 56 ++
.../ResourceValidator.java | 31 +
.../ValidAndTransformHelper.java | 63 ++
.../XSDResourceTypeIdentifier.java | 87 +++
.../XSDResourceValidator.java | 88 +++
.../XSLTResourceTransformer.java | 87 +++
.../reference-parameter-parsing.xml | 27 +
.../main/resources/schemas/catalog-fragment.cat | 21 +
.../src/main/resources/schemas/catalog.cat | 23 +
.../src/main/resources/schemas/fragment.xsd | 87 +++
.../src/main/resources/schemas/transfer.xjb | 37 ++
.../src/main/resources/schemas/transfer.xsd | 192 ++++++
.../src/main/resources/schemas/ws-addr.xsd | 141 +++++
.../integration/FragmentGetQNameTest.java | 171 +++++
.../integration/FragmentGetXPath10Test.java | 333 ++++++++++
.../integration/FragmentPutAddTest.java | 238 +++++++
.../integration/FragmentPutInsertAfterTest.java | 194 ++++++
.../FragmentPutInsertBeforeTest.java | 194 ++++++
.../integration/FragmentPutRemoveTest.java | 113 ++++
.../integration/FragmentPutReplaceTest.java | 419 +++++++++++++
.../integration/IntegrationBaseTest.java | 196 ++++++
.../integration/ResourceFactoryTest.java | 135 ++++
.../ws/transfer/integration/ResourceTest.java | 168 +++++
.../unit/MemoryResourceManagerTest.java | 204 ++++++
.../transfer/unit/XSDResourceValidatorTest.java | 60 ++
.../unit/XSLTResourceTransformerTest.java | 60 ++
.../invalidRepresentation.xml | 26 +
.../xml/xsdresourcevalidator/schema.xsd | 35 ++
.../validRepresentation.xml | 27 +
.../xsltresourcetransformer/representation.xml | 26 +
.../xml/xsltresourcetransformer/stylesheet.xsl | 43 ++
systests/pom.xml | 3 +-
systests/ws-transfer/pom.xml | 61 ++
.../systest/ws/transfer/CreateStudentTest.java | 103 +++
.../systest/ws/transfer/CreateTeacherTest.java | 91 +++
.../cxf/systest/ws/transfer/DeleteTest.java | 118 ++++
.../apache/cxf/systest/ws/transfer/GetTest.java | 111 ++++
.../apache/cxf/systest/ws/transfer/PutTest.java | 129 ++++
.../cxf/systest/ws/transfer/TestUtils.java | 174 ++++++
.../cxf/systest/ws/transfer/UIDManager.java | 40 ++
.../transfer/resolver/MyResourceResolver.java | 55 ++
.../validator/StudentPutResourceValidator.java | 47 ++
.../validator/TeacherResourceValidator.java | 51 ++
.../src/test/resources/schema/studentCreate.xsd | 46 ++
.../src/test/resources/schema/studentPut.xsd | 47 ++
.../src/test/resources/schema/teacher.xsd | 47 ++
.../resources/schema/teacherCreateBasic.xsd | 35 ++
.../src/test/resources/xml/createStudent.xml | 31 +
.../test/resources/xml/createStudentPartial.xml | 29 +
.../test/resources/xml/createStudentWrong.xml | 32 +
.../src/test/resources/xml/createTeacher.xml | 31 +
.../test/resources/xml/createTeacherPartial.xml | 25 +
.../test/resources/xml/createTeacherWrong.xml | 32 +
.../src/test/resources/xml/putStudent.xml | 32 +
.../src/test/resources/xml/putTeacher.xml | 32 +
.../src/test/resources/xml/random.xml | 24 +
.../src/test/resources/xslt/studentCreate.xsl | 110 ++++
.../src/test/resources/xslt/studentPut.xsl | 108 ++++
.../test/resources/xslt/teacherCreateBasic.xsl | 45 ++
.../resources/xslt/teacherDefaultValues.xsl | 108 ++++
90 files changed, 7991 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/pom.xml
----------------------------------------------------------------------
diff --git a/rt/ws/pom.xml b/rt/ws/pom.xml
index 0bea25c..70e1c97 100644
--- a/rt/ws/pom.xml
+++ b/rt/ws/pom.xml
@@ -36,5 +36,6 @@
<module>rm</module>
<module>mex</module>
<module>eventing</module>
+ <module>transfer</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/pom.xml
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/pom.xml b/rt/ws/transfer/pom.xml
new file mode 100644
index 0000000..d2c1a09
--- /dev/null
+++ b/rt/ws/transfer/pom.xml
@@ -0,0 +1,91 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>cxf-rt-ws-transfer</artifactId>
+ <packaging>jar</packaging>
+ <name>Apache CXF Runtime WS Transfer</name>
+ <url>http://cxf.apache.org</url>
+
+ <parent>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-parent</artifactId>
+ <version>3.2.0-SNAPSHOT</version>
+ <relativePath>../../../parent/pom.xml</relativePath>
+ </parent>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>cxf-rt-frontend-jaxws</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>cxf-rt-transports-local</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.cxf</groupId>
+ <artifactId>cxf-xjc-plugin</artifactId>
+ <version>${cxf.xjc-utils.version}</version>
+ <executions>
+ <execution>
+ <id>generate-transfer</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>xsdtojava</goal>
+ </goals>
+ <configuration>
+ <sourceRoot>${basedir}/target/generated-sources/xjc</sourceRoot>
+ <xsdOptions>
+ <xsdOption>
+ <xsd>${basedir}/src/main/resources/schemas/transfer.xsd</xsd>
+ <packagename>org.apache.cxf.ws.transfer</packagename>
+ <bindingFile>${basedir}/src/main/resources/schemas/transfer.xjb</bindingFile>
+ <catalog>${basedir}/src/main/resources/schemas/catalog.cat</catalog>
+ </xsdOption>
+ </xsdOptions>
+ </configuration>
+ </execution>
+ <execution>
+ <id>generate-fragment</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>xsdtojava</goal>
+ </goals>
+ <configuration>
+ <sourceRoot>${basedir}/target/generated-sources/xjc</sourceRoot>
+ <xsdOptions>
+ <xsdOption>
+ <xsd>${basedir}/src/main/resources/schemas/fragment.xsd</xsd>
+ <packagename>org.apache.cxf.ws.transfer.dialect.fragment</packagename>
+ <catalog>${basedir}/src/main/resources/schemas/catalog-fragment.cat</catalog>
+ </xsdOption>
+ </xsdOptions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/Dialect.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/Dialect.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/Dialect.java
new file mode 100644
index 0000000..6ea5208
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/Dialect.java
@@ -0,0 +1,64 @@
+/**
+ * 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.cxf.ws.transfer.dialect;
+
+import org.apache.cxf.ws.transfer.Create;
+import org.apache.cxf.ws.transfer.Delete;
+import org.apache.cxf.ws.transfer.Get;
+import org.apache.cxf.ws.transfer.Put;
+import org.apache.cxf.ws.transfer.Representation;
+
+/**
+ * The interface for a Dialect objects.
+ */
+public interface Dialect {
+
+ /**
+ * Method for processing incoming Get message by Dialect extension.
+ * @param body Get body
+ * @param representation XML representation stored in the ResourceManager
+ * @return Representation, which will be returned in response.
+ */
+ Object processGet(Get body, Representation representation);
+
+ /**
+ * Method for processing incoming Put message by Dialect extension.
+ * @param body Put body
+ * @param representation XML representation stored in the ResourceManager
+ * @return Representation, which will be stored in ResourceManager.
+ */
+ Representation processPut(Put body, Representation representation);
+
+ /**
+ * Method for processing incoming Delete message by Dialect extension.
+ * @param body Delete body
+ * @param representation XML representation stored in the ResourceManager
+ * @return Representation, which will be stored in ResourceManager.
+ */
+ boolean processDelete(Delete body, Representation representation);
+
+ /**
+ * Method for processing incoming Create message by Dialect extension.
+ * @param body Create body
+ * @return Representation, which will be stored in ResourceManager.
+ */
+ Representation processCreate(Create body);
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialect.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialect.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialect.java
new file mode 100644
index 0000000..8498ff8
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialect.java
@@ -0,0 +1,622 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import javax.annotation.Resource;
+import javax.xml.bind.JAXBElement;
+import javax.xml.ws.WebServiceContext;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.apache.cxf.binding.soap.SoapFault;
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.ws.transfer.Create;
+import org.apache.cxf.ws.transfer.Delete;
+import org.apache.cxf.ws.transfer.Get;
+import org.apache.cxf.ws.transfer.Put;
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.dialect.Dialect;
+import org.apache.cxf.ws.transfer.dialect.fragment.faults.InvalidExpression;
+import org.apache.cxf.ws.transfer.dialect.fragment.faults.UnsupportedLanguage;
+import org.apache.cxf.ws.transfer.dialect.fragment.faults.UnsupportedMode;
+import org.apache.cxf.ws.transfer.dialect.fragment.language.FragmentDialectLanguage;
+import org.apache.cxf.ws.transfer.dialect.fragment.language.FragmentDialectLanguageQName;
+import org.apache.cxf.ws.transfer.dialect.fragment.language.FragmentDialectLanguageXPath10;
+import org.apache.cxf.ws.transfer.shared.faults.InvalidRepresentation;
+import org.apache.cxf.ws.transfer.shared.faults.UnknownDialect;
+
+/**
+ * Implementation of the WS-Fragment dialect.
+ */
+public class FragmentDialect implements Dialect {
+
+ @Resource
+ WebServiceContext context;
+
+ private final Map<String, FragmentDialectLanguage> languages;
+
+ private Pattern badXPathPattern;
+
+ private Pattern goodXPathPattern;
+
+ public FragmentDialect() {
+ languages = new HashMap<String, FragmentDialectLanguage>();
+ languages.put(FragmentDialectConstants.QNAME_LANGUAGE_IRI, new FragmentDialectLanguageQName());
+ languages.put(FragmentDialectConstants.XPATH10_LANGUAGE_IRI, new FragmentDialectLanguageXPath10());
+ if (badXPathPattern == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("//@?");
+ sb.append(FragmentDialectLanguageQName.getQNamePatternString());
+ sb.append("$");
+ badXPathPattern = Pattern.compile(sb.toString());
+ }
+ if (goodXPathPattern == null) {
+ StringBuilder sb = new StringBuilder();
+ sb.append("/@?");
+ sb.append(FragmentDialectLanguageQName.getQNamePatternString());
+ sb.append("$");
+ goodXPathPattern = Pattern.compile(sb.toString());
+ }
+ }
+
+ @Override
+ public JAXBElement<ValueType> processGet(Get body, Representation representation) {
+ for (Object o : body.getAny()) {
+ if (o instanceof JAXBElement<?> && ((JAXBElement<?>)o).getDeclaredType() == ExpressionType.class) {
+ ExpressionType expression = (ExpressionType) ((JAXBElement<?>)o).getValue();
+ String languageIRI = expression.getLanguage();
+ languageIRI = languageIRI == null ? FragmentDialectConstants.XPATH10_LANGUAGE_IRI : languageIRI;
+ if (languages.containsKey(languageIRI)) {
+ FragmentDialectLanguage language = languages.get(languageIRI);
+ return generateGetResponse(language.getResourceFragment(representation, expression));
+ } else {
+ throw new UnsupportedLanguage();
+ }
+ }
+ }
+ throw new SoapFault("wsf:Expression is not present.", getSoapVersion().getSender());
+ }
+
+ @Override
+ public Representation processPut(Put body, Representation representation) {
+ for (Object o : body.getAny()) {
+ if (o instanceof Fragment) {
+ Fragment fragment = (Fragment) o;
+ ExpressionType expression = fragment.getExpression();
+ ValueType value = fragment.getValue();
+
+ if (expression == null) {
+ throw new SoapFault("wsf:Expression is not present.", getSoapVersion().getSender());
+ }
+ if (value == null) {
+ value = new ValueType();
+ }
+ String languageIRI = expression.getLanguage();
+ languageIRI = languageIRI == null ? FragmentDialectConstants.XPATH10_LANGUAGE_IRI : languageIRI;
+ if (languages.containsKey(languageIRI)) {
+ FragmentDialectLanguage language = languages.get(languageIRI);
+ Object resourceFragment = language.getResourceFragment(representation, expression);
+ String mode = expression.getMode();
+ mode = mode == null ? FragmentDialectConstants.FRAGMENT_MODE_REPLACE : mode;
+ if (resourceFragment == null && FragmentDialectConstants.FRAGMENT_MODE_REPLACE.equals(mode)
+ && FragmentDialectConstants.XPATH10_LANGUAGE_IRI.equals(languageIRI)) {
+ resourceFragment = language.getResourceFragment(representation, getParentXPath(expression));
+ mode = FragmentDialectConstants.FRAGMENT_MODE_ADD;
+ }
+ return modifyRepresentation(resourceFragment, mode, value);
+ } else {
+ throw new UnsupportedLanguage();
+ }
+ }
+ }
+ throw new SoapFault("wsf:Fragment is not present.", getSoapVersion().getSender());
+ }
+
+ @Override
+ public boolean processDelete(Delete body, Representation representation) {
+ throw new UnknownDialect();
+ }
+
+ @Override
+ public Representation processCreate(Create body) {
+ throw new UnknownDialect();
+ }
+
+ /**
+ * Register FragmentDialectLanguage object for IRI.
+ * @param iri
+ * @param language
+ */
+ public void registerLanguage(String iri, FragmentDialectLanguage language) {
+ if (languages.containsKey(iri)) {
+ throw new IllegalArgumentException(String.format("IRI \"%s\" is already registered", iri));
+ }
+ languages.put(iri, language);
+ }
+
+ /**
+ * Unregister FragmentDialectLanguage object for IRI.
+ * @param iri
+ */
+ public void unregisterLanguage(String iri) {
+ if (!languages.containsKey(iri)) {
+ throw new IllegalArgumentException(String.format("IRI \"%s\" is not registered", iri));
+ }
+ languages.remove(iri);
+ }
+
+ /**
+ * Generates Value element, which is returned as response to Get request.
+ * @param value Result of the XPath evaluation.
+ * @return
+ */
+ private JAXBElement<ValueType> generateGetResponse(Object value) {
+ if (value instanceof Node) {
+ return generateGetResponseNode((Node) value);
+ } else if (value instanceof NodeList) {
+ return generateGetResponseNodeList((NodeList) value);
+ } else if (value instanceof String) {
+ return generateGetResponseString((String) value);
+ }
+ ObjectFactory objectFactory = new ObjectFactory();
+ return objectFactory.createValue(new ValueType());
+ }
+
+ /**
+ * Generates Value element from NodeList.
+ * @param nodeList
+ * @return
+ */
+ private JAXBElement<ValueType> generateGetResponseNodeList(NodeList nodeList) {
+ ValueType resultValue = new ValueType();
+ for (int i = 0; i < nodeList.getLength(); i++) {
+ resultValue.getContent().add(nodeList.item(i));
+ }
+ ObjectFactory objectFactory = new ObjectFactory();
+ return objectFactory.createValue(resultValue);
+ }
+
+ /**
+ * Generates Value element from Node.
+ * @param node
+ * @return
+ */
+ private JAXBElement<ValueType> generateGetResponseNode(Node node) {
+ Document doc = DOMUtils.createDocument();
+ ValueType resultValue = new ValueType();
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ Element attrNodeEl = doc.createElementNS(
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI,
+ FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME);
+ attrNodeEl.setAttribute(
+ FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME_ATTR,
+ node.getNodeName()
+ );
+ attrNodeEl.setTextContent(node.getNodeValue());
+ resultValue.getContent().add(attrNodeEl);
+ } else if (node.getNodeType() == Node.TEXT_NODE) {
+ Element textNodeEl = doc.createElementNS(
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI,
+ FragmentDialectConstants.FRAGMENT_TEXT_NODE_NAME);
+ textNodeEl.setNodeValue(node.getNodeValue());
+ resultValue.getContent().add(textNodeEl);
+ } else if (node.getNodeType() == Node.ELEMENT_NODE) {
+ resultValue.getContent().add(node);
+ }
+ ObjectFactory objectFactory = new ObjectFactory();
+ return objectFactory.createValue(resultValue);
+ }
+
+ /**
+ * Generates Value element from String.
+ * @param value
+ * @return
+ */
+ private JAXBElement<ValueType> generateGetResponseString(String value) {
+ ValueType resultValue = new ValueType();
+ resultValue.getContent().add(value);
+ ObjectFactory objectFactory = new ObjectFactory();
+ return objectFactory.createValue(resultValue);
+ }
+
+ /**
+ * Returns expression containing XPath, which refers to parent element.
+ * @param expression
+ * @return
+ */
+ private ExpressionType getParentXPath(ExpressionType expression) {
+ String expr;
+ if (expression.getContent().size() == 1) {
+ expr = (String) expression.getContent().get(0);
+ } else {
+ throw new InvalidExpression();
+ }
+ if (badXPathPattern.matcher(expr).find()) {
+ throw new InvalidExpression();
+ }
+ if (goodXPathPattern.matcher(expr).find()) {
+ expression.getContent().clear();
+ expr = expr.replaceFirst(goodXPathPattern.pattern(), "");
+ if (expr.isEmpty()) {
+ expr = "/";
+ }
+ expression.getContent().add(expr);
+ return expression;
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+
+ /**
+ * Process Put requests.
+ * @param resourceFragment Result of the XPath evaluation. It can be Node or NodeList.
+ * @param mode Mode defined in the Mode attribute.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentation(
+ Object resourceFragment,
+ String mode,
+ ValueType value) {
+ if (resourceFragment instanceof Node) {
+ List<Node> nodeList = new ArrayList<Node>();
+ nodeList.add((Node) resourceFragment);
+ return modifyRepresentationMode(nodeList, mode, value);
+ } else if (resourceFragment instanceof NodeList) {
+ NodeList rfNodeList = (NodeList) resourceFragment;
+ List<Node> nodeList = new ArrayList<Node>();
+ for (int i = 0; i < rfNodeList.getLength(); i++) {
+ nodeList.add(rfNodeList.item(i));
+ }
+ return modifyRepresentationMode(nodeList, mode, value);
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+
+ /**
+ * Process Put requests.
+ * @param mode Mode defined in the Mode attribute.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationMode(
+ List<Node> nodeList,
+ String mode,
+ ValueType value) {
+ switch (mode) {
+ case FragmentDialectConstants.FRAGMENT_MODE_REPLACE:
+ return modifyRepresentationModeReplace(nodeList, value);
+ case FragmentDialectConstants.FRAGMENT_MODE_ADD:
+ return modifyRepresentationModeAdd(nodeList, value);
+ case FragmentDialectConstants.FRAGMENT_MODE_INSERT_BEFORE:
+ return modifyRepresentationModeInsertBefore(nodeList, value);
+ case FragmentDialectConstants.FRAGMENT_MODE_INSERT_AFTER:
+ return modifyRepresentationModeInsertAfter(nodeList, value);
+ case FragmentDialectConstants.FRAGMENT_MODE_REMOVE:
+ return modifyRepresentationModeRemove(nodeList, value);
+ default:
+ throw new UnsupportedMode();
+ }
+ }
+
+ /**
+ * Process Put requests for Replace mode.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationModeReplace(
+ List<Node> nodeList,
+ ValueType value) {
+
+ if (nodeList.isEmpty()) {
+ throw new InvalidExpression();
+ }
+ Node firstNode = nodeList.get(0);
+ Document ownerDocument = firstNode.getOwnerDocument();
+ // if firstNode.getOwnerDocument == null the firstNode is ownerDocument
+ ownerDocument = ownerDocument == null ? (Document) firstNode : ownerDocument;
+ Node nextSibling = null;
+ Node parent = null;
+
+ for (Node node : nodeList) {
+ nextSibling = node.getNextSibling();
+ parent = removeNode(node);
+ }
+
+ addNode(ownerDocument, parent, nextSibling, value);
+
+ Representation representation = new Representation();
+ representation.setAny(ownerDocument.getDocumentElement());
+ return representation;
+ }
+
+ /**
+ * Process Put requests for Add mode.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationModeAdd(
+ List<Node> nodeList,
+ ValueType value) {
+ if (nodeList.isEmpty()) {
+ throw new InvalidExpression();
+ }
+ Node firstNode = nodeList.get(0);
+ Document ownerDocument = firstNode.getOwnerDocument();
+ // if firstNode.getOwnerDocument == null the firstNode is ownerDocument
+ ownerDocument = ownerDocument == null ? (Document) firstNode : ownerDocument;
+
+ for (Node node : nodeList) {
+ addNode(ownerDocument, node, null, value);
+ }
+ Representation representation = new Representation();
+ representation.setAny(ownerDocument.getDocumentElement());
+ return representation;
+ }
+
+ /**
+ * Process Put requests for InsertBefore mode.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationModeInsertBefore(
+ List<Node> nodeList,
+ ValueType value) {
+ if (nodeList.isEmpty()) {
+ throw new InvalidExpression();
+ }
+ Node firstNode = nodeList.get(0);
+ Document ownerDocument = firstNode.getOwnerDocument();
+ // if firstNode.getOwnerDocument == null the firstNode is ownerDocument
+ ownerDocument = ownerDocument == null ? (Document) firstNode : ownerDocument;
+
+ Node parent = firstNode.getParentNode();
+ if (parent == null && firstNode.getNodeType() != Node.DOCUMENT_NODE) {
+ throw new InvalidExpression();
+ }
+ if (parent == null) {
+ parent = firstNode;
+ if (((Document) parent).getDocumentElement() != null) {
+ throw new InvalidExpression();
+ }
+ }
+
+ for (Node node : nodeList) {
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ throw new InvalidRepresentation();
+ }
+ insertBefore(ownerDocument, parent, node, value);
+ }
+
+ Representation representation = new Representation();
+ representation.setAny(ownerDocument.getDocumentElement());
+ return representation;
+ }
+
+ /**
+ * Process Put requests for InsertAfter mode.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationModeInsertAfter(
+ List<Node> nodeList,
+ ValueType value) {
+ if (nodeList.isEmpty()) {
+ throw new InvalidExpression();
+ }
+ Node firstNode = nodeList.get(0);
+ Document ownerDocument = firstNode.getOwnerDocument();
+ // if firstNode.getOwnerDocument == null the firstNode is ownerDocument
+ ownerDocument = ownerDocument == null ? (Document) firstNode : ownerDocument;
+
+ Node parent = firstNode.getParentNode();
+ if (parent == null && firstNode.getNodeType() != Node.DOCUMENT_NODE) {
+ throw new InvalidExpression();
+ }
+ if (parent == null) {
+ parent = firstNode;
+ if (((Document) parent).getDocumentElement() != null) {
+ throw new InvalidExpression();
+ }
+ }
+
+ for (Node node : nodeList) {
+ if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+ throw new InvalidRepresentation();
+ }
+ insertAfter(ownerDocument, parent, node, value);
+ }
+
+ Representation representation = new Representation();
+ representation.setAny(ownerDocument.getDocumentElement());
+ return representation;
+ }
+
+ /**
+ * Process Put requests for Remove mode.
+ * @param value Value defined in the Value element.
+ * @return Representation element, which is returned as response.
+ */
+ private Representation modifyRepresentationModeRemove(
+ List<Node> nodeList,
+ ValueType value) {
+ if (nodeList.isEmpty()) {
+ throw new InvalidExpression();
+ }
+ Node firstNode = nodeList.get(0);
+ Document ownerDocument = firstNode.getOwnerDocument();
+ // if firstNode.getOwnerDocument == null the firstNode is ownerDocument
+ ownerDocument = ownerDocument == null ? (Document) firstNode : ownerDocument;
+
+ for (Node node : nodeList) {
+ removeNode(node);
+ }
+
+ Representation representation = new Representation();
+ representation.setAny(ownerDocument.getDocumentElement());
+ return representation;
+ }
+
+ /**
+ * Helper method. It removes Node and returns its parent.
+ * @param resourceFragment Node to remove.
+ * @return Parent of removed Node.
+ */
+ private Node removeNode(Node resourceFragment) {
+ Node parent = null;
+ if (resourceFragment.getNodeType() == Node.ATTRIBUTE_NODE) {
+ parent = ((Attr)resourceFragment).getOwnerElement();
+ } else {
+ parent = resourceFragment.getParentNode();
+ }
+ if (parent == null) {
+ // resourceFragment is Document Node
+ parent = resourceFragment;
+ }
+ if (resourceFragment.getNodeType() == Node.ATTRIBUTE_NODE) {
+ ((Element)parent).removeAttributeNode((Attr)resourceFragment);
+ } else {
+ if (parent != resourceFragment) {
+ parent.removeChild(resourceFragment);
+ } else {
+ // Both parent and resourceFragment are Document
+ Document doc = (Document) parent;
+ if (doc.getDocumentElement() != null) {
+ doc.removeChild(doc.getDocumentElement());
+ }
+ }
+ }
+
+ return parent;
+ }
+
+ private void insertAfter(Document ownerDocument, Node parent, Node refChild, ValueType value) {
+ for (Object o : value.getContent()) {
+ if (o instanceof Node) {
+ Node node = (Node) o;
+
+ if (
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI.equals(node.getNamespaceURI())
+ && FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME.equals(node.getLocalName())) {
+ throw new InvalidRepresentation();
+ }
+
+ Node importedNode = ownerDocument.importNode(node, true);
+ if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+ parent.appendChild(importedNode);
+ } else {
+ Node nextSibling = refChild.getNextSibling();
+ if (nextSibling == null) {
+ parent.appendChild(importedNode);
+ } else {
+ parent.insertBefore(importedNode, nextSibling);
+ }
+ }
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+ }
+
+ private void insertBefore(Document ownerDocument, Node parent, Node refChild, ValueType value) {
+ for (Object o : value.getContent()) {
+ if (o instanceof Node) {
+ Node node = (Node) o;
+
+ if (
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI.equals(node.getNamespaceURI())
+ && FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME.equals(node.getLocalName())) {
+ throw new InvalidRepresentation();
+ }
+
+ Node importedNode = ownerDocument.importNode(node, true);
+ if (parent.getNodeType() == Node.DOCUMENT_NODE) {
+ parent.appendChild(importedNode);
+ } else {
+ parent.insertBefore(importedNode, refChild);
+ }
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+ }
+
+ /**
+ * Helper method. It adds new Node as the last child of parent.
+ * @param ownerDocument Document, where the Node is added.
+ * @param parent Parent, where the Node is added.
+ * @param value Value defined in the Value element. It represents newly added Node.
+ */
+ private void addNode(Document ownerDocument, Node parent, Node nextSibling, ValueType value) {
+ if (ownerDocument == parent && ownerDocument.getDocumentElement() != null) {
+ throw new InvalidRepresentation();
+ }
+ for (Object o : value.getContent()) {
+ if (o instanceof String) {
+ parent.setTextContent(parent.getTextContent() + ((String) o));
+ } else if (o instanceof Node) {
+ Node node = (Node) o;
+ if (
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI.equals(node.getNamespaceURI())
+ && FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME.equals(node.getLocalName())) {
+ String attrName = ((Element)node).getAttributeNS(
+ FragmentDialectConstants.FRAGMENT_2011_03_IRI,
+ FragmentDialectConstants.FRAGMENT_ATTR_NODE_NAME_ATTR);
+ String attrValue = node.getTextContent();
+ if (attrName == null) {
+ throw new SoapFault("wsf:AttributeNode@name is not present.", getSoapVersion().getSender());
+ }
+ if (((Element) parent).hasAttribute(attrName)) {
+ throw new InvalidRepresentation();
+ }
+ ((Element) parent).setAttribute(attrName, attrValue);
+ } else {
+ // import the node to the ownerDocument
+ Node importedNode = ownerDocument.importNode((Node) o, true);
+ if (nextSibling == null) {
+ parent.appendChild(importedNode);
+ } else {
+ parent.insertBefore(importedNode, nextSibling);
+ }
+ }
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+ }
+
+ private SoapVersion getSoapVersion() {
+ WrappedMessageContext wmc = (WrappedMessageContext) context.getMessageContext();
+ SoapMessage message = (SoapMessage) wmc.getWrappedMessage();
+ return message.getVersion();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialectConstants.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialectConstants.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialectConstants.java
new file mode 100644
index 0000000..6ffd009
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/FragmentDialectConstants.java
@@ -0,0 +1,51 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment;
+
+/**
+ * Helper class for holding of constants.
+ */
+public final class FragmentDialectConstants {
+
+ public static final String FRAGMENT_2011_03_IRI = "http://www.w3.org/2011/03/ws-fra";
+
+ public static final String QNAME_LANGUAGE_IRI = "http://www.w3.org/2011/03/ws-fra/QName";
+
+ public static final String XPATH10_LANGUAGE_IRI = "http://www.w3.org/2011/03/ws-fra/XPath10";
+
+ public static final String FRAGMENT_TEXT_NODE_NAME = "TextNode";
+
+ public static final String FRAGMENT_ATTR_NODE_NAME = "AttributeNode";
+
+ public static final String FRAGMENT_ATTR_NODE_NAME_ATTR = "name";
+
+ public static final String FRAGMENT_MODE_REPLACE = "http://www.w3.org/2011/03/ws-fra/Modes/Replace";
+
+ public static final String FRAGMENT_MODE_ADD = "http://www.w3.org/2011/03/ws-fra/Modes/Add";
+
+ public static final String FRAGMENT_MODE_INSERT_BEFORE = "http://www.w3.org/2011/03/ws-fra/Modes/InsertBefore";
+
+ public static final String FRAGMENT_MODE_INSERT_AFTER = "http://www.w3.org/2011/03/ws-fra/Modes/InsertAfter";
+
+ public static final String FRAGMENT_MODE_REMOVE = "http://www.w3.org/2011/03/ws-fra/Modes/Remove";
+
+ private FragmentDialectConstants() {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/FragmentFault.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/FragmentFault.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/FragmentFault.java
new file mode 100644
index 0000000..3777238
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/FragmentFault.java
@@ -0,0 +1,44 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.faults;
+
+import javax.xml.namespace.QName;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.apache.cxf.binding.soap.SoapFault;
+import org.apache.cxf.helpers.DOMUtils;
+
+/**
+ * The parent for all WS-Fragment-specific faults.
+ */
+public abstract class FragmentFault extends SoapFault {
+
+ private static final long serialVersionUID = 2111286624025926462L;
+
+ public FragmentFault(String reason, String detail, QName faultCode) {
+ super(reason, faultCode);
+ if (detail != null) {
+ Document doc = DOMUtils.createDocument();
+ Element detailEl = doc.createElement("detail");
+ detailEl.setTextContent(detail);
+ setDetail(detailEl);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/InvalidExpression.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/InvalidExpression.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/InvalidExpression.java
new file mode 100644
index 0000000..23da1bc
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/InvalidExpression.java
@@ -0,0 +1,42 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.faults;
+
+import javax.xml.namespace.QName;
+import org.apache.cxf.ws.transfer.dialect.fragment.FragmentDialectConstants;
+
+/**
+ * Definition of the InvalidExpression SOAPFault.
+ */
+public class InvalidExpression extends FragmentFault {
+
+ private static final long serialVersionUID = -1920756304737648952L;
+
+ private static final String SUBCODE = "InvalidExpression";
+
+ private static final String REASON = "The specified Language expression is invalid.";
+
+ private static final String DETAIL = "The invalid language expression.";
+
+ public InvalidExpression() {
+ super(REASON, DETAIL,
+ new QName(FragmentDialectConstants.FRAGMENT_2011_03_IRI, SUBCODE));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedLanguage.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedLanguage.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedLanguage.java
new file mode 100644
index 0000000..bb13b4c
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedLanguage.java
@@ -0,0 +1,41 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.faults;
+
+import javax.xml.namespace.QName;
+import org.apache.cxf.ws.transfer.dialect.fragment.FragmentDialectConstants;
+
+/**
+ * Definition of the UnsupportedLanguage SOAPFault.
+ */
+public class UnsupportedLanguage extends FragmentFault {
+
+ private static final long serialVersionUID = 7627652802987243575L;
+
+ private static final String SUBCODE = "UnsupportedLanguage";
+
+ private static final String REASON = "The specified Language IRI is not supported.";
+
+ private static final String DETAIL = "The unsupported Language IRI.";
+
+ public UnsupportedLanguage() {
+ super(REASON, DETAIL,
+ new QName(FragmentDialectConstants.FRAGMENT_2011_03_IRI, SUBCODE));
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedMode.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedMode.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedMode.java
new file mode 100644
index 0000000..f38b912
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/faults/UnsupportedMode.java
@@ -0,0 +1,42 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.faults;
+
+import javax.xml.namespace.QName;
+import org.apache.cxf.ws.transfer.dialect.fragment.FragmentDialectConstants;
+
+/**
+ * Definition of the UnsupportedMode SOAPFault.
+ */
+public class UnsupportedMode extends FragmentFault {
+
+ private static final long serialVersionUID = -5824904523582078377L;
+
+ private static final String SUBCODE = "UnsupportedMode";
+
+ private static final String REASON = "The specified mode is not supported.";
+
+ private static final String DETAIL = "The unsupported Mode.";
+
+ public UnsupportedMode() {
+ super(REASON, DETAIL,
+ new QName(FragmentDialectConstants.FRAGMENT_2011_03_IRI, SUBCODE));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguage.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguage.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguage.java
new file mode 100644
index 0000000..8ff8018
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguage.java
@@ -0,0 +1,37 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.language;
+
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.dialect.fragment.ExpressionType;
+
+/**
+ * Interface for FragmentDialect languages.
+ */
+public interface FragmentDialectLanguage {
+
+ /**
+ * Returns fragment of resource, which is described by expression.
+ * @param representation Resource, from which is fragment computed.
+ * @param expression Expression written in the language.
+ * @return It can return org.w3c.dom.Node | org.w3c.dom.NodeList | String
+ */
+ Object getResourceFragment(Representation representation, ExpressionType expression);
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageQName.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageQName.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageQName.java
new file mode 100644
index 0000000..a5d78ad
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageQName.java
@@ -0,0 +1,134 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.language;
+
+import java.util.Iterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.xml.namespace.NamespaceContext;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.apache.cxf.helpers.XPathUtils;
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.dialect.fragment.ExpressionType;
+import org.apache.cxf.ws.transfer.dialect.fragment.faults.InvalidExpression;
+
+/**
+ * Implementation of the QName language.
+ */
+public class FragmentDialectLanguageQName implements FragmentDialectLanguage {
+
+ private static Pattern qNamePattern;
+
+ public FragmentDialectLanguageQName() {
+ if (qNamePattern == null) {
+ String qName = getQNamePatternString();
+ qNamePattern = Pattern.compile("^" + qName);
+ }
+ }
+
+ /**
+ * Returns regex string, which describes QName format.
+ * @return
+ */
+ public static String getQNamePatternString() {
+ // See http://www.w3.org/TR/REC-xml-names/#NT-PrefixedName
+ // NCNameStartChar
+ // see http://www.w3.org/TR/REC-xml-names/#NT-NCName
+ // and http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+ String ncNameStartChar = "[A-Z]|_|[a-z]|[\\x{c0}-\\x{d6}]|[\\x{d8}-\\x{f6}]|[\\x{f8}-\\x{2ff}]|"
+ + "[\\x{370}-\\x{37d}]|[\\x{37f}-\\x{1fff}]|[\\x{200c}-\\x{200d}]|"
+ + "[\\x{2070}-\\x{218f}]|[\\x{2c00}-\\x{2fef}]|[\\x{3001}-\\x{d7ff}]|"
+ + "[\\x{f900}-\\x{fdcf}]|[\\x{fdf0}-\\x{fffd}]|[\\x{10000}-\\x{effff}]";
+ // NCNameChar
+ // see http://www.w3.org/TR/REC-xml/#NT-NameChar
+ String ncNameChar = ncNameStartChar
+ + "|-|\\.|[0-9]|\\x{b7}|[\\x{0300}-\\x{036f}]|[\\x{203f}-\\x{2040}]";
+ // NCName
+ // see http://www.w3.org/TR/REC-xml/#NT-Name
+ String ncName = String.format("(%s)(%s)*", ncNameStartChar, ncNameChar);
+ // QName
+ // see http://www.w3.org/TR/REC-xml-names/#NT-QName
+ return String.format("((%s):)?(%s)", ncName, ncName);
+ }
+
+ @Override
+ public Object getResourceFragment(final Representation representation, ExpressionType expression) {
+ String expressionStr = getXPathFromQNameExpression(expression);
+ // Evaluate XPath
+ XPathUtils xu = new XPathUtils(new NamespaceContext() {
+ @Override
+ public String getNamespaceURI(String prefix) {
+ if (prefix != null && !prefix.isEmpty()) {
+ Element resource = (Element) representation.getAny();
+ return resource.getAttribute("xmlns:" + prefix);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getPrefix(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<String> getPrefixes(String s) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ Node resource = (Node) representation.getAny();
+ if (resource == null) {
+ // Returns empty NodeList
+ return new NodeList() {
+ @Override
+ public Node item(int i) {
+ return null;
+ }
+
+ @Override
+ public int getLength() {
+ return 0;
+ }
+ };
+ }
+ return xu.getValueList(expressionStr, resource);
+ }
+
+ /**
+ * Converts expression in QName language to XPath expression.
+ * @param expression Expression in QName language.
+ * @return Expression in XPath language.
+ */
+ private String getXPathFromQNameExpression(ExpressionType expression) {
+ if (expression.getContent().size() == 1) {
+ String expressionValue = (String) expression.getContent().get(0);
+ Matcher m = qNamePattern.matcher(expressionValue);
+ if (m.matches()) {
+ return "/node()/" + expressionValue;
+ } else {
+ throw new InvalidExpression();
+ }
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageXPath10.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageXPath10.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageXPath10.java
new file mode 100644
index 0000000..86bddab
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/dialect/fragment/language/FragmentDialectLanguageXPath10.java
@@ -0,0 +1,160 @@
+/**
+ * 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.cxf.ws.transfer.dialect.fragment.language;
+
+import java.util.Iterator;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathException;
+import javax.xml.xpath.XPathFactory;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.dialect.fragment.ExpressionType;
+import org.apache.cxf.ws.transfer.dialect.fragment.faults.InvalidExpression;
+
+/**
+ * Implementation of the XPath 1.0 language.
+ */
+public class FragmentDialectLanguageXPath10 implements FragmentDialectLanguage {
+
+ private static XPathFactory xpathFactory = XPathFactory.newInstance();
+
+ @Override
+ public Object getResourceFragment(final Representation representation, ExpressionType expression) {
+ String expressionStr = getXPathFromExpression(expression);
+ // Evaluate XPath
+ XPath xPath = xpathFactory.newXPath();
+ xPath.setNamespaceContext(new NamespaceContext() {
+
+ @Override
+ public String getNamespaceURI(String prefix) {
+ if (prefix != null && !prefix.isEmpty()) {
+ Element resource = (Element) representation.getAny();
+ return resource.getAttribute("xmlns:" + prefix);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getPrefix(String string) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<String> getPrefixes(String string) {
+ throw new UnsupportedOperationException();
+ }
+ });
+ try {
+ Object resource = representation.getAny();
+ if (resource == null) {
+ resource = DOMUtils.createDocument();
+ }
+ NodeList result = (NodeList) xPath.evaluate(
+ expressionStr, resource, XPathConstants.NODESET);
+ if (checkResultConstraints(result)) {
+ if (result.getLength() == 0) {
+ return null;
+ } else {
+ return result;
+ }
+ } else {
+ return result.item(0);
+ }
+ } catch (XPathException ex) {
+ // See https://www.java.net/node/681793
+ }
+
+ try {
+ return (String) xPath.evaluate(
+ expressionStr, representation.getAny(), XPathConstants.STRING);
+ } catch (XPathException ex) {
+ throw new InvalidExpression();
+ }
+ }
+
+ /**
+ * Get XPath from the Expression element.
+ * @param expression
+ * @return
+ */
+ private String getXPathFromExpression(ExpressionType expression) {
+ if (expression.getContent().size() == 1) {
+ return (String) expression.getContent().get(0);
+ } else {
+ throw new InvalidExpression();
+ }
+ }
+
+ /**
+ * Check if result from evaluation of XPath expression fullfils constraints
+ * defined in the specification.
+ * See http://www.w3.org/TR/ws-fragment/#IdResSubset
+ * @param result
+ * @return If the result is true, the server should return all sequence of elements,
+ * otherwise it should return only the first element.
+ */
+ private boolean checkResultConstraints(NodeList result) {
+ if (result.getLength() > 0) {
+ Node firstNode = result.item(0);
+ if (firstNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element firstEl = (Element) firstNode;
+ // QName attributes
+ String localName = firstEl.getLocalName();
+ String namespace = firstEl.getNamespaceURI();
+ Node parent = firstEl.getParentNode();
+ for (int i = 1; i < result.getLength(); i++) {
+ Node node = result.item(i);
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ if (!stringEquals(element.getLocalName(), localName)) {
+ return false;
+ }
+ if (!stringEquals(element.getNamespaceURI(), namespace)) {
+ return false;
+ }
+ if (element.getParentNode() != parent) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Helper method for equation two strings, which can be nullable.
+ * @param str1
+ * @param str2
+ * @return
+ */
+ private boolean stringEquals(String str1, String str2) {
+ return str1 == null ? str2 == null : str1.equals(str2);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/MemoryResourceManager.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/MemoryResourceManager.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/MemoryResourceManager.java
new file mode 100644
index 0000000..9609013e
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/MemoryResourceManager.java
@@ -0,0 +1,160 @@
+/**
+ * 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.cxf.ws.transfer.manager;
+
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import javax.annotation.Resource;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.ws.WebServiceContext;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.apache.cxf.binding.soap.SoapFault;
+import org.apache.cxf.binding.soap.SoapMessage;
+import org.apache.cxf.binding.soap.SoapVersion;
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.helpers.DOMUtils;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.cxf.ws.addressing.ReferenceParametersType;
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.shared.faults.UnknownResource;
+
+/**
+ * In memory implementation for ResourceManager interface.
+ */
+public class MemoryResourceManager implements ResourceManager {
+
+ public static final String REF_NAMESPACE = "http://cxf.apache.org/rt/ws/transfer/MemoryResourceManager";
+
+ public static final String REF_LOCAL_NAME = "uuid";
+
+ private static final Logger LOG = LogUtils.getL7dLogger(MemoryResourceManager.class);
+
+ protected Map<String, String> storage;
+
+ @Resource
+ private WebServiceContext context;
+
+ public MemoryResourceManager() {
+ storage = new HashMap<String, String>();
+ }
+
+ @Override
+ public Representation get(ReferenceParametersType ref) {
+ String uuid = getUUID(ref);
+ if (!storage.containsKey(uuid)) {
+ throw new UnknownResource();
+ }
+ String resource = storage.get(uuid);
+ if (resource.isEmpty()) {
+ return new Representation();
+ } else {
+ Document doc = null;
+ try {
+ doc = StaxUtils.read(new StringReader(storage.get(uuid)));
+ } catch (XMLStreamException e) {
+ LOG.severe(e.getLocalizedMessage());
+ throw new SoapFault("Internal Error", getSoapVersion().getReceiver());
+ }
+ Representation representation = new Representation();
+ representation.setAny(doc.getDocumentElement());
+ return representation;
+ }
+ }
+
+ @Override
+ public void delete(ReferenceParametersType ref) {
+ String uuid = getUUID(ref);
+ if (!storage.containsKey(uuid)) {
+ throw new UnknownResource();
+ }
+ storage.remove(uuid);
+ }
+
+ @Override
+ public void put(ReferenceParametersType ref, Representation newRepresentation) {
+ String uuid = getUUID(ref);
+ if (!storage.containsKey(uuid)) {
+ throw new UnknownResource();
+ }
+ Element representationEl = (Element) newRepresentation.getAny();
+ if (representationEl == null) {
+ storage.put(uuid, "");
+ } else {
+ storage.put(uuid, StaxUtils.toString(representationEl));
+ }
+ }
+
+ @Override
+ public ReferenceParametersType create(Representation initRepresentation) {
+ // Store xmlResource
+ String uuid = UUID.randomUUID().toString();
+ Element representationEl = (Element) initRepresentation.getAny();
+ if (representationEl == null) {
+ storage.put(uuid, "");
+ } else {
+ storage.put(uuid, StaxUtils.toString(representationEl));
+ }
+
+ Element uuidEl = DOMUtils.createDocument().createElementNS(REF_NAMESPACE, REF_LOCAL_NAME);
+ uuidEl.setTextContent(uuid);
+
+ // Create referenceParameter
+ ReferenceParametersType refParam = new ReferenceParametersType();
+ refParam.getAny().add(uuidEl);
+ return refParam;
+ }
+
+ private String getUUID(ReferenceParametersType ref) {
+ for (Object object : ref.getAny()) {
+ if (object instanceof JAXBElement) {
+ JAXBElement<?> element = (JAXBElement<?>) object;
+ QName qName = element.getName();
+ if (
+ REF_NAMESPACE.equals(qName.getNamespaceURI())
+ && REF_LOCAL_NAME.equals(qName.getLocalPart())) {
+ return (String) element.getValue();
+ }
+ } else if (object instanceof Element) {
+ Element element = (Element) object;
+ if (
+ REF_NAMESPACE.equals(element.getNamespaceURI())
+ && REF_LOCAL_NAME.equals(element.getLocalName())) {
+ return element.getTextContent();
+ }
+ }
+ }
+ throw new UnknownResource();
+ }
+
+ private SoapVersion getSoapVersion() {
+ WrappedMessageContext wmc = (WrappedMessageContext) context.getMessageContext();
+ SoapMessage message = (SoapMessage) wmc.getWrappedMessage();
+ return message.getVersion();
+ }
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/ResourceManager.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/ResourceManager.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/ResourceManager.java
new file mode 100644
index 0000000..7dbc6ac
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/manager/ResourceManager.java
@@ -0,0 +1,59 @@
+/**
+ * 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.cxf.ws.transfer.manager;
+
+import org.apache.cxf.ws.addressing.ReferenceParametersType;
+import org.apache.cxf.ws.transfer.Representation;
+
+/**
+ * Interface for managing resource representations.
+ */
+public interface ResourceManager {
+
+ /**
+ * Returns Representation object given by reference parameter.
+ * @param ref Reference parameter returned by create method.
+ * @return Representation object containing the XML resource.
+ * @see ResourceManager#create(org.apache.cxf.ws.transfer.Representation)
+ */
+ Representation get(ReferenceParametersType ref);
+
+ /**
+ * Deletes Representation object given by reference parameter.
+ * @param ref Reference parameter returned by create method.
+ * @see ResourceManager#create(org.apache.cxf.ws.transfer.Representation)
+ */
+ void delete(ReferenceParametersType ref);
+
+ /**
+ * Replaces Representation object given by reference parameter with newRepresentation.
+ * @param ref Reference parameter returned by create method.
+ * @param newRepresentation New Representation object, which will replace the old one.
+ * @see ResourceManager#create(org.apache.cxf.ws.transfer.Representation)
+ */
+ void put(ReferenceParametersType ref, Representation newRepresentation);
+
+ /**
+ * Creates new Representation object from initRepresenation.
+ * @param initRepresentation Representation object containing initial XML resource.
+ * @return Reference parameter for newly created Representation object.
+ */
+ ReferenceParametersType create(Representation initRepresentation);
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/Resource.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/Resource.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/Resource.java
new file mode 100644
index 0000000..3280e39
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/Resource.java
@@ -0,0 +1,101 @@
+/**
+ * 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.cxf.ws.transfer.resource;
+
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebResult;
+import javax.jws.WebService;
+import javax.jws.soap.SOAPBinding;
+import javax.xml.ws.Action;
+import javax.xml.ws.soap.Addressing;
+import org.apache.cxf.ws.transfer.Delete;
+import org.apache.cxf.ws.transfer.DeleteResponse;
+import org.apache.cxf.ws.transfer.Get;
+import org.apache.cxf.ws.transfer.GetResponse;
+import org.apache.cxf.ws.transfer.Put;
+import org.apache.cxf.ws.transfer.PutResponse;
+import org.apache.cxf.ws.transfer.shared.TransferConstants;
+
+/**
+ * The interface definition of a Resource web service, according to the specification.
+ */
+@WebService(targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ name = TransferConstants.NAME_RESOURCE)
+@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
+@Addressing(enabled = true, required = true)
+public interface Resource {
+
+ @Action(
+ input = TransferConstants.ACTION_GET,
+ output = TransferConstants.ACTION_GET_RESPONSE)
+ @WebMethod(operationName = TransferConstants.NAME_OPERATION_GET)
+ @WebResult(
+ name = TransferConstants.NAME_MESSAGE_GET_RESPONSE,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ GetResponse get(
+ @WebParam(
+ name = TransferConstants.NAME_MESSAGE_GET,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ Get body
+ );
+
+ @Action(
+ input = TransferConstants.ACTION_DELETE,
+ output = TransferConstants.ACTION_DELETE_RESPONSE
+ )
+ @WebMethod(operationName = TransferConstants.NAME_OPERATION_DELETE)
+ @WebResult(
+ name = TransferConstants.NAME_MESSAGE_DELETE_RESPONSE,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ DeleteResponse delete(
+ @WebParam(
+ name = TransferConstants.NAME_MESSAGE_DELETE,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ Delete body
+ );
+
+ @Action(
+ input = TransferConstants.ACTION_PUT,
+ output = TransferConstants.ACTION_PUT_RESPONSE
+ )
+ @WebMethod(operationName = TransferConstants.NAME_OPERATION_PUT)
+ @WebResult(
+ name = TransferConstants.NAME_MESSAGE_PUT_RESPONSE,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ PutResponse put(
+ @WebParam(
+ name = TransferConstants.NAME_MESSAGE_PUT,
+ targetNamespace = TransferConstants.TRANSFER_2011_03_NAMESPACE,
+ partName = "Body"
+ )
+ Put body
+ );
+}
http://git-wip-us.apache.org/repos/asf/cxf/blob/517ef67f/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/ResourceLocal.java
----------------------------------------------------------------------
diff --git a/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/ResourceLocal.java b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/ResourceLocal.java
new file mode 100644
index 0000000..49333d6
--- /dev/null
+++ b/rt/ws/transfer/src/main/java/org/apache/cxf/ws/transfer/resource/ResourceLocal.java
@@ -0,0 +1,191 @@
+/**
+ * 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.cxf.ws.transfer.resource;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.ws.WebServiceContext;
+import org.apache.cxf.jaxws.context.WrappedMessageContext;
+import org.apache.cxf.ws.addressing.AddressingProperties;
+import org.apache.cxf.ws.addressing.JAXWSAConstants;
+import org.apache.cxf.ws.addressing.ReferenceParametersType;
+import org.apache.cxf.ws.transfer.Delete;
+import org.apache.cxf.ws.transfer.DeleteResponse;
+import org.apache.cxf.ws.transfer.Get;
+import org.apache.cxf.ws.transfer.GetResponse;
+import org.apache.cxf.ws.transfer.Put;
+import org.apache.cxf.ws.transfer.PutResponse;
+import org.apache.cxf.ws.transfer.Representation;
+import org.apache.cxf.ws.transfer.dialect.Dialect;
+import org.apache.cxf.ws.transfer.dialect.fragment.FragmentDialect;
+import org.apache.cxf.ws.transfer.dialect.fragment.FragmentDialectConstants;
+import org.apache.cxf.ws.transfer.manager.ResourceManager;
+import org.apache.cxf.ws.transfer.shared.faults.UnknownDialect;
+import org.apache.cxf.ws.transfer.validationtransformation.ResourceTypeIdentifier;
+import org.apache.cxf.ws.transfer.validationtransformation.ValidAndTransformHelper;
+
+/**
+ * Implementation of the Resource interface for resources, which are created locally.
+ * @see org.apache.cxf.ws.transfer.resourcefactory.resolver.ResourceResolver
+ */
+public class ResourceLocal implements Resource {
+
+ @javax.annotation.Resource
+ protected WebServiceContext context;
+
+ protected ResourceManager manager;
+
+ protected List<ResourceTypeIdentifier> resourceTypeIdentifiers;
+
+ protected Map<String, Dialect> dialects;
+
+ public ResourceLocal() {
+ dialects = new HashMap<String, Dialect>();
+ dialects.put(FragmentDialectConstants.FRAGMENT_2011_03_IRI, new FragmentDialect());
+ }
+
+ public ResourceManager getManager() {
+ return manager;
+ }
+
+ public void setManager(ResourceManager manager) {
+ this.manager = manager;
+ }
+
+ public List<ResourceTypeIdentifier> getResourceTypeIdentifiers() {
+ if (resourceTypeIdentifiers == null) {
+ resourceTypeIdentifiers = new ArrayList<>();
+ }
+ return resourceTypeIdentifiers;
+ }
+
+ public void setResourceTypeIdentifiers(List<ResourceTypeIdentifier> resourceTypeIdentifiers) {
+ this.resourceTypeIdentifiers = resourceTypeIdentifiers;
+ }
+
+ /**
+ * Register Dialect object for URI.
+ * @param iri
+ * @param dialect
+ */
+ public void registerDialect(String iri, Dialect dialect) {
+ if (dialects.containsKey(iri)) {
+ throw new IllegalArgumentException(String.format("IRI \"%s\" is already registered", iri));
+ }
+ dialects.put(iri, dialect);
+ }
+
+ /**
+ * Unregister dialect URI.
+ * @param iri
+ */
+ public void unregisterDialect(String iri) {
+ if (!dialects.containsKey(iri)) {
+ throw new IllegalArgumentException(String.format("IRI \"%s\" is not registered", iri));
+ }
+ dialects.remove(iri);
+ }
+
+ @Override
+ public GetResponse get(Get body) {
+ // Getting reference paramaters
+ AddressingProperties addrProps = (AddressingProperties) ((WrappedMessageContext) context
+ .getMessageContext()).getWrappedMessage()
+ .getContextualProperty(JAXWSAConstants.ADDRESSING_PROPERTIES_INBOUND);
+ ReferenceParametersType refParams = addrProps
+ .getToEndpointReference()
+ .getReferenceParameters();
+ GetResponse response = new GetResponse();
+ // Getting representation from the ResourceManager
+ Representation representation = manager.get(refParams);
+ // Dialect processing
+ if (body.getDialect() != null && !body.getDialect().isEmpty()) {
+ if (dialects.containsKey(body.getDialect())) {
+ Dialect dialect = dialects.get(body.getDialect());
+ // Send fragment of resource instead it's representation.
+ response.getAny().add(dialect.processGet(body, representation));
+ } else {
+ throw new UnknownDialect();
+ }
+ } else {
+ // Send representation obtained from ResourceManager.
+ response.setRepresentation(representation);
+ }
+ return response;
+ }
+
+ @Override
+ public DeleteResponse delete(Delete body) {
+ // Getting reference paramaters
+ AddressingProperties addrProps = (AddressingProperties) ((WrappedMessageContext) context
+ .getMessageContext()).getWrappedMessage()
+ .getContextualProperty(JAXWSAConstants.ADDRESSING_PROPERTIES_INBOUND);
+ ReferenceParametersType refParams = addrProps
+ .getToEndpointReference()
+ .getReferenceParameters();
+ boolean delete = true;
+ // Dialect processing
+ if (body.getDialect() != null && !body.getDialect().isEmpty()) {
+ if (dialects.containsKey(body.getDialect())) {
+ Dialect dialect = dialects.get(body.getDialect());
+ delete = dialect.processDelete(body, manager.get(refParams));
+ } else {
+ throw new UnknownDialect();
+ }
+ }
+ if (delete) {
+ manager.delete(refParams);
+ }
+ return new DeleteResponse();
+ }
+
+ @Override
+ public PutResponse put(Put body) {
+ // Getting reference paramaters
+ AddressingProperties addrProps = (AddressingProperties) ((WrappedMessageContext) context
+ .getMessageContext()).getWrappedMessage()
+ .getContextualProperty(JAXWSAConstants.ADDRESSING_PROPERTIES_INBOUND);
+ ReferenceParametersType refParams = addrProps
+ .getToEndpointReference()
+ .getReferenceParameters();
+ // Getting representation from the ResourceManager
+ Representation storedRepresentation = manager.get(refParams);
+ // Getting representation from the incoming SOAP message. This representation will be stored.
+ Representation putRepresentation = body.getRepresentation();
+ // Dialect processing
+ if (body.getDialect() != null && !body.getDialect().isEmpty()) {
+ if (dialects.containsKey(body.getDialect())) {
+ Dialect dialect = dialects.get(body.getDialect());
+ putRepresentation = dialect.processPut(body, storedRepresentation);
+ } else {
+ throw new UnknownDialect();
+ }
+ }
+ ValidAndTransformHelper.validationAndTransformation(
+ resourceTypeIdentifiers, putRepresentation, storedRepresentation);
+ manager.put(refParams, putRepresentation);
+ PutResponse response = new PutResponse();
+ response.setRepresentation(putRepresentation);
+ return response;
+ }
+
+}