/**
* 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.jooby.crash;
import static java.util.Arrays.asList;
import static javaslang.Tuple.of;
import static org.jooby.crash.CrashFSDriver.endsWith;
import static org.jooby.crash.CrashFSDriver.noneOf;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import org.crsh.plugin.CRaSHPlugin;
import org.crsh.plugin.PluginContext;
import org.crsh.plugin.PluginLifeCycle;
import org.crsh.vfs.FS;
import javaslang.control.Try;
class CrashBootstrap extends PluginLifeCycle {
private static final Predicate<Path> ACCEPT = endsWith(".class").negate();
private List<CrashFSDriver> drivers = new ArrayList<>();
public PluginContext start(final ClassLoader loader, final Properties props,
final Map<String, Object> attributes, final Set<CRaSHPlugin<?>> plugins) throws IOException {
FS conffs = newFS(CrashFSDriver.parse(loader, asList(
of("crash", ACCEPT))));
FS cmdfs = newFS(CrashFSDriver.parse(loader, asList(
of("cmd", ACCEPT),
of("org/jooby/crash", ACCEPT),
of("crash/commands", noneOf("jndi.groovy", "jdbc.groovy", "jpa.groovy", "jul.groovy")))));
setConfig(props);
PluginContext ctx = new PluginContext(executor("crash"), scanner("crash-scanner"),
() -> plugins, attributes, cmdfs, conffs, loader);
ctx.refresh();
start(ctx);
return ctx;
}
public void shutdown() {
drivers.forEach(it -> Try.run(it::close));
super.stop();
}
private FS newFS(final List<CrashFSDriver> drivers) throws IOException {
FS fs = new FS();
for (CrashFSDriver driver : drivers) {
fs.mount(driver);
}
this.drivers.addAll(drivers);
return fs;
}
private static ScheduledExecutorService scanner(final String name) {
return Executors.newScheduledThreadPool(1, r -> {
Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setName(name);
return thread;
});
}
private static ExecutorService executor(final String name) {
AtomicInteger next = new AtomicInteger(0);
return new ThreadPoolExecutor(0, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
r -> {
Thread thread = Executors.defaultThreadFactory().newThread(r);
thread.setName(name + "-" + next.incrementAndGet());
return thread;
});
}
}