Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions api/src/org/labkey/api/module/DefaultModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,13 @@ public void dispatch(HttpServletRequest request, HttpServletResponse response, A

ViewContext rootContext = new ViewContext(request, response, url);

Container container = rootContext.getContainer();
if (container != null && isAvailableOnlyWhenActive() && !container.getActiveModules().contains(this))
{
ExceptionUtil.handleException(request, response, new NotFoundException("Module " + getName() + " is not active in " + container.getPath()), null, false);
return;
}

try (var ignored =HttpView.initForRequest(rootContext, request, response))
{
response.setContentType("text/html;charset=UTF-8");
Expand All @@ -1125,8 +1132,8 @@ public void dispatch(HttpServletRequest request, HttpServletResponse response, A
}
request.setAttribute(ViewServlet.REQUEST_ACTION_URL, url);

if (controller instanceof HasViewContext)
((HasViewContext)controller).setViewContext(rootContext);
if (controller instanceof HasViewContext hvc)
hvc.setViewContext(rootContext);
controller.handleRequest(request, response);
}
catch (ServletException | IOException x)
Expand Down
9 changes: 9 additions & 0 deletions api/src/org/labkey/api/module/Module.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ default void registerFilters(ServletContext servletCtx) {}

default boolean isUnderResourcesDirectory(java.nio.file.Path path) { return false; }

/**
* If true, the module is considered unreachable in any container where it's not active/enabled. Its controllers
* will not respond to requests, and it will not show in the admin menu's module list.
*
* More modules should return true, but historically we haven't been especially mindful of service-type modules
* (such as query or pipeline) being active in all containers where they're being used.
*/
default boolean isAvailableOnlyWhenActive() { return false; }

enum TabDisplayMode
{
DISPLAY_NEVER,
Expand Down
4 changes: 2 additions & 2 deletions api/src/org/labkey/api/view/HttpView.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public final void render(ModelBean model, HttpServletRequest request, HttpServle
{
if (response.getContentType() != null && !response.getContentType().contains("charset"))
response.setContentType(response.getContentType()+"; charset=UTF-8");
try (var closeable = HttpView.pushView(this, request, response, null))
try (var _ = HttpView.pushView(this, request, response, null))
{
initViewContext(getViewContext(), request, response);
renderInternal(model, request, response);
Expand Down Expand Up @@ -752,7 +752,7 @@ public static PropertyValues getBindPropertyValues()
ModelAndView mv = vse.mv;
if (mv instanceof HasViewContext)
{
ViewContext context = ((HttpView)mv).getViewContext();
ViewContext context = ((HttpView<?>)mv).getViewContext();
if (context._pvsBind != null)
return context._pvsBind;
}
Expand Down
12 changes: 6 additions & 6 deletions api/src/org/labkey/api/view/JspView.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.labkey.api.view;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.action.HasViewContext;
Expand All @@ -37,7 +38,6 @@
import jakarta.servlet.http.HttpSession;
import jakarta.servlet.jsp.HttpJspPage;
import java.util.Map;
import java.util.Set;


public class JspView<ModelClass> extends WebPartView<ModelClass>
Expand Down Expand Up @@ -133,11 +133,11 @@ protected void renderView(ModelClass model, HttpServletRequest request, HttpServ
boolean devMode = AppProps.getInstance().isDevMode() ||
(_viewContext != null && _viewContext.getUser() != null && _viewContext.getContainer() != null &&
_viewContext.getUser().isPlatformDeveloper());
boolean isDebugHtml = devMode && this.getFrame() != FrameType.NOT_HTML && StringUtils.startsWith(response.getContentType(), "text/html");
boolean isDebugHtml = devMode && this.getFrame() != FrameType.NOT_HTML && Strings.CI.startsWith(response.getContentType(), "text/html");
if (isDebugHtml)
response.getWriter().print("<!--" + _page.getClass() + "-->");

try (Timing t = MiniProfiler.step(_page.getClass().getSimpleName()))
try (Timing _ = MiniProfiler.step(_page.getClass().getSimpleName()))
{
_page._jspService(request, response);
}
Expand Down Expand Up @@ -194,10 +194,10 @@ protected void exposeModelAsRequestAttributes(Map model, HttpServletRequest requ
if (model != null)
context.getExtendedProperties().putAll(model);

for (Map.Entry e : (Set<Map.Entry>)context.getExtendedProperties().entrySet())
for (Map.Entry<String, Object> e : context.getExtendedProperties().entrySet())
{
if (e.getKey() instanceof String && e.getValue() != null)
request.setAttribute((String)e.getKey(), e.getValue());
if (e.getKey() != null && e.getValue() != null)
request.setAttribute(e.getKey(), e.getValue());
}
}
}
1 change: 1 addition & 0 deletions api/src/org/labkey/api/view/PopupAdminView.java
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ public static NavTree createNavTree(final ViewContext context)
SortedSet<Module> disabledModules = new TreeSet<>(moduleComparator);
disabledModules.addAll(ModuleLoader.getInstance().getModules());
disabledModules.removeAll(activeModules);
disabledModules.removeIf(Module::isAvailableOnlyWhenActive);

NavTree goToModuleMenu = new NavTree("Go To Module");
Module defaultModule = null;
Expand Down
3 changes: 1 addition & 2 deletions api/src/org/labkey/api/view/ServletView.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,8 @@ public String getPath()
public void renderInternal(Object model, HttpServletRequest request, HttpServletResponse response) throws Exception
{
ViewContext context = getViewContext();
for (Object o : context.entrySet())
for (Map.Entry<String, Object> entry : context.entrySet())
{
Map.Entry entry = (Map.Entry) o;
request.setAttribute(String.valueOf(entry.getKey()), entry.getValue());
}

Expand Down
7 changes: 3 additions & 4 deletions api/src/org/labkey/api/view/ViewContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,16 @@ public ViewContext(HttpServletRequest request, HttpServletResponse response, Act
setRequest(request);
setResponse(response);

for (Object o : _request.getParameterMap().entrySet())
for (Map.Entry<String, String[]> entry : _request.getParameterMap().entrySet())
{
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>) o;
String key = entry.getKey();
String[] value = entry.getValue();

if (value.length == 1)
_map.put(key, value[0]);
else
{
List list = new ArrayList<>(Arrays.asList(value));
List<String> list = new ArrayList<>(Arrays.asList(value));
_map.put(key, list);
}
}
Expand Down Expand Up @@ -193,7 +192,7 @@ public static ViewContext getMockViewContext(User user, Container c, ActionURL u
// ===========================================
// Last vestiges of ViewContext implementing BoundMap/Map below. TODO: Remove these methods

public Map getExtendedProperties()
public Map<String, Object> getExtendedProperties()
{
return _map;
}
Expand Down
6 changes: 6 additions & 0 deletions mothership/src/org/labkey/mothership/MothershipModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ public boolean hasScripts()
return true;
}

@Override
public boolean isAvailableOnlyWhenActive()
{
return true;
}

@Override
public void afterUpdate(ModuleContext moduleContext)
{
Expand Down