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

oracle / opengrok / #3642

23 Oct 2023 02:33PM UTC coverage: 75.784% (+1.4%) from 74.413%
#3642

push

web-flow
Sonar code smell issue fixes (#4450)

Signed-off-by: Gino Augustine <ginoaugustine@gmail.com>

200 of 200 new or added lines in 39 files covered. (100.0%)

44390 of 58574 relevant lines covered (75.78%)

0.76 hits per line

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

78.08
/opengrok-indexer/src/main/java/org/opengrok/indexer/authorization/AuthorizationPlugin.java
1
/*
2
 * CDDL HEADER START
3
 *
4
 * The contents of this file are subject to the terms of the
5
 * Common Development and Distribution License (the "License").
6
 * You may not use this file except in compliance with the License.
7
 *
8
 * See LICENSE.txt included in this distribution for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing Covered Code, include this CDDL HEADER in each
12
 * file and include the License file at LICENSE.txt.
13
 * If applicable, add the following below this CDDL HEADER, with the
14
 * fields enclosed by brackets "[]" replaced with your own identifying
15
 * information: Portions Copyright [yyyy] [name of copyright owner]
16
 *
17
 * CDDL HEADER END
18
 */
19

20
/*
21
 * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
22
 * Portions Copyright (c) 2018, Chris Fraire <cfraire@me.com>.
23
 */
24
package org.opengrok.indexer.authorization;
25

26
import java.util.Locale;
27
import java.util.Map;
28
import java.util.TreeMap;
29
import java.util.logging.Level;
30
import java.util.logging.Logger;
31
import org.opengrok.indexer.configuration.Group;
32
import org.opengrok.indexer.configuration.Nameable;
33
import org.opengrok.indexer.configuration.Project;
34
import org.opengrok.indexer.logger.LoggerFactory;
35

36
/**
37
 * This is a subclass of {@link AuthorizationEntity} and is a wrapper to a
38
 * {@link IAuthorizationPlugin} delegating the decision methods to the contained
39
 * plugin.
40
 *
41
 * @author Krystof Tulinger
42
 */
43
public class AuthorizationPlugin extends AuthorizationStack {
44

45
    private static final Logger LOGGER = LoggerFactory.getLogger(AuthorizationPlugin.class);
1✔
46
    private static final long serialVersionUID = 2L;
47

48
    private transient IAuthorizationPlugin plugin;
49

50
    public AuthorizationPlugin() {
1✔
51
    }
1✔
52

53
    /**
54
     * Clones the plugin. Performs:
55
     * <ul>
56
     * <li>copy the superclass {@link AuthorizationStack}</li>
57
     * <li>sets the plugin to {@code null}</li>
58
     * </ul>
59
     *
60
     * @param x the plugin to be copied
61
     */
62
    public AuthorizationPlugin(AuthorizationPlugin x) {
63
        super(x);
1✔
64
        plugin = null;
1✔
65
    }
1✔
66

67
    public AuthorizationPlugin(AuthControlFlag flag, IAuthorizationPlugin plugin) {
68
        this(flag, plugin.getClass().getCanonicalName() == null ? plugin.getClass().getName() : plugin.getClass().getCanonicalName(), plugin);
1✔
69
    }
1✔
70

71
    public AuthorizationPlugin(AuthControlFlag flag, String name) {
72
        this(flag, name, null);
1✔
73
    }
1✔
74

75
    public AuthorizationPlugin(AuthControlFlag flag, String name, IAuthorizationPlugin plugin) {
76
        super(flag, name);
1✔
77
        this.plugin = plugin;
1✔
78
    }
1✔
79

80
    /**
81
     * Call the load method on the underlying plugin if the plugin exists. Note
82
     * that the load method can throw any throwable from its body and it should
83
     * not stop the application.
84
     * <p>
85
     * <p>If the method is unable to load the plugin because of any reason (mostly
86
     * the class is not found, not instantiable or the load method throws an
87
     * exception) then any authorization check should fail for this plugin in
88
     * the future.
89
     *
90
     * @param parameters parameters given in the configuration
91
     *
92
     * @see IAuthorizationPlugin#load(java.util.Map)
93
     */
94
    @Override
95
    public synchronized void load(Map<String, Object> parameters) {
96
        // fill properly the "forGroups" and "forProjects" fields
97
        processTargetGroupsAndProjects();
1✔
98

99
        if (!hasPlugin()) {
1✔
100
            LOGGER.log(Level.SEVERE, "Configured plugin \"{0}\" has not been loaded into JVM (missing file?). "
1✔
101
                    + "This can cause the authorization to fail always.",
102
                    getName());
1✔
103
            setFailed();
1✔
104
            LOGGER.log(Level.INFO, "[{0}] Plugin \"{1}\" {2} and is {3}.",
1✔
105
                    new Object[]{
106
                        getFlag().toString().toUpperCase(Locale.ROOT),
1✔
107
                        getName(),
1✔
108
                        hasPlugin() ? "found" : "not found",
1✔
109
                        isWorking() ? "working" : "failed"});
1✔
110
            return;
1✔
111
        }
112

113
        setCurrentSetup(new TreeMap<>());
1✔
114
        getCurrentSetup().putAll(parameters);
1✔
115
        getCurrentSetup().putAll(getSetup());
1✔
116

117
        try {
118
            plugin.load(getCurrentSetup());
1✔
119
            setWorking();
1✔
120
        } catch (Throwable ex) {
1✔
121
            LOGGER.log(Level.SEVERE, ex, () -> "Plugin \"" + getName() + "\" has failed while loading with exception:");
1✔
122
            setFailed();
1✔
123
        }
1✔
124

125
        LOGGER.log(Level.INFO, "[{0}] Plugin \"{1}\" {2} and is {3}.",
1✔
126
                new Object[]{
127
                    getFlag().toString().toUpperCase(Locale.ROOT),
1✔
128
                    getName(),
1✔
129
                    hasPlugin() ? "found" : "not found",
1✔
130
                    isWorking() ? "working" : "failed"});
1✔
131
    }
1✔
132

133
    /**
134
     * Call the unload method on the underlying plugin if the plugin exists.
135
     * Note that the unload method can throw any throwable from its body and it
136
     * should not stop the application.
137
     *
138
     * @see IAuthorizationPlugin#unload()
139
     */
140
    @Override
141
    public synchronized void unload() {
142
        if (hasPlugin()) {
1✔
143
            try {
144
                plugin.unload();
1✔
145
                plugin = null;
1✔
146
            } catch (Throwable ex) {
×
147
                LOGGER.log(Level.SEVERE, ex, () -> "Plugin \"" + getName() + "\" has failed while unloading with exception:");
×
148
            }
1✔
149
        }
150
    }
1✔
151

152
    /**
153
     * Test the underlying plugin with the predicate if and only if the plugin
154
     * is not marked as failed.
155
     *
156
     * @param entity the given entity - this is either group or project and is
157
     * passed just for the logging purposes.
158
     * @param pluginPredicate predicate returning true or false for the given
159
     * entity which determines if the authorization for such entity is
160
     * successful or failed for particular request and plugin
161
     * @param skippingPredicate predicate returning true if this authorization
162
     * entity should be omitted from the authorization process
163
     * @return true if the plugin is not failed and the project is allowed;
164
     * false otherwise
165
     *
166
     * @see #isFailed()
167
     * @see IAuthorizationPlugin#isAllowed(jakarta.servlet.http.HttpServletRequest, Project)
168
     * @see IAuthorizationPlugin#isAllowed(jakarta.servlet.http.HttpServletRequest, Group)
169
     */
170
    @Override
171
    public boolean isAllowed(Nameable entity,
172
            AuthorizationEntity.PluginDecisionPredicate pluginPredicate,
173
            AuthorizationEntity.PluginSkippingPredicate skippingPredicate) {
174
        /**
175
         * We don't check the skippingPredicate here as this instance is
176
         * <b>always</b> a part of some stack (may be the default stack) and the
177
         * stack checks the skipping predicate before invoking this method.
178
         *
179
         * @see AuthorizationStack#processStack
180
         */
181

182
        if (isFailed()) {
1✔
183
            return false;
1✔
184
        }
185

186
        return pluginPredicate.decision(this.plugin);
1✔
187
    }
188

189
    /**
190
     * Set the plugin to this entity if this entity requires this plugin class
191
     * in the configuration. This creates a new instance of the plugin for each
192
     * class which needs it.
193
     *
194
     * @param plugin the new instance of a plugin
195
     * @return true if there is the class names are equal and the plugin is not
196
     * null; false otherwise
197
     */
198
    @Override
199
    public boolean setPlugin(IAuthorizationPlugin plugin) {
200
        if (!getName().equals(plugin.getClass().getCanonicalName())
1✔
201
                || !getName().equals(plugin.getClass().getName())) {
1✔
202
            return false;
1✔
203
        }
204
        if (hasPlugin()) {
1✔
205
            unload();
×
206
        }
207
        try {
208
            /**
209
             * The exception should not happen here as we already have an
210
             * instance of IAuthorizationPlugin. But it is required by the
211
             * compiler.
212
             *
213
             * NOTE: If we were to add a throws clause here we would interrupt
214
             * the whole stack walk through and prevent the other authorization
215
             * entities to work properly.
216
             */
217
            this.plugin = plugin.getClass().getDeclaredConstructor().newInstance();
1✔
218
            return true;
1✔
219
        } catch (InstantiationException ex) {
×
220
            LOGGER.log(Level.INFO, "Class could not be instantiated: ", ex);
×
221
        } catch (IllegalAccessException ex) {
×
222
            LOGGER.log(Level.INFO, "Class loader threw an exception: ", ex);
×
223
        } catch (Throwable ex) {
×
224
            LOGGER.log(Level.INFO, "Class loader threw an unknown error: ", ex);
×
225
        }
×
226
        return false;
×
227
    }
228

229
    /**
230
     * Get the authorization plugin.
231
     *
232
     * @return the underlying plugin
233
     */
234
    protected IAuthorizationPlugin getPlugin() {
235
        return plugin;
1✔
236
    }
237

238
    /**
239
     * Check if the plugin exists and has not failed while loading.
240
     *
241
     * @return true if working, false otherwise
242
     */
243
    @Override
244
    public boolean isWorking() {
245
        return working && hasPlugin();
1✔
246
    }
247

248
    /**
249
     * Check if the plugin class was found for this plugin.
250
     *
251
     * @return true if was; false otherwise
252
     */
253
    public boolean hasPlugin() {
254
        return plugin != null;
1✔
255
    }
256

257
    /**
258
     * Clones the plugin. Performs:
259
     * <ul>
260
     * <li>copy the superclass {@link AuthorizationStack}</li>
261
     * <li>sets the plugin to {@code null}</li>
262
     * </ul>
263
     *
264
     * @return new instance of {@link AuthorizationPlugin}
265
     */
266
    @Override
267
    public AuthorizationPlugin clone() {
268
        return new AuthorizationPlugin(this);
1✔
269
    }
270

271
    /**
272
     * Print the plugin info.
273
     *
274
     * @param prefix this prefix should be prepended to every line produced by
275
     * this stack
276
     * @param colorElement a possible element where any occurrence of %color%
277
     * will be replaced with a HTML HEX color representing this entity state.
278
     * @return the string containing this stack representation
279
     */
280
    @Override
281
    public String hierarchyToString(String prefix, String colorElement) {
282
        return prefix + colorToString(colorElement) +
×
283
                infoToString(prefix) +
×
284
                " (class " + (isWorking() ? "loaded" : "missing/failed") + ")" +
×
285
                "\n" +
286
                setupToString(prefix) +
×
287
                targetsToString(prefix);
×
288
    }
289
}
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

© 2026 Coveralls, Inc