diff --git a/src/main/java/org/hisp/dhis/BaseDhis2.java b/src/main/java/org/hisp/dhis/BaseDhis2.java index 00399914..f756d37b 100644 --- a/src/main/java/org/hisp/dhis/BaseDhis2.java +++ b/src/main/java/org/hisp/dhis/BaseDhis2.java @@ -80,6 +80,7 @@ import org.apache.hc.core5.http.message.BasicHeader; import org.apache.hc.core5.http.message.BasicNameValuePair; import org.apache.hc.core5.net.URIBuilder; +import org.hisp.dhis.api.LogLevel; import org.hisp.dhis.model.completedatasetregistration.CompleteDataSetRegistrationImportOptions; import org.hisp.dhis.model.datavalueset.DataValueSet; import org.hisp.dhis.model.datavalueset.DataValueSetImportOptions; @@ -137,7 +138,7 @@ public class BaseDhis2 { private static final String LOG_LEVEL_WARN = "warn"; /** Override current log level for debugging here. */ - private static final Optional LOG_LEVEL = Optional.empty(); + protected Optional logLevel = Optional.empty(); // Status codes @@ -1469,11 +1470,11 @@ private void log(int statusCode, String format, Object... arguments) { * @param arguments the message arguments. */ private void log(String format, Object... arguments) { - String logLevel = getLogLevel(); + String level = getLogLevel(); - if (LOG_LEVEL_INFO.equalsIgnoreCase(logLevel)) { + if (LOG_LEVEL_INFO.equalsIgnoreCase(level)) { log.info(format, arguments); - } else if (LOG_LEVEL_WARN.equalsIgnoreCase(logLevel)) { + } else if (LOG_LEVEL_WARN.equalsIgnoreCase(level)) { log.warn(format, arguments); } else { log.debug(format, arguments); @@ -1487,8 +1488,8 @@ private void log(String format, Object... arguments) { * @return the log level. */ private String getLogLevel() { - if (LOG_LEVEL.isPresent()) { - return LOG_LEVEL.get(); + if (logLevel.isPresent()) { + return logLevel.get().getValue(); } return System.getProperty(LOG_LEVEL_SYSTEM_PROPERTY); diff --git a/src/main/java/org/hisp/dhis/Dhis2.java b/src/main/java/org/hisp/dhis/Dhis2.java index 6273aea0..927d4095 100644 --- a/src/main/java/org/hisp/dhis/Dhis2.java +++ b/src/main/java/org/hisp/dhis/Dhis2.java @@ -68,6 +68,7 @@ import org.apache.hc.core5.http.io.entity.StringEntity; import org.apache.hc.core5.net.URIBuilder; import org.hisp.dhis.api.ApiFields; +import org.hisp.dhis.api.LogLevel; import org.hisp.dhis.auth.AccessTokenAuthentication; import org.hisp.dhis.auth.BasicAuthentication; import org.hisp.dhis.auth.CookieAuthentication; @@ -238,6 +239,31 @@ public static Dhis2 withCookieAuth(String url, String sessionId) { return new Dhis2(new Dhis2Config(url, new CookieAuthentication(sessionId))); } + // ------------------------------------------------------------------------- + // Log level + // ------------------------------------------------------------------------- + + /** + * Sets the log level for subsequent requests. + * + * @param logLevel the {@link LogLevel}. + * @return the {@link Dhis2} instance. + */ + public Dhis2 setLogLevel(LogLevel logLevel) { + this.logLevel = Optional.of(logLevel); + return this; + } + + /** + * Resets the log level for subsequent requests. + * + * @return the {@link Dhis2} instance. + */ + public Dhis2 setDefaultLogLevel() { + this.logLevel = Optional.empty(); + return this; + } + // ------------------------------------------------------------------------- // Status // ------------------------------------------------------------------------- diff --git a/src/main/java/org/hisp/dhis/api/LogLevel.java b/src/main/java/org/hisp/dhis/api/LogLevel.java new file mode 100644 index 00000000..bd0d707d --- /dev/null +++ b/src/main/java/org/hisp/dhis/api/LogLevel.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.api; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum LogLevel { + INFO("info"), + WARN("warn"), + ERROR("error"); + + private final String value; +} diff --git a/src/main/java/org/hisp/dhis/security/context/Dhis2Context.java b/src/main/java/org/hisp/dhis/security/context/Dhis2Context.java new file mode 100644 index 00000000..7b3936c4 --- /dev/null +++ b/src/main/java/org/hisp/dhis/security/context/Dhis2Context.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.security.context; + +import java.util.Objects; +import lombok.Getter; +import org.hisp.dhis.model.Me; + +/** Represents the security context for a DHIS2 session. */ +@Getter +public class Dhis2Context { + /** The DHIS2 session identifier. */ + private final String sessionId; + + /** The currently authenticated user as {@link Me}. */ + private final Me user; + + /** + * Constructor. + * + * @param sessionId the session identifier. + * @param user the currently authenticated user as {@link Me}. + */ + public Dhis2Context(String sessionId, Me user) { + this.sessionId = sessionId; + this.user = user; + Objects.requireNonNull(sessionId); + } +} diff --git a/src/main/java/org/hisp/dhis/security/context/Dhis2ContextHolder.java b/src/main/java/org/hisp/dhis/security/context/Dhis2ContextHolder.java new file mode 100644 index 00000000..09230b98 --- /dev/null +++ b/src/main/java/org/hisp/dhis/security/context/Dhis2ContextHolder.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2004-2025, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package org.hisp.dhis.security.context; + +import java.util.Objects; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +/** Thread-local holder for {@link Dhis2Context}. */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class Dhis2ContextHolder { + private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); + + /** + * Sets the {@link Dhis2Context} for the current thread. + * + * @param context the {@link Dhis2Context}. + */ + public static void setContext(Dhis2Context context) { + Objects.requireNonNull(context); + Objects.requireNonNull(context.getSessionId()); + CONTEXT_HOLDER.set(context); + } + + /** + * Gets the {@link Dhis2Context} for the current thread. + * + * @return the {@link Dhis2Context}. + */ + public static Dhis2Context getContext() { + return CONTEXT_HOLDER.get(); + } + + /** Clears the {@link Dhis2Context} for the current thread. */ + public static void clearContext() { + CONTEXT_HOLDER.remove(); + } +}