summaryrefslogtreecommitdiffstats
path: root/java/sca/modules/node-impl/src
diff options
context:
space:
mode:
authorrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2009-08-12 23:43:27 +0000
committerrfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68>2009-08-12 23:43:27 +0000
commitc122a7379b57d45d2c994728171d20609842f7c5 (patch)
tree9ea10773724f65216b0ebe8d155db4dabaca08f9 /java/sca/modules/node-impl/src
parentaaa85d1773cf5740e22913a9b5027f0bfebbf1de (diff)
Fix issues around XMLStreamWriter based on the isRepairingNamespaces property of XMLOutputFactory
More refactoring to use common-xml and common-java git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@803742 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/sca/modules/node-impl/src')
-rw-r--r--java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/NodeConfigurationProcessor.java31
-rw-r--r--java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/XMLStreamSerializer.java287
-rw-r--r--java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeFactoryImpl.java19
-rw-r--r--java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeImpl.java3
-rw-r--r--java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeUtil.java48
-rw-r--r--java/sca/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeUtilTestCase.java11
6 files changed, 28 insertions, 371 deletions
diff --git a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/NodeConfigurationProcessor.java b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/NodeConfigurationProcessor.java
index 31f21ee09f..e91c5961fc 100644
--- a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/NodeConfigurationProcessor.java
+++ b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/NodeConfigurationProcessor.java
@@ -25,19 +25,19 @@ import java.io.StringWriter;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
+import org.apache.tuscany.sca.common.xml.stax.StAXHelper;
import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
import org.apache.tuscany.sca.contribution.processor.ContributionResolveException;
import org.apache.tuscany.sca.contribution.processor.ContributionWriteException;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.monitor.Monitor;
import org.apache.tuscany.sca.node.configuration.BindingConfiguration;
@@ -65,25 +65,15 @@ public class NodeConfigurationProcessor extends BaseStAXArtifactProcessor implem
private StAXArtifactProcessor processor;
private NodeConfigurationFactory nodeConfigurationFactory;
- private XMLInputFactory xmlInputFactory;
- private XMLOutputFactory xmlOutputFactory;
+ private StAXHelper helper;
- public NodeConfigurationProcessor(FactoryExtensionPoint modelFactories,
+ public NodeConfigurationProcessor(ExtensionPointRegistry registry,
StAXArtifactProcessor processor,
Monitor monitor) {
+ FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
this.nodeConfigurationFactory = modelFactories.getFactory(NodeConfigurationFactory.class);
this.processor = processor;
- this.xmlInputFactory = modelFactories.getFactory(XMLInputFactory.class);
- this.xmlOutputFactory = modelFactories.getFactory(XMLOutputFactory.class);
- }
-
- public NodeConfigurationProcessor(NodeConfigurationFactory nodeConfigurationFactory,
- XMLInputFactory xmlInputFactory,
- XMLOutputFactory xmlOutputFactory) {
- super();
- this.nodeConfigurationFactory = nodeConfigurationFactory;
- this.xmlInputFactory = xmlInputFactory;
- this.xmlOutputFactory = xmlOutputFactory;
+ this.helper = StAXHelper.getInstance(registry);
}
public QName getArtifactType() {
@@ -153,9 +143,8 @@ public class NodeConfigurationProcessor extends BaseStAXArtifactProcessor implem
}
*/
StringWriter sw = new StringWriter();
- XMLStreamWriter writer = xmlOutputFactory.createXMLStreamWriter(sw);
- new XMLStreamSerializer().serialize(reader, writer);
- writer.flush();
+ XMLStreamWriter writer = helper.createXMLStreamWriter(sw);
+ helper.save(reader, writer);
composite.setContent(sw.toString());
}
break;
@@ -207,9 +196,9 @@ public class NodeConfigurationProcessor extends BaseStAXArtifactProcessor implem
new XAttr("location", dc.getLocation()),
new XAttr("contribution", dc.getContributionURI()));
if (dc.getContent() != null) {
- XMLStreamReader reader = xmlInputFactory.createXMLStreamReader(new StringReader(dc.getContent()));
+ XMLStreamReader reader = helper.createXMLStreamReader(new StringReader(dc.getContent()));
reader.nextTag(); // Move to the first element
- new XMLStreamSerializer().serialize(reader, writer);
+ helper.save(reader, writer);
reader.close();
}
writeEnd(writer);
diff --git a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/XMLStreamSerializer.java b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/XMLStreamSerializer.java
deleted file mode 100644
index 1ddf25953d..0000000000
--- a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/configuration/xml/XMLStreamSerializer.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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.tuscany.sca.node.configuration.xml;
-
-import javax.xml.namespace.NamespaceContext;
-import javax.xml.stream.XMLStreamConstants;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.stream.XMLStreamWriter;
-
-/**
- * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter
- *
- * @version $Rev$ $Date$
- */
-public class XMLStreamSerializer implements XMLStreamConstants {
- public static final String NAMESPACE_PREFIX = "ns";
- private static int namespaceSuffix;
-
- /*
- * The behavior of the Serializer is such that it returns when it encounters the starting element for the second
- * time. The depth variable tracks the depth of the Serializer and tells it when to return. Note that it is assumed
- * that this Serialization starts on an Element.
- */
-
- /**
- * Field depth
- */
- private int depth;
-
- /**
- * Generates a unique namespace prefix that is not in the scope of the NamespaceContext
- *
- * @param nsCtxt
- * @return string
- */
- private String generateUniquePrefix(NamespaceContext nsCtxt) {
- String prefix = NAMESPACE_PREFIX + namespaceSuffix++;
- // null should be returned if the prefix is not bound!
- while (nsCtxt.getNamespaceURI(prefix) != null) {
- prefix = NAMESPACE_PREFIX + namespaceSuffix++;
- }
-
- return prefix;
- }
-
- /**
- * Method serialize.
- *
- * @param node
- * @param writer
- * @throws XMLStreamException
- */
- public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException {
- serializeNode(node, writer);
- }
-
- /**
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- int count = reader.getAttributeCount();
- String prefix;
- String namespaceName;
- String writerPrefix;
- for (int i = 0; i < count; i++) {
- prefix = reader.getAttributePrefix(i);
- namespaceName = reader.getAttributeNamespace(i);
- /*
- * Due to parser implementations returning null as the namespace URI (for the empty namespace) we need to
- * make sure that we deal with a namespace name that is not null. The best way to work around this issue is
- * to set the namespace URI to "" if it is null
- */
- if (namespaceName == null) {
- namespaceName = "";
- }
-
- writerPrefix = writer.getPrefix(namespaceName);
-
- if (!"".equals(namespaceName)) {
- // prefix has already being declared but this particular
- // attrib has a
- // no prefix attached. So use the prefix provided by the
- // writer
- if (writerPrefix != null && (prefix == null || prefix.equals(""))) {
- writer.writeAttribute(writerPrefix, namespaceName, reader.getAttributeLocalName(i), reader
- .getAttributeValue(i));
-
- // writer prefix is available but different from the
- // current
- // prefix of the attrib. We should be declaring the new
- // prefix
- // as a namespace declaration
- } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) {
- writer.writeNamespace(prefix, namespaceName);
- writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
- .getAttributeValue(i));
-
- // prefix is null (or empty), but the namespace name is
- // valid! it has not
- // being written previously also. So we need to generate
- // a prefix
- // here
- } else if (prefix == null || prefix.equals("")) {
- prefix = generateUniquePrefix(writer.getNamespaceContext());
- writer.writeNamespace(prefix, namespaceName);
- writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
- .getAttributeValue(i));
- } else {
- writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader
- .getAttributeValue(i));
- }
- } else {
- // empty namespace is equal to no namespace!
- writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
- }
-
- }
- }
-
- /**
- * Method serializeCData.
- *
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- writer.writeCData(reader.getText());
- }
-
- /**
- * Method serializeComment.
- *
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- writer.writeComment(reader.getText());
- }
-
- /**
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- String prefix = reader.getPrefix();
- String nameSpaceName = reader.getNamespaceURI();
- if (nameSpaceName != null) {
- String writerPrefix = writer.getPrefix(nameSpaceName);
- if (writerPrefix != null) {
- writer.writeStartElement(nameSpaceName, reader.getLocalName());
- } else {
- if (prefix != null) {
- writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName);
- writer.writeNamespace(prefix, nameSpaceName);
- // writer.setPrefix(prefix, nameSpaceName);
- } else {
- // [rfeng] We need to set default NS 1st before calling writeStateElement
- writer.setDefaultNamespace(nameSpaceName);
- writer.writeStartElement(nameSpaceName, reader.getLocalName());
- writer.writeDefaultNamespace(nameSpaceName);
- }
- }
- } else {
- writer.writeStartElement(reader.getLocalName());
- }
-
- // add the namespaces
- int count = reader.getNamespaceCount();
- String namespacePrefix;
- for (int i = 0; i < count; i++) {
- namespacePrefix = reader.getNamespacePrefix(i);
- // [rfeng] The following is commented out to allow to default ns
- // if (namespacePrefix != null && namespacePrefix.length() == 0) {
- // continue;
- // }
-
- serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer);
- }
-
- // add attributes
- serializeAttributes(reader, writer);
-
- }
-
- /**
- * Method serializeEndElement.
- *
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException {
- writer.writeEndElement();
- }
-
- /**
- * Method serializeNamespace.
- *
- * @param prefix
- * @param uri
- * @param writer
- * @throws XMLStreamException
- */
- private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer) throws XMLStreamException {
- String prefix1 = writer.getPrefix(uri);
- if (prefix1 == null) {
- writer.writeNamespace(prefix, uri);
- // writer.setPrefix(prefix, uri);
- }
- }
-
- /**
- * Method serializeNode.
- *
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- while (true) {
- int event = reader.getEventType();
- if (event == START_ELEMENT) {
- serializeElement(reader, writer);
- depth++;
- } else if (event == ATTRIBUTE) {
- serializeAttributes(reader, writer);
- } else if (event == CHARACTERS) {
- serializeText(reader, writer);
- } else if (event == COMMENT) {
- serializeComment(reader, writer);
- } else if (event == CDATA) {
- serializeCData(reader, writer);
- } else if (event == END_ELEMENT) {
- serializeEndElement(writer);
- depth--;
- } else if (event == START_DOCUMENT) {
- depth++; // if a start document is found then increment
- writer.writeStartDocument();
- // the depth
- } else if (event == END_DOCUMENT) {
- if (depth != 0) {
- depth--; // for the end document - reduce the depth
- }
- writer.writeEndDocument();
- }
- if (depth == 0) {
- break;
- }
- if (reader.hasNext()) {
- reader.next();
- } else {
- break;
- }
- }
- }
-
- /**
- * @param reader
- * @param writer
- * @throws XMLStreamException
- */
- protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
- writer.writeCharacters(reader.getText());
- }
-}
diff --git a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeFactoryImpl.java b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeFactoryImpl.java
index 9f2303a93f..8c4ebabe79 100644
--- a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeFactoryImpl.java
+++ b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeFactoryImpl.java
@@ -20,8 +20,8 @@
package org.apache.tuscany.sca.node.impl;
import static java.lang.System.currentTimeMillis;
-import static org.apache.tuscany.sca.node.impl.NodeUtil.createURI;
-import static org.apache.tuscany.sca.node.impl.NodeUtil.openStream;
+import static org.apache.tuscany.sca.common.java.io.IOHelper.createURI;
+import static org.apache.tuscany.sca.common.java.io.IOHelper.openStream;
import java.io.File;
import java.io.IOException;
@@ -48,7 +48,6 @@ import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
@@ -58,6 +57,7 @@ import org.apache.tuscany.sca.assembly.builder.CompositeBuilder;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderExtensionPoint;
import org.apache.tuscany.sca.assembly.builder.CompositeBuilderTmp;
import org.apache.tuscany.sca.assembly.builder.EndpointReferenceBuilder;
+import org.apache.tuscany.sca.common.xml.stax.StAXHelper;
import org.apache.tuscany.sca.contribution.Artifact;
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.contribution.ContributionFactory;
@@ -100,7 +100,6 @@ import org.apache.tuscany.sca.node.configuration.BindingConfiguration;
import org.apache.tuscany.sca.node.configuration.ContributionConfiguration;
import org.apache.tuscany.sca.node.configuration.DeploymentComposite;
import org.apache.tuscany.sca.node.configuration.NodeConfiguration;
-import org.apache.tuscany.sca.node.configuration.xml.NodeConfigurationProcessor;
import org.apache.tuscany.sca.work.WorkScheduler;
import org.oasisopen.sca.ServiceRuntimeException;
@@ -171,12 +170,14 @@ public class NodeFactoryImpl extends NodeFactory {
@Override
public NodeConfiguration loadConfiguration(InputStream xml) {
try {
- XMLInputFactory inputFactory = getFactory(XMLInputFactory.class);
- XMLOutputFactory outputFactory = getFactory(XMLOutputFactory.class);
- XMLStreamReader reader = inputFactory.createXMLStreamReader(xml);
- NodeConfigurationProcessor processor = new NodeConfigurationProcessor(this, inputFactory, outputFactory);
+ init();
+ StAXHelper helper = StAXHelper.getInstance(extensionPoints);
+ XMLStreamReader reader = helper.createXMLStreamReader(xml);
+ StAXArtifactProcessorExtensionPoint processors =
+ extensionPoints.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
+ StAXArtifactProcessor processor = processors.getProcessor(NodeConfiguration.class);
reader.nextTag();
- NodeConfiguration config = processor.read(reader);
+ NodeConfiguration config = (NodeConfiguration)processor.read(reader);
xml.close();
return config;
} catch (Throwable e) {
diff --git a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeImpl.java b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeImpl.java
index ca9706bc22..92bd54a3d8 100644
--- a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeImpl.java
+++ b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeImpl.java
@@ -33,6 +33,7 @@ import org.apache.tuscany.sca.assembly.Composite;
import org.apache.tuscany.sca.assembly.CompositeService;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.assembly.Service;
+import org.apache.tuscany.sca.common.java.io.IOHelper;
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
@@ -116,7 +117,7 @@ public class NodeImpl implements Node, Client {
// Start the composite
compositeActivator.start(compositeActivator.getDomainComposite());
- NodeFinder.addNode(NodeUtil.createURI(configuration.getDomainURI()), this);
+ NodeFinder.addNode(IOHelper.createURI(configuration.getDomainURI()), this);
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
try {
diff --git a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeUtil.java b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeUtil.java
index 3f65d49740..4da41442f5 100644
--- a/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeUtil.java
+++ b/java/sca/modules/node-impl/src/main/java/org/apache/tuscany/sca/node/impl/NodeUtil.java
@@ -19,13 +19,6 @@
package org.apache.tuscany.sca.node.impl;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-
import org.apache.tuscany.sca.contribution.Contribution;
import org.apache.tuscany.sca.contribution.ContributionFactory;
@@ -47,45 +40,4 @@ public class NodeUtil {
return contribution;
}
- /**
- * Open a URL connection without cache
- * @param url
- * @return
- * @throws IOException
- */
- static InputStream openStream(URL url) throws IOException {
- InputStream is = null;
- URLConnection connection = url.openConnection();
- connection.setUseCaches(false);
- is = connection.getInputStream();
- return is;
- }
-
- /**
- * Escape the space in URL string
- * @param uri
- * @return
- */
- static URI createURI(String uri) {
- if (uri == null) {
- return null;
- }
- if (uri.indexOf('%') != -1) {
- // Avoid double-escaping
- return URI.create(uri);
- }
- int index = uri.indexOf(':');
- String scheme = null;
- String ssp = uri;
- if (index != -1) {
- scheme = uri.substring(0, index);
- ssp = uri.substring(index + 1);
- }
- try {
- return new URI(scheme, ssp, null);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
}
diff --git a/java/sca/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeUtilTestCase.java b/java/sca/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeUtilTestCase.java
index 725bce5e09..5a47465702 100644
--- a/java/sca/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeUtilTestCase.java
+++ b/java/sca/modules/node-impl/src/test/java/org/apache/tuscany/sca/node/impl/NodeUtilTestCase.java
@@ -19,6 +19,7 @@
package org.apache.tuscany.sca.node.impl;
+import org.apache.tuscany.sca.common.java.io.IOHelper;
import org.junit.Assert;
import org.junit.Test;
@@ -29,10 +30,10 @@ import org.junit.Test;
public class NodeUtilTestCase {
@Test
public void testCreateURI() {
- Assert.assertEquals("/a/b", NodeUtil.createURI("/a/b").toString());
- Assert.assertEquals("/a%20b", NodeUtil.createURI("/a b").toString());
- Assert.assertEquals("file:/a/b", NodeUtil.createURI("file:/a/b").toString());
- Assert.assertEquals("file:/a%20b", NodeUtil.createURI("file:/a b").toString());
- Assert.assertEquals("file:/a%20b", NodeUtil.createURI("file:/a%20b").toString());
+ Assert.assertEquals("/a/b", IOHelper.createURI("/a/b").toString());
+ Assert.assertEquals("/a%20b", IOHelper.createURI("/a b").toString());
+ Assert.assertEquals("file:/a/b", IOHelper.createURI("file:/a/b").toString());
+ Assert.assertEquals("file:/a%20b", IOHelper.createURI("file:/a b").toString());
+ Assert.assertEquals("file:/a%20b", IOHelper.createURI("file:/a%20b").toString());
}
}