• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LearnLib / automatalib / 13138848026

04 Feb 2025 02:53PM UTC coverage: 92.108% (+2.2%) from 89.877%
13138848026

push

github

mtf90
[maven-release-plugin] prepare release automatalib-0.12.0

16609 of 18032 relevant lines covered (92.11%)

1.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.71
/commons/util/src/main/java/net/automatalib/common/util/lib/LibLoader.java
1
/* Copyright (C) 2013-2025 TU Dortmund University
2
 * This file is part of AutomataLib <https://automatalib.net>.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package net.automatalib.common.util.lib;
17

18
import java.io.IOException;
19
import java.io.InputStream;
20
import java.nio.file.Files;
21
import java.nio.file.Path;
22
import java.util.HashSet;
23
import java.util.Set;
24

25
import org.checkerframework.checker.nullness.qual.Nullable;
26
import org.slf4j.Logger;
27
import org.slf4j.LoggerFactory;
28

29
/**
30
 * Utility (singleton) class to manage loading of native libraries.
31
 */
32
public final class LibLoader {
33

34
    private static final Logger LOG = LoggerFactory.getLogger(LibLoader.class);
2✔
35

36
    private static final LibLoader INSTANCE = new LibLoader();
2✔
37
    private final String libPrefix;
38
    private final String libExtension;
39
    private final @Nullable Path tempLibDir;
40
    private final Set<String> loaded = new HashSet<>();
2✔
41

42
    private LibLoader() {
2✔
43
        // Read architecture properties
44
        if (PlatformProperties.OS_NAME.startsWith("windows")) {
2✔
45
            this.libPrefix = "";
×
46
        } else {
47
            this.libPrefix = "lib";
2✔
48
        }
49

50
        if (PlatformProperties.OS_NAME.startsWith("windows")) {
2✔
51
            this.libExtension = "dll";
×
52
        } else if (PlatformProperties.OS_NAME.startsWith("mac")) {
2✔
53
            this.libExtension = "dylib";
×
54
        } else {
55
            // assume OS is some UNIX
56
            this.libExtension = "so";
2✔
57
        }
58

59
        Path tmpDir = null;
2✔
60
        try {
61
            tmpDir = Files.createTempDirectory(getClass().getName());
2✔
62
            tmpDir.toFile().deleteOnExit();
2✔
63
        } catch (IOException ex) {
×
64
            LOG.error("Error setting up classloader for custom library loading.", ex);
×
65
            LOG.error("Loading of shipped libraries will fail");
×
66
        }
2✔
67
        this.tempLibDir = tmpDir;
2✔
68
    }
2✔
69

70
    public static LibLoader getInstance() {
71
        return INSTANCE;
2✔
72
    }
73

74
    /**
75
     * Loads a native library. Uses {@link LoadPolicy#PREFER_SHIPPED} as the default loading policy.
76
     *
77
     * @param clazz
78
     *         The class whose classloader should be used to resolve shipped libraries
79
     * @param name
80
     *         The name of the class.
81
     *
82
     * @throws LoadLibraryException
83
     *         if the library could not be loaded correctly
84
     */
85
    public void loadLibrary(Class<?> clazz, String name) {
86
        loadLibrary(clazz, name, LoadPolicy.PREFER_SHIPPED);
2✔
87
    }
2✔
88

89
    /**
90
     * Loads a native library with the given {@link LoadPolicy load policy}.
91
     *
92
     * @param clazz
93
     *         The class whose classloader should be used to resolve shipped libraries
94
     * @param name
95
     *         The name of the class.
96
     * @param policy
97
     *         The load policy.
98
     *
99
     * @throws LoadLibraryException
100
     *         if the library could not be loaded correctly
101
     */
102
    public void loadLibrary(Class<?> clazz, String name, LoadPolicy policy) {
103
        if (loaded.contains(name)) {
2✔
104
            return;
2✔
105
        }
106

107
        switch (policy) {
2✔
108
            case PREFER_SHIPPED:
109
                try {
110
                    loadShippedLibrary(clazz, name);
2✔
111
                } catch (LoadLibraryException ex) {
2✔
112
                    LOG.info("Couldn't load shipped library", ex);
2✔
113
                    loadSystemLibrary(name);
×
114
                }
2✔
115
                break;
×
116
            case PREFER_SYSTEM:
117
                try {
118
                    loadSystemLibrary(name);
×
119
                } catch (LoadLibraryException ex) {
2✔
120
                    LOG.info("Couldn't load system library", ex);
2✔
121
                    loadShippedLibrary(clazz, name);
2✔
122
                }
×
123
                break;
2✔
124
            case SHIPPED_ONLY:
125
                loadShippedLibrary(clazz, name);
×
126
                break;
×
127
            case SYSTEM_ONLY:
128
                loadSystemLibrary(name);
×
129
                break;
×
130
            default:
131
                throw new IllegalStateException("Unknown policy " + policy);
×
132
        }
133

134
        loaded.add(name);
2✔
135
    }
2✔
136

137
    private void loadShippedLibrary(Class<?> clazz, String name) {
138
        if (tempLibDir == null) {
2✔
139
            throw new LoadLibraryException("Loading of shipped libraries not supported");
×
140
        }
141

142
        String libFileName = libPrefix + name + "." + libExtension;
2✔
143
        Path libPath = tempLibDir.resolve(libFileName);
2✔
144
        String libResourcePath =
2✔
145
                "/lib/" + PlatformProperties.OS_NAME + "/" + PlatformProperties.OS_ARCH + "/" + libFileName;
146
        try (InputStream libStream = clazz.getResourceAsStream(libResourcePath)) {
2✔
147
            if (libStream == null) {
2✔
148
                throw new LoadLibraryException("Could not find shipped library resource '" + libFileName + "'");
2✔
149
            }
150
            Files.copy(libStream, libPath);
2✔
151
        } catch (IOException ex) {
×
152
            throw new LoadLibraryException(
×
153
                    "Could not copy shipped library to local file system at '" + libPath + "': " + ex.getMessage(), ex);
×
154
        }
2✔
155
        libPath.toFile().deleteOnExit();
2✔
156
        try {
157
            System.load(libPath.toString());
2✔
158
        } catch (SecurityException | UnsatisfiedLinkError ex) {
×
159
            throw new LoadLibraryException(ex);
×
160
        }
2✔
161
    }
2✔
162

163
    @SuppressWarnings("PMD.AvoidUsingNativeCode") // we explicitly want to support native code here
164
    private void loadSystemLibrary(String name) {
165
        try {
166
            System.loadLibrary(name);
×
167
        } catch (SecurityException | UnsatisfiedLinkError ex) {
2✔
168
            throw new LoadLibraryException(ex);
2✔
169
        }
×
170
    }
×
171

172
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc