DefaultJLibnotifyLoader.java

1
/*
2
 * Copyright 2019 Hector Espert <hectorespertpardo@gmail.com>.
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 es.blackleg.jlibnotify.core;
17
18
import com.sun.jna.DefaultTypeMapper;
19
import com.sun.jna.Library;
20
import com.sun.jna.Native;
21
import com.sun.jna.platform.EnumConverter;
22
import es.blackleg.jlibnotify.exception.JLibnotifyLoadException;
23
import es.blackleg.jlibnotify.jna.GBoolean;
24
import java.util.HashMap;
25
import java.util.Map;
26
import es.blackleg.jlibnotify.JLibnotifyLoader;
27
import es.blackleg.jlibnotify.JLibnotify;
28
import es.blackleg.jlibnotify.jna.NativeLibnotify;
29
30
/**
31
 * Reference implementation of {@link JLibnotifyLoader}, and the entry point of the library.
32
 *
33
 * <p>{@link #init()} builds a loader for the default library name, so a complete start looks
34
 * like:</p>
35
 *
36
 * <pre>{@code
37
 * JLibnotify jLibnotify = DefaultJLibnotifyLoader.init().load();
38
 * jLibnotify.init("My Application");
39
 * }</pre>
40
 *
41
 * <p>This is the only class of {@link es.blackleg.jlibnotify.core} application code is expected to
42
 * name; everything else is reached through the interfaces of {@link es.blackleg.jlibnotify}.</p>
43
 *
44
 * @author Hector Espert
45
 */
46
public class DefaultJLibnotifyLoader implements JLibnotifyLoader {
47
48
    /**
49
     * Name of the shared library loaded when none is given: version 4 of libnotify.
50
     */
51
    private static final String DEFAULT_LIBRARY_NAME = "libnotify.so.4";
52
53
    private final String libraryName;
54
55
    private final ServerCapabilitiesReader serverCapabilitiesReader;
56
57
    /**
58
     * Creates a loader for the default library name, {@code libnotify.so.4}.
59
     */
60
    public DefaultJLibnotifyLoader() {
61
        this(DEFAULT_LIBRARY_NAME);
62
    }
63
64
    /**
65
     * Creates a loader for a given library name.
66
     *
67
     * <p>Useful to load another version of libnotify, or a copy of it installed outside the
68
     * standard library path.</p>
69
     *
70
     * @param libraryName name of the shared library, as understood by
71
     *                    {@link com.sun.jna.Native#load(String, Class, Map)}
72
     */
73
    public DefaultJLibnotifyLoader(String libraryName) {
74
        this(libraryName, new DefaultServerCapabilitiesReader());
75
    }
76
77
    /**
78
     * Creates a loader for a given library name and capabilities reader.
79
     *
80
     * @param libraryName              name of the shared library, as understood by
81
     *                                 {@link com.sun.jna.Native#load(String, Class, Map)}
82
     * @param serverCapabilitiesReader reader the loaded library will use to walk the capabilities
83
     *                                 returned by the notification server
84
     */
85
    public DefaultJLibnotifyLoader(String libraryName, ServerCapabilitiesReader serverCapabilitiesReader) {
86
        this.libraryName = libraryName;
87
        this.serverCapabilitiesReader = serverCapabilitiesReader;
88
    }
89
90
    /**
91
     * Loads the native library and binds it to a {@link DefaultJLibnotify}.
92
     *
93
     * <p>Registers a type mapper converting the C {@code gboolean} results into {@link GBoolean}
94
     * before handing the interface to JNA. Native loading fails with an {@link Error} rather than
95
     * an exception, so every {@link Throwable} is caught and reported as a checked
96
     * {@link JLibnotifyLoadException}.</p>
97
     *
98
     * @return a binding of the loaded library, not yet initialised
99
     * @throws JLibnotifyLoadException if the library is missing or cannot be loaded, which is the
100
     *                                 case on any platform other than Linux
101
     */
102
    @Override
103
    public JLibnotify load() throws JLibnotifyLoadException {
104
        try {
105
            EnumConverter enumConverter = new EnumConverter(GBoolean.class);
106
            DefaultTypeMapper defaultTypeMapper = new DefaultTypeMapper();
107 1 1. load : removed call to com/sun/jna/DefaultTypeMapper::addTypeConverter → NO_COVERAGE
            defaultTypeMapper.addTypeConverter(GBoolean.class, enumConverter);
108
            Map<String, Object> options = new HashMap<>();
109
            options.put(Library.OPTION_TYPE_MAPPER, defaultTypeMapper);
110
            NativeLibnotify nativeLibNotify = Native.load(this.libraryName, NativeLibnotify.class, options);
111 1 1. load : replaced return value with null for es/blackleg/jlibnotify/core/DefaultJLibnotifyLoader::load → NO_COVERAGE
            return new DefaultJLibnotify(nativeLibNotify, this.serverCapabilitiesReader);
112
        } catch (Throwable throwable) {
113
            throw new JLibnotifyLoadException(String.format("Unable to load %s library", this.libraryName), throwable);
114
        }
115
    }
116
117
    /**
118
     * Creates a loader for the default library name, {@code libnotify.so.4}.
119
     *
120
     * <p>Starting point of the library, meant to be chained with {@link #load()}.</p>
121
     *
122
     * @return a loader ready to load the default libnotify library
123
     */
124
    public static JLibnotifyLoader init() {
125 1 1. init : replaced return value with null for es/blackleg/jlibnotify/core/DefaultJLibnotifyLoader::init → NO_COVERAGE
        return new DefaultJLibnotifyLoader();
126
    }
127
128
}

Mutations

107

1.1
Location : load
Killed by : none
removed call to com/sun/jna/DefaultTypeMapper::addTypeConverter → NO_COVERAGE

111

1.1
Location : load
Killed by : none
replaced return value with null for es/blackleg/jlibnotify/core/DefaultJLibnotifyLoader::load → NO_COVERAGE

125

1.1
Location : init
Killed by : none
replaced return value with null for es/blackleg/jlibnotify/core/DefaultJLibnotifyLoader::init → NO_COVERAGE

Active mutators

Tests examined


Report generated by PIT 1.30.0 support