Skip to content

Commit 2d0e3a5

Browse files
authored
Add duplicate class check (#693)
1 parent 3414ffd commit 2d0e3a5

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

java-client-serverless/src/main/java/co/elastic/clients/elasticsearch/ElasticsearchClient.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,9 @@
112112
import co.elastic.clients.transport.endpoints.BinaryResponse;
113113
import co.elastic.clients.transport.endpoints.BooleanResponse;
114114
import co.elastic.clients.transport.endpoints.EndpointWithResponseMapperAttr;
115+
import co.elastic.clients.util.DuplicateResourceFinder;
115116
import co.elastic.clients.util.ObjectBuilder;
117+
116118
import java.io.IOException;
117119
import java.lang.reflect.Type;
118120
import java.util.function.Function;
@@ -123,6 +125,12 @@
123125
*/
124126
public class ElasticsearchClient extends ApiClient<ElasticsearchTransport, ElasticsearchClient> {
125127

128+
static {
129+
// Make sure we don't have several versions of this class. This may happen if
130+
// several flavors of the client (Stack and Serverless) are present in the classpath.
131+
DuplicateResourceFinder.ensureClassUniqueness(ElasticsearchClient.class);
132+
}
133+
126134
public ElasticsearchClient(ElasticsearchTransport transport) {
127135
super(transport, null);
128136
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package co.elastic.clients.util;
21+
22+
import java.io.IOException;
23+
import java.net.URL;
24+
import java.util.ArrayList;
25+
import java.util.Enumeration;
26+
import java.util.List;
27+
28+
public class DuplicateResourceFinder {
29+
30+
private static volatile boolean ENABLED = true;
31+
32+
/**
33+
* Disables the resource uniqueness checks. Use with caution, as it will mask problems that may hit later.
34+
*/
35+
public static void enableCheck(boolean enabled) {
36+
ENABLED = enabled;
37+
}
38+
39+
/**
40+
* Ensure a class is only defined once in this class' classpath
41+
*/
42+
public static void ensureClassUniqueness(Class<?> clazz) {
43+
String name = clazz.getName();
44+
String resource = clazz.getName().replace('.', '/') + ".class";
45+
ensureResourceUniqueness(resource, name, DuplicateResourceFinder.class.getClassLoader());
46+
}
47+
48+
public static void ensureResourceUniqueness(String path) {
49+
ensureResourceUniqueness(path, path, DuplicateResourceFinder.class.getClassLoader());
50+
}
51+
52+
private static void ensureResourceUniqueness(String path, String name, ClassLoader classLoader) {
53+
if (!ENABLED) {
54+
return;
55+
}
56+
57+
// With Java9 modules, will work only with exported classes/resources. This is actually
58+
// what we want, as non-exported classes/resources will not conflict.
59+
List<URL> list = new ArrayList<>();
60+
try {
61+
Enumeration<URL> resources = classLoader.getResources(path);
62+
while (resources.hasMoreElements()) {
63+
list.add(resources.nextElement());
64+
}
65+
} catch (IOException ioe) {
66+
// Ignore
67+
}
68+
69+
if (list.size() > 1) {
70+
StringBuilder sb = new StringBuilder("Several versions of ")
71+
.append(name)
72+
.append(" were found. This can cause conflicts, please fix the classpath:\n");
73+
for (URL url: list) {
74+
sb.append(" ").append(url.toString()).append("\n");
75+
}
76+
sb.append(" See the Java API client's troubleshooting documentation for more information.\n");
77+
throw new RuntimeException(sb.toString());
78+
}
79+
}
80+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package co.elastic.clients.util;
21+
22+
import com.fasterxml.jackson.databind.ext.CoreXMLSerializers;
23+
import org.junit.jupiter.api.Assertions;
24+
import org.junit.jupiter.api.Test;
25+
26+
class DuplicateResourceFinderTest extends Assertions {
27+
28+
@Test
29+
public void testDuplicateCheck() {
30+
31+
Exception e = assertThrows(RuntimeException.class, () -> {
32+
DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class);
33+
});
34+
assertTrue(e.getMessage().contains("Several versions of"));
35+
36+
// Disabling the test should not throw an exception
37+
DuplicateResourceFinder.enableCheck(false);
38+
DuplicateResourceFinder.ensureClassUniqueness(CoreXMLSerializers.class);
39+
}
40+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package com.fasterxml.jackson.databind.ext;
21+
22+
// A "duplicate" of a class that exists in the project's dependencies.
23+
// It's not actually used by the project, so the duplicate won't harm and is used in DuplicateResourceFinderTest
24+
public class CoreXMLSerializers {
25+
}

0 commit comments

Comments
 (0)