You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2011/10/27 15:08:49 UTC
svn commit: r1189737 - in /camel/trunk/camel-core/src:
main/java/org/apache/camel/builder/xml/XPathBuilder.java
test/java/org/apache/camel/language/XPathFromFileExceptionTest.java
Author: davsclaus
Date: Thu Oct 27 13:08:49 2011
New Revision: 1189737
URL: http://svn.apache.org/viewvc?rev=1189737&view=rev
Log:
CAMEL-4591: Fixed issue with locking File on Windows if XPath evaluation failed from a file source
Added:
camel/trunk/camel-core/src/test/java/org/apache/camel/language/XPathFromFileExceptionTest.java
Modified:
camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java?rev=1189737&r1=1189736&r2=1189737&view=diff
==============================================================================
--- camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java (original)
+++ camel/trunk/camel-core/src/main/java/org/apache/camel/builder/xml/XPathBuilder.java Thu Oct 27 13:08:49 2011
@@ -16,6 +16,7 @@
*/
package org.apache.camel.builder.xml;
+import java.io.File;
import java.io.InputStream;
import java.io.StringReader;
import java.util.List;
@@ -54,6 +55,7 @@ import org.apache.camel.spi.Language;
import org.apache.camel.spi.NamespaceAware;
import org.apache.camel.support.SynchronizationAdapter;
import org.apache.camel.util.ExchangeHelper;
+import org.apache.camel.util.IOHelper;
import org.apache.camel.util.MessageHelper;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
@@ -651,8 +653,18 @@ public class XPathBuilder implements Exp
// set exchange and variable resolver as thread locals for concurrency
this.exchange.set(exchange);
+ // the underlying input stream, which we need to close to avoid locking files or other resources
+ InputStream is = null;
try {
- Object document = getDocument(exchange);
+ Object document;
+ // only convert to input stream if really needed
+ if (isInputStreamNeeded(exchange)) {
+ is = exchange.getIn().getBody(InputStream.class);
+ document = getDocument(exchange, is);
+ } else {
+ Object body = exchange.getIn().getBody();
+ document = getDocument(exchange, body);
+ }
if (resultQName != null) {
if (document instanceof InputSource) {
InputSource inputSource = (InputSource) document;
@@ -676,6 +688,9 @@ public class XPathBuilder implements Exp
}
} catch (XPathExpressionException e) {
throw new InvalidXPathExpression(getText(), e);
+ } finally {
+ // IOHelper can handle if is is null
+ IOHelper.close(is);
}
if (LOG.isTraceEnabled()) {
@@ -761,21 +776,47 @@ public class XPathBuilder implements Exp
}
/**
+ * Checks whether we need an {@link InputStream} to access the message body.
+ * <p/>
+ * Depending on the content in the message body, we may not need to convert
+ * to {@link InputStream}.
+ *
+ * @param exchange the current exchange
+ * @return <tt>true</tt> to convert to {@link InputStream} beforehand converting afterwards.
+ */
+ protected boolean isInputStreamNeeded(Exchange exchange) {
+ Object body = exchange.getIn().getBody();
+ if (body == null) {
+ return false;
+ }
+
+ if (body instanceof WrappedFile) {
+ body = ((WrappedFile) body).getFile();
+ }
+ if (body instanceof File) {
+ // input stream is needed for File to avoid locking the file in case of errors etc
+ return true;
+ }
+
+ // input stream is not needed otherwise
+ return false;
+ }
+
+ /**
* Strategy method to extract the document from the exchange.
*/
@SuppressWarnings("unchecked")
- protected Object getDocument(Exchange exchange) {
+ protected Object getDocument(Exchange exchange, Object body) {
Object answer = null;
- Message in = exchange.getIn();
Class type = getDocumentType();
if (type != null) {
// try to get the body as the desired type
- answer = in.getBody(type);
+ answer = exchange.getContext().getTypeConverter().convertTo(type, exchange, body);
}
// fallback to get the body as is
if (answer == null) {
- answer = in.getBody();
+ answer = body;
}
// lets try coerce some common types into something JAXP can deal with
Added: camel/trunk/camel-core/src/test/java/org/apache/camel/language/XPathFromFileExceptionTest.java
URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/language/XPathFromFileExceptionTest.java?rev=1189737&view=auto
==============================================================================
--- camel/trunk/camel-core/src/test/java/org/apache/camel/language/XPathFromFileExceptionTest.java (added)
+++ camel/trunk/camel-core/src/test/java/org/apache/camel/language/XPathFromFileExceptionTest.java Thu Oct 27 13:08:49 2011
@@ -0,0 +1,86 @@
+/**
+ * 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.camel.language;
+
+import java.io.File;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ *
+ */
+public class XPathFromFileExceptionTest extends ContextTestSupport {
+
+ @Override
+ protected void setUp() throws Exception {
+ deleteDirectory("target/xpath");
+ super.setUp();
+ }
+
+ public void testXPathFromFileExceptionOk() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+ getMockEndpoint("mock:error").expectedMessageCount(0);
+
+ template.sendBodyAndHeader("file:target/xpath", "<hello>world!</hello>", Exchange.FILE_NAME, "hello.xml");
+
+ assertMockEndpointsSatisfied();
+
+ oneExchangeDone.matchesMockWaitTime();
+
+ File file = new File("target/xpath/hello.xml");
+ assertFalse("File should not exists " + file, file.exists());
+
+ file = new File("target/xpath/ok/hello.xml");
+ assertTrue("File should exists " + file, file.exists());
+ }
+
+ public void testXPathFromFileExceptionFail() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(0);
+ getMockEndpoint("mock:error").expectedMessageCount(1);
+
+ // the last tag is not ended properly
+ template.sendBodyAndHeader("file:target/xpath", "<hello>world!</hello", Exchange.FILE_NAME, "hello2.xml");
+
+ assertMockEndpointsSatisfied();
+
+ oneExchangeDone.matchesMockWaitTime();
+
+ File file = new File("target/xpath/hello2.xml");
+ assertFalse("File should not exists " + file, file.exists());
+
+ file = new File("target/xpath/error/hello2.xml");
+ assertTrue("File should exists " + file, file.exists());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("file:target/xpath?moveFailed=error&move=ok")
+ .onException(Exception.class)
+ .to("mock:error")
+ .end()
+ .choice()
+ .when().xpath("/hello").to("mock:result")
+ .end();
+ }
+ };
+ }
+}
\ No newline at end of file