diff --git a/api/src/org/labkey/api/script/ScriptService.java b/api/src/org/labkey/api/script/ScriptService.java index dbb45505770..9d27d3e97c8 100644 --- a/api/src/org/labkey/api/script/ScriptService.java +++ b/api/src/org/labkey/api/script/ScriptService.java @@ -36,7 +36,7 @@ static void setInstance(ScriptService impl) ServiceRegistry.get().registerService(ScriptService.class, impl); } - // marker class for server script logging (see log4j.xml) + // marker class for server script logging (see log4j2.xml) class Console {} /** diff --git a/api/src/org/labkey/api/util/LabKeyDeleteAction.java b/api/src/org/labkey/api/util/LabKeyDeleteAction.java deleted file mode 100644 index 01097bd3278..00000000000 --- a/api/src/org/labkey/api/util/LabKeyDeleteAction.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to you under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.labkey.api.util; - -import org.apache.logging.log4j.core.Core; -import org.apache.logging.log4j.core.appender.rolling.action.AbstractPathAction; -import org.apache.logging.log4j.core.appender.rolling.action.DeletingVisitor; -import org.apache.logging.log4j.core.appender.rolling.action.PathCondition; -import org.apache.logging.log4j.core.appender.rolling.action.PathSortByModificationTime; -import org.apache.logging.log4j.core.appender.rolling.action.PathSorter; -import org.apache.logging.log4j.core.appender.rolling.action.PathWithAttributes; -import org.apache.logging.log4j.core.appender.rolling.action.SortingVisitor; -import org.apache.logging.log4j.core.config.Configuration; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginConfiguration; -import org.apache.logging.log4j.core.config.plugins.PluginElement; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; -import org.apache.logging.log4j.core.lookup.StrSubstitutor; - -import java.io.IOException; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * A modified version of log4j2 DeleteAction that doesn't require any conditions; files to delete are determined - * by Java code. - * - * We will retain up to three error log files of 100 MB (as configured in log4j2.xml). We'll keep the first log from a given - * webapp startup, moving it to labkey-errors-yyyy-MM-dd.log for archive purposes. - * - * Keep in sync with org.labkey.embedded.LabKeyDeleteAction until we're embedded-only and can consolidate. - * - * See issue 43686. - */ -@Plugin(name = "LabKeyDelete", category = Core.CATEGORY_NAME, printObject = true) -public class LabKeyDeleteAction extends AbstractPathAction -{ - public static final int MAX_RETAINED = 3; - /** - * Don't retain more than one file per session - */ - private static boolean _copiedOriginal = false; - - /** - * Remember when we started up so we can compare file timestamps against it - */ - private static final Date _startup = new Date(); - - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); - - private final PathSorter pathSorter; - private final boolean testMode; - - /** - * Creates a new DeleteAction that starts scanning for files to delete from the specified base path. - * - * @param basePath base path from where to start scanning for files to delete. - * @param followSymbolicLinks whether to follow symbolic links. Default is false. - * @param maxDepth The maxDepth parameter is the maximum number of levels of directories to visit. A value of 0 - * means that only the starting file is visited, unless denied by the security manager. A value of - * MAX_VALUE may be used to indicate that all levels should be visited. - * @param testMode if true, files are not deleted but instead a message is printed to the status logger - * at INFO level. Users can use this to do a dry run to test if their configuration works as expected. - * @param sorter sorts - * @param pathConditions an array of path filters (if more than one, they all need to accept a path before it is - * deleted). - */ - LabKeyDeleteAction( - final String basePath, - final boolean followSymbolicLinks, - final int maxDepth, - final boolean testMode, - final PathSorter sorter, - final PathCondition[] pathConditions, - final StrSubstitutor subst) { - super(basePath, followSymbolicLinks, maxDepth, pathConditions, subst); - this.testMode = testMode; - this.pathSorter = Objects.requireNonNull(sorter, "sorter"); - } - - /* - * (non-Javadoc) - * - * @see org.apache.logging.log4j.core.appender.rolling.action.AbstractPathAction#execute() - */ - @Override - public boolean execute() throws IOException { - return executeDelete(); - } - - private boolean executeDelete() throws IOException { - final List selectedForDeletion = selectFiles(); - if (selectedForDeletion == null) { - LOGGER.trace("Null list returned (no files to delete)"); - return true; - } - deleteSelectedFiles(selectedForDeletion); - return true; - } - - private List selectFiles() throws IOException { - final List sortedPaths = getSortedPaths(); - trace("Sorted paths:", sortedPaths); - return selectFilesToDelete(getBasePath(), sortedPaths); - } - - private List selectFilesToDelete(Path basePath, List paths) - { - // Narrow to just the error log files - paths = paths.stream().filter(p -> p.getPath().toString().contains("labkey-errors.log")).collect(Collectors.toList()); - - List result = new ArrayList<>(); - - // Look for the first file from the current set of logging to move it away instead of rotating it - PathWithAttributes logToRetain = null; - long bestTimeVersusStartup = Long.MAX_VALUE; - - // Per Log4J specs, paths are sorted with most recently modified files first - for (int i = MAX_RETAINED; i < paths.size(); i++) - { - PathWithAttributes path = paths.get(i); - long timeVersusStartup = Math.abs(path.getAttributes().creationTime().toMillis() - _startup.getTime()); - // Look for a file that's the closest to the time we started up, and within 20 seconds of startup - if (timeVersusStartup < bestTimeVersusStartup && timeVersusStartup < 20_000) - { - bestTimeVersusStartup = timeVersusStartup; - logToRetain = path; - } - - result.add(path); - } - - if (logToRetain != null && !_copiedOriginal && logToRetain.getAttributes().size() > 0) - { - Path target = logToRetain.getPath().getParent().resolve("labkey-errors-" + DATE_FORMAT.format(new Date()) + ".log"); - LOGGER.info("Retaining labkey-errors.log file before it gets deleted by rotation. Copying to " + target); - - try - { - Files.move(logToRetain.getPath(), target); - // Don't need to mark it for deletion, as it's already been moved - result.remove(logToRetain); - } - catch (IOException e) - { - LOGGER.warn("Failed to retain error log file " + logToRetain.getPath(), e); - } - _copiedOriginal = true; - } - - return result; - } - - private void deleteSelectedFiles(final List selectedForDeletion) throws IOException { - trace("Paths selected for deletion:", selectedForDeletion); - for (final PathWithAttributes pathWithAttributes : selectedForDeletion) { - final Path path = pathWithAttributes == null ? null : pathWithAttributes.getPath(); - if (isTestMode()) { - LOGGER.info("Deleting {} (TEST MODE: file not actually deleted)", path); - } else { - delete(path); - } - } - } - - /** - * Deletes the specified file. - * - * @param path the file to delete - * @throws IOException if a problem occurred deleting the file - */ - protected void delete(final Path path) throws IOException { - LOGGER.trace("Deleting {}", path); - Files.deleteIfExists(path); - } - - /* - * (non-Javadoc) - * - * @see org.apache.logging.log4j.core.appender.rolling.action.AbstractPathAction#execute(FileVisitor) - */ - @Override - public boolean execute(final FileVisitor visitor) throws IOException { - final List sortedPaths = getSortedPaths(); - trace("Sorted paths:", sortedPaths); - - for (final PathWithAttributes element : sortedPaths) { - try { - visitor.visitFile(element.getPath(), element.getAttributes()); - } catch (final IOException ioex) { - LOGGER.error("Error in post-rollover Delete when visiting {}", element.getPath(), ioex); - visitor.visitFileFailed(element.getPath(), ioex); - } - } - // TODO return (visitor.success || ignoreProcessingFailure) - return true; // do not abort rollover even if processing failed - } - - private void trace(final String label, final List sortedPaths) { - LOGGER.trace(label); - for (final PathWithAttributes pathWithAttributes : sortedPaths) { - LOGGER.trace(pathWithAttributes); - } - } - - /** - * Returns a sorted list of all files up to maxDepth under the basePath. - * - * @return a sorted list of files - * @throws IOException - */ - List getSortedPaths() throws IOException { - final SortingVisitor sort = new SortingVisitor(pathSorter); - super.execute(sort); - final List sortedPaths = sort.getSortedPaths(); - return sortedPaths; - } - - /** - * Returns {@code true} if files are not deleted even when all conditions accept a path, {@code false} otherwise. - * - * @return {@code true} if files are not deleted even when all conditions accept a path, {@code false} otherwise - */ - public boolean isTestMode() { - return testMode; - } - - @Override - protected FileVisitor createFileVisitor(final Path visitorBaseDir, final List conditions) { - return new DeletingVisitor(visitorBaseDir, conditions, testMode); - } - - /** - * Create a DeleteAction. - * - * @param basePath base path from where to start scanning for files to delete. - * @param followLinks whether to follow symbolic links. Default is false. - * @param maxDepth The maxDepth parameter is the maximum number of levels of directories to visit. A value of 0 - * means that only the starting file is visited, unless denied by the security manager. A value of - * MAX_VALUE may be used to indicate that all levels should be visited. - * @param testMode if true, files are not deleted but instead a message is printed to the status logger - * at INFO level. Users can use this to do a dry run to test if their configuration works as expected. - * Default is false. - * @param sorterParameter a plugin implementing the {@link PathSorter} interface - * @param pathConditions an array of path conditions (if more than one, they all need to accept a path before it is - * deleted). - * @param config The Configuration. - * @return A DeleteAction. - */ - @PluginFactory - public static LabKeyDeleteAction createDeleteAction( - // @formatter:off - @PluginAttribute("basePath") final String basePath, - @PluginAttribute(value = "followLinks") final boolean followLinks, - @PluginAttribute(value = "maxDepth", defaultInt = 1) final int maxDepth, - @PluginAttribute(value = "testMode") final boolean testMode, - @PluginElement("PathSorter") final PathSorter sorterParameter, - @PluginElement("PathConditions") final PathCondition[] pathConditions, - @PluginConfiguration final Configuration config) { - // @formatter:on - final PathSorter sorter = sorterParameter == null ? new PathSortByModificationTime(true) : sorterParameter; - return new LabKeyDeleteAction( - basePath, - followLinks, - maxDepth, - testMode, - sorter, - pathConditions, - config.getStrSubstitutor()); - } -} diff --git a/api/src/org/labkey/api/util/SessionAppender.java b/api/src/org/labkey/api/util/SessionAppender.java index dc12c86c8de..5be885b7995 100644 --- a/api/src/org/labkey/api/util/SessionAppender.java +++ b/api/src/org/labkey/api/util/SessionAppender.java @@ -15,17 +15,7 @@ */ package org.labkey.api.util; -import org.apache.logging.log4j.core.Appender; -import org.apache.logging.log4j.core.Core; -import org.apache.logging.log4j.core.Filter; -import org.apache.logging.log4j.core.Layout; import org.apache.logging.log4j.core.LogEvent; -import org.apache.logging.log4j.core.appender.AbstractAppender; -import org.apache.logging.log4j.core.config.Property; -import org.apache.logging.log4j.core.config.plugins.Plugin; -import org.apache.logging.log4j.core.config.plugins.PluginAttribute; -import org.apache.logging.log4j.core.config.plugins.PluginElement; -import org.apache.logging.log4j.core.config.plugins.PluginFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.util.ConcurrentReferenceHashMap; @@ -33,6 +23,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpSession; import java.io.Serializable; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -40,29 +31,14 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; /** - * User: matthewb - * Date: Aug 18, 2009 - * Time: 2:18:21 PM + * Makes trigger script logging available to developers in the web UI. */ -@Plugin(name = "SessionAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE, printObject = true) -public class SessionAppender extends AbstractAppender +public class SessionAppender { - @PluginFactory - public static SessionAppender createAppender(@PluginAttribute("name") String name, - @PluginElement("Layout") Layout layout, - @PluginElement("Filter") final Filter filter) - { - return new SessionAppender(name, filter, layout, false, null); - } - - protected SessionAppender(String name, Filter filter, Layout layout, boolean ignoreExceptions, Property[] properties) - { - super(name, filter, layout, ignoreExceptions, properties); - } - - static class AppenderInfo implements Serializable + public static class AppenderInfo implements Serializable { AppenderInfo(String key, boolean on) { @@ -86,6 +62,25 @@ protected boolean removeEldestEntry(Map.Entry eldest) private static final ThreadLocal localInfo = new ThreadLocal<>(); + static + { + try + { + Class cl = Class.forName("org.labkey.embedded.SessionAppender"); + Field f = cl.getDeclaredField("_consumer"); + f.set(null, (Consumer) event -> { + AppenderInfo info = localInfo.get(); + if (null == info || !info.on) + return; + info.eventIdMap.put(event, ++info.eventId); + }); + } + catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) + { + throw UnexpectedException.wrap(e); + } + } + // AppenderInfos are thread-local variables initialized with the user session. This Map allows background threads to share an // active session's appenderInfo to output logs to that session's SessionAppender. When the session is ended, the // thread-local appenderInfo will be released and this map, which uses weak references, will allow gc to remove and @@ -110,16 +105,6 @@ public static String getAppendingInfoKey(HttpServletRequest request) return _getLoggingForSession(request).key; } - @Override - public void append(LogEvent event) - { - AppenderInfo info = localInfo.get(); - if (null == info || !info.on) - return; - info.eventIdMap.put(event, ++info.eventId); - } - - /** * @return serialization-suitable list of events with eventId, level, message, and timestamp properties */ diff --git a/pipeline/src/org/labkey/pipeline/api/PipelineServiceImpl.java b/pipeline/src/org/labkey/pipeline/api/PipelineServiceImpl.java index f4065cef274..ef012c01144 100644 --- a/pipeline/src/org/labkey/pipeline/api/PipelineServiceImpl.java +++ b/pipeline/src/org/labkey/pipeline/api/PipelineServiceImpl.java @@ -18,7 +18,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import org.apache.activemq.ActiveMQConnectionFactory; -import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.logging.log4j.Logger; @@ -72,8 +71,8 @@ import org.labkey.api.util.FileUtil; import org.labkey.api.util.JsonUtil; import org.labkey.api.util.NetworkDrive; -import org.labkey.api.util.Pair; import org.labkey.api.util.TestContext; +import org.labkey.api.util.UnexpectedException; import org.labkey.api.util.logging.LogHelper; import org.labkey.api.view.ActionURL; import org.labkey.api.view.HttpView; @@ -101,11 +100,9 @@ import javax.naming.InitialContext; import javax.naming.NamingException; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; @@ -123,9 +120,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; import static org.labkey.api.pipeline.PipelineJobNotificationProvider.DefaultPipelineJobNotificationProvider.DEFAULT_PIPELINE_JOB_NOTIFICATION_PROVIDER; import static org.labkey.api.pipeline.file.AbstractFileAnalysisJob.ANALYSIS_PARAMETERS_ROLE_NAME; @@ -457,78 +451,37 @@ public boolean isEnterprisePipeline() return (getPipelineQueue() instanceof EPipelineQueueImpl); } - /** @return first is labkeyBootstrap.jar, second is servletApi.jar */ - private Pair extractBootstrapFromEmbedded() throws IOException - { - File bootstrap = null; - File servlet = null; - // Look through the JAR files in the working directory, which is expected to contain the Spring Boot - // entrypoint and the Servlet API - File pwd = new File("."); - File[] jars = pwd.listFiles(f -> f.getName().toLowerCase().endsWith(".jar")); - for (File jar : jars) - { - try (JarFile j = new JarFile(jar)) - { - // Look inside the JAR for a labkeyBootstrap*.jar file - Iterator entries = j.entries().asIterator(); - while (entries.hasNext()) - { - // Keep this code in sync with org.labkey.embedded.EmbeddedExtractor.extractExecutableJar() - JarEntry entry = entries.next(); - if (entry.getName().contains("labkeyBootstrap") && entry.getName().toLowerCase().endsWith(".jar")) - { - bootstrap = extractEntry(j, entry, "labkeyBootstrap.jar"); - } - if (entry.getName().contains("tomcat-embed-core") && entry.getName().toLowerCase().endsWith(".jar")) - { - servlet = extractEntry(j, entry, "servletApi.jar"); - } - } - } - } - return Pair.of(bootstrap, servlet); - } - - private File extractEntry(JarFile jar, ZipEntry entry, String name) throws IOException - { - File result = FileUtil.getAbsoluteCaseSensitiveFile(new File(name)); - try (InputStream in = jar.getInputStream(entry); - OutputStream out = new FileOutputStream(result)) - { - IOUtils.copy(in, out); - } - return result; - } - - @Override - public List getClusterStartupArguments() throws IOException + public List getClusterStartupArguments() { List args = new ArrayList<>(); args.add(System.getProperty("java.home") + "/bin/java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")); - File labkeyBootstrap = new File(new File(new File(System.getProperty("catalina.home")), "lib"), "labkeyBootstrap.jar"); - File servletApi = null; + File labkeyBootstrap = new File(new File(System.getProperty("catalina.home")), "labkeyBootstrap.jar"); if (!labkeyBootstrap.exists()) { - Pair extracted = extractBootstrapFromEmbedded(); - labkeyBootstrap = extracted.first; - if (labkeyBootstrap == null || !labkeyBootstrap.exists()) + try + { + Class extractorClass = Class.forName("org.labkey.embedded.EmbeddedExtractor"); + Object extractor = extractorClass.getDeclaredConstructor(boolean.class).newInstance(true); + Method method = extractorClass.getDeclaredMethod("extractRemotePipelineJars"); + labkeyBootstrap = (File) method.invoke(extractor); + } + catch (InvocationTargetException e) { - throw new IllegalStateException("Couldn't find labkeyBootstrap.jar"); + throw UnexpectedException.wrap(e.getTargetException()); } - servletApi = extracted.second; - if (servletApi == null || !servletApi.exists()) + catch (ClassNotFoundException | InstantiationException | + IllegalAccessException | NoSuchMethodException e) { - throw new IllegalStateException("Couldn't find servletApi.jar"); + throw UnexpectedException.wrap(e); } } // Uncomment this line if you want to debug the forked process -// args.add("-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=*:5005"); +// args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005"); args.add("-cp"); - args.add(labkeyBootstrap.getPath()); + args.add(labkeyBootstrap.getAbsolutePath()); args.add(ClusterBootstrap.class.getName()); for (String sysProp : new String[]{"labkey.externalModulesDir", "labkey.modulesDir", "cpas.modulesDir"}) @@ -541,10 +494,8 @@ public List getClusterStartupArguments() throws IOException } args.add("-webappdir=" + ModuleLoader.getServletContext().getRealPath("")); - if (servletApi != null) - { - args.add("-pipelinelibdir=" + servletApi.getParent()); - } + File pipelineLib = FileUtil.appendName(labkeyBootstrap.getParentFile(), "pipeline-lib"); + args.add("-pipelinelibdir=" + pipelineLib.getAbsolutePath()); return args; } @@ -1109,7 +1060,7 @@ public void setUp() { TestContext ctx = TestContext.get(); User loggedIn = ctx.getUser(); - assertTrue("login before running this test", null != loggedIn); + assertNotNull("login before running this test", loggedIn); assertFalse("login before running this test", loggedIn.isGuest()); _user = ctx.getUser().cloneUser(); } @@ -1136,7 +1087,7 @@ public void testPipelineRootDefaultsInProject() File fileRoot = fileService.getFileRoot(_project, FileContentService.ContentType.files); // verify pipeline root and file root are set to defaults and they they point to the same place - assertEquals("The pipeline root isDefault flag was not set correctly.", true, pipelineRootSetting.isFileRoot()); + assertTrue("The pipeline root isDefault flag was not set correctly.", pipelineRootSetting.isFileRoot()); assertEquals("The default pipeline root was not set the same as the default file root.", pipelineRoot, fileRoot); String DEFAULT_ROOT_URI = "/files/__PipelineRootTestProject/@files"; assertTrue("The pipeline root uri was: " + FileUtil.uriToString(pipelineRootSetting.getUri()) + ", but expected: " + DEFAULT_ROOT_URI, FileUtil.uriToString(pipelineRootSetting.getUri()).contains(DEFAULT_ROOT_URI)); @@ -1171,7 +1122,7 @@ public void testPipelineRootWithCustomizedFileRootInProject() File fileRoot = fileService.getFileRoot(_project, FileContentService.ContentType.files); // verify pipeline root and file root are now both customized and set to the same customized location - assertEquals("The pipeline root isDefault flag was not set correctly.",true, pipelineRootSetting.isFileRoot()); + assertTrue("The pipeline root isDefault flag was not set correctly.", pipelineRootSetting.isFileRoot()); assertEquals("The default pipeline root was not set the same as the customized file root.",pipelineRoot, fileRoot); assertEquals("The pipeline root was not set to the customized file root location.", pipelineRoot.getParentFile(), getTestRoot(FILE_ROOT_SUFFIX)); @@ -1206,7 +1157,7 @@ public void testBothPipelineRootAndFileRootCustomizedInProject() throws Exceptio File fileRoot = fileService.getFileRoot(_project, FileContentService.ContentType.files); // verify pipeline root and file root are now both customized and set to different customized location - assertEquals("The pipeline root isDefault flag was not set correctly.",false, pipelineRootSetting.isFileRoot()); + assertFalse("The pipeline root isDefault flag was not set correctly.", pipelineRootSetting.isFileRoot()); assertNotEquals("The customized pipeline root was not set different than the customized file root.",pipelineRoot, fileRoot); assertEquals("The file root was not set to the customized file root location.", fileRoot.getParentFile(), getTestRoot(FILE_ROOT_SUFFIX)); assertEquals("The pipeline root was not set to the customized pipeline root location.", pipelineRoot, getTestRoot(PIPELINE_ROOT_SUFFIX)); @@ -1249,7 +1200,7 @@ public void testSubfolderWhenCustomizedFileRootInProject() File subfolderPipelineRoot = subfolderPipelineRootSetting.getRootPath(); // verify subfolder pipeline root and file root are now both customized and set to the same subfolder of the project file root - assertEquals("The pipeline root isDefault flag was not set correctly.",true, subfolderPipelineRootSetting.isFileRoot()); + assertTrue("The pipeline root isDefault flag was not set correctly.", subfolderPipelineRootSetting.isFileRoot()); assertEquals("The pipeline root of this subfolder was not set the same as the file root of the subfolder.",subFolderFileRoot, subfolderPipelineRoot); assertEquals("The file root of this subfolder was not set to a subfolder of the file root of the parent project.",projectFileRoot.getParentFile(), subFolderFileRoot.getParentFile().getParentFile()); @@ -1300,8 +1251,8 @@ public void testSubfolderWhenBothPipelineRootAndFileRootCustomizedInProject() th File subfolderPipelineRoot = subfolderPipelineRootSetting.getRootPath(); // verify subfolder pipeline root and project pipeline root are now both customized and set to the same location - assertEquals("The project pipeline root isDefault flag was not set correctly.",false, projectPipelineRootSetting.isFileRoot()); - assertEquals("The subfolder pipeline root isDefault flag was not set correctly.",false, subfolderPipelineRootSetting.isFileRoot()); + assertFalse("The project pipeline root isDefault flag was not set correctly.", projectPipelineRootSetting.isFileRoot()); + assertFalse("The subfolder pipeline root isDefault flag was not set correctly.", subfolderPipelineRootSetting.isFileRoot()); assertEquals("The file root of this subfolder was not set to a subfolder of the file root of the parent project.",projectFileRoot.getParentFile(), subFolderFileRoot.getParentFile().getParentFile()); assertEquals("The pipeline root of this subfolder was not set the same as the pipeline root of the parent project.",projectPipelineRoot, subfolderPipelineRoot); diff --git a/pipeline/src/org/labkey/pipeline/mule/test/DummyPipelineJob.java b/pipeline/src/org/labkey/pipeline/mule/test/DummyPipelineJob.java index a744e15a40e..1765440d137 100644 --- a/pipeline/src/org/labkey/pipeline/mule/test/DummyPipelineJob.java +++ b/pipeline/src/org/labkey/pipeline/mule/test/DummyPipelineJob.java @@ -30,7 +30,6 @@ import org.labkey.api.util.UnexpectedException; import org.labkey.api.view.ViewBackgroundInfo; -import java.io.File; import java.io.IOException; /** @@ -79,7 +78,7 @@ public DummyPipelineJob(Container c, User user, Worker worker) } catch (IOException e) { - throw new UnexpectedException(e); + throw UnexpectedException.wrap(e); } setActiveTaskId(getTaskPipeline().getTaskProgression()[0], false); } @@ -103,7 +102,7 @@ public String getDescription() @Nullable @Override - public TaskPipeline getTaskPipeline() + public TaskPipeline getTaskPipeline() { return PipelineJobService.get().getTaskPipeline(new TaskId(DummyPipelineJob.class)); }