Skip to content

Commit 3fe5e30

Browse files
authored
AVRO-3095: Handle relative imports in resources (apache#1157)
* AVRO-3095: Handle relative imports in resources * AVRO-3095: Clean up code warnings
1 parent 00a4f5c commit 3fe5e30

6 files changed

Lines changed: 76 additions & 27 deletions

File tree

lang/java/avro/src/test/java/org/apache/avro/TestDataFileCorruption.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
public class TestDataFileCorruption {
3737

38-
private static final File DIR = new File("/tmp");
38+
private static final File DIR = new File(System.getProperty("java.io.tmpdir"));
3939

4040
private File makeFile(String name) {
4141
return new File(DIR, "test-" + name + ".avro");

lang/java/compiler/pom.xml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,21 @@
7373
</manifestEntries>
7474
</archive>
7575
</configuration>
76+
<executions>
77+
<execution>
78+
<id>prepare-test-jar</id>
79+
<phase>generate-test-resources</phase>
80+
<goals>
81+
<goal>test-jar</goal>
82+
</goals>
83+
<configuration>
84+
<classifier>test-resource</classifier>
85+
<testClassesDirectory>src/test/idl/putOnClassPath</testClassesDirectory>
86+
<finalName>putOnClassPath</finalName>
87+
<outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
88+
</configuration>
89+
</execution>
90+
</executions>
7691
</plugin>
7792
<!-- Avro generates a parser class with javacc. By default, this looks in src/main/javacc
7893
and outputs to target/generated-sources/javacc See http://mojo.codehaus.org/javacc-maven-plugin/javacc-mojo.html
@@ -114,7 +129,7 @@
114129
</goals>
115130
<configuration>
116131
<executable>java</executable>
117-
<workingDirectory>/tmp</workingDirectory>
132+
<workingDirectory>${java.io.tmpdir}</workingDirectory>
118133
<classpathScope>test</classpathScope>
119134
<arguments>
120135
<argument>-classpath</argument>

lang/java/compiler/src/main/javacc/org/apache/avro/compiler/idl/idl.jj

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ PARSER_BEGIN(Idl)
6161
package org.apache.avro.compiler.idl;
6262

6363
import java.io.*;
64+
import java.net.*;
6465
import java.util.ArrayList;
6566
import java.util.HashMap;
6667
import java.util.LinkedHashMap;
@@ -89,7 +90,7 @@ import org.apache.commons.lang3.StringEscapeUtils;
8990
public class Idl implements Closeable {
9091
static JsonNodeFactory FACTORY = JsonNodeFactory.instance;
9192

92-
File inputDir = new File(".");
93+
URI inputDir;
9394
ClassLoader resourceLoader = null;
9495
String namespace;
9596
Map<String,Schema> names = new LinkedHashMap<String,Schema>();
@@ -104,22 +105,35 @@ public class Idl implements Closeable {
104105

105106
public Idl(File inputFile) throws IOException {
106107
this(new FileInputStream(inputFile), "UTF-8");
107-
this.inputDir = inputFile.getParentFile();
108+
this.inputDir = inputFile.getParentFile().toURI();
108109
}
109110

110111
public Idl(File inputFile, ClassLoader resourceLoader) throws IOException {
111112
this(inputFile);
112113
this.resourceLoader = resourceLoader;
113114
}
114-
115+
116+
private static URI resourceParent(URL jar) throws IOException {
117+
String path = jar.toExternalForm();
118+
String name = path.substring(path.indexOf("!/") + 1);
119+
try {
120+
URI uri = new URI("classpath", null, name, null);
121+
return uri.resolve(".");
122+
} catch (URISyntaxException e) {
123+
throw new IOException("Could not handle resource import in " + jar, e);
124+
}
125+
}
126+
115127
private Idl(URL input, Idl parent) throws IOException {
116128
this(input.openStream(), "UTF-8");
117129
this.inputDir = "file".equals(input.getProtocol())
118-
? new File(input.getPath()).getParentFile()
130+
? new File(input.getPath()).getParentFile().toURI()
131+
: "jar".equals(input.getProtocol())
132+
? resourceParent(input)
119133
: parent.inputDir;
120134
this.resourceLoader = parent.resourceLoader;
121135
}
122-
136+
123137
public void close() throws IOException {
124138
jj_input_stream.inputStream.close();
125139
}
@@ -150,12 +164,15 @@ public class Idl implements Closeable {
150164
throw error(key+" values must be textual: "+n, token);
151165
return values;
152166
}
153-
167+
154168
private URL findFile(String importFile) throws IOException {
155-
File file = new File(this.inputDir, importFile);
169+
URI uri = this.inputDir.resolve(importFile);
170+
File file = "file".equals(uri.getScheme()) ? new File(uri.getPath()) : null;
156171
URL result = null;
157-
if (file.exists())
158-
result = file.toURL();
172+
if (file != null && file.exists())
173+
result = file.toURI().toURL();
174+
else if("classpath".equals(uri.getScheme()))
175+
result = this.resourceLoader.getResource(uri.getPath().substring(1));
159176
else if (this.resourceLoader != null)
160177
result = this.resourceLoader.getResource(importFile);
161178
if (result == null)
@@ -1533,7 +1550,7 @@ Schema ResultType():
15331550
String PropertyName():
15341551
{
15351552
Token t;
1536-
StringBuffer name = new StringBuffer();
1553+
StringBuilder name = new StringBuilder();
15371554
}
15381555
{
15391556
t = <IDENTIFIER> { name.append(t.image); }

lang/java/compiler/src/test/idl/putOnClassPath/OnTheClasspath.avdl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
@namespace("org.on.the.classpath")
2020
protocol OnTheClasspath {
21-
import idl "nestedtypes.avdl";
21+
import idl "folder/relativePath.avdl";
2222
record FromAfar {
2323
}
2424
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* https://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
@namespace("org.on.the.classpath")
20+
protocol OnTheClasspathDependency {
21+
import idl "../nestedtypes.avdl";
22+
}

lang/java/compiler/src/test/java/org/apache/avro/compiler/idl/TestIdl.java

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
package org.apache.avro.compiler.idl;
2020

21-
import static org.junit.Assert.assertEquals;
22-
import static org.junit.Assert.assertTrue;
23-
import static org.junit.Assert.fail;
21+
import com.fasterxml.jackson.databind.JsonNode;
22+
import com.fasterxml.jackson.databind.ObjectMapper;
23+
import org.apache.avro.Protocol;
24+
import org.junit.Before;
25+
import org.junit.Test;
2426

2527
import java.io.BufferedReader;
2628
import java.io.File;
@@ -33,11 +35,9 @@
3335
import java.util.ArrayList;
3436
import java.util.List;
3537

36-
import org.apache.avro.Protocol;
37-
import com.fasterxml.jackson.databind.JsonNode;
38-
import com.fasterxml.jackson.databind.ObjectMapper;
39-
import org.junit.Before;
40-
import org.junit.Test;
38+
import static org.junit.Assert.assertEquals;
39+
import static org.junit.Assert.assertTrue;
40+
import static org.junit.Assert.fail;
4141

4242
/**
4343
* Simple test harness for Idl. This relies on an input/ and output/ directory.
@@ -124,12 +124,7 @@ public GenTest(File in, File expectedOut) {
124124
private String generate() throws Exception {
125125
ClassLoader cl = Thread.currentThread().getContextClassLoader();
126126

127-
// Calculate the absolute path to src/test/resources/putOnClassPath/
128-
File file = new File(".");
129-
String currentWorkPath = file.toURI().toURL().toString();
130-
String newPath = currentWorkPath + "src" + File.separator + "test" + File.separator + "idl" + File.separator
131-
+ "putOnClassPath" + File.separator;
132-
URL[] newPathURL = new URL[] { new URL(newPath) };
127+
URL[] newPathURL = new URL[] { cl.getResource("putOnClassPath-test-resource.jar") };
133128
URLClassLoader ucl = new URLClassLoader(newPathURL, cl);
134129

135130
Idl parser = new Idl(in, ucl);

0 commit comments

Comments
 (0)