From: Mathieu Baudier Date: Thu, 2 Jan 2020 10:43:00 +0000 (+0100) Subject: Start isolating Spring dependent parts. X-Git-Tag: argeo-slc-2.1.17~82 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=e2e42de8e379883a1c696fcd035d837648cb3526;p=gpl%2Fargeo-slc.git Start isolating Spring dependent parts. --- diff --git a/dep/org.argeo.slc.dep.backend/pom.xml b/dep/org.argeo.slc.dep.backend/pom.xml index baee5f845..8816fe9f0 100644 --- a/dep/org.argeo.slc.dep.backend/pom.xml +++ b/dep/org.argeo.slc.dep.backend/pom.xml @@ -40,7 +40,7 @@ org.argeo.slc - org.argeo.slc.dep.minimal + org.argeo.slc.dep.spring 2.1.17-SNAPSHOT diff --git a/dep/org.argeo.slc.dep.e4.rap/pom.xml b/dep/org.argeo.slc.dep.e4.rap/pom.xml index 8ae8da524..aea4c1ef0 100644 --- a/dep/org.argeo.slc.dep.e4.rap/pom.xml +++ b/dep/org.argeo.slc.dep.e4.rap/pom.xml @@ -45,7 +45,7 @@ org.argeo.slc - org.argeo.slc.dep.minimal + org.argeo.slc.dep.spring 2.1.17-SNAPSHOT diff --git a/dep/org.argeo.slc.dep.minimal/pom.xml b/dep/org.argeo.slc.dep.minimal/pom.xml index d297a9f03..6367fda66 100644 --- a/dep/org.argeo.slc.dep.minimal/pom.xml +++ b/dep/org.argeo.slc.dep.minimal/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 org.argeo.slc @@ -90,88 +92,7 @@ org.argeo.slc.agent.jcr 2.1.17-SNAPSHOT - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -196,29 +117,6 @@ - - - - - - - - - - - - - - - - - - - - - - - org.codehaus.mojo rpm-maven-plugin @@ -247,13 +145,6 @@ - - - - - - - argeo-cms-node diff --git a/dep/org.argeo.slc.dep.spring/.gitignore b/dep/org.argeo.slc.dep.spring/.gitignore new file mode 100644 index 000000000..76df179ce --- /dev/null +++ b/dep/org.argeo.slc.dep.spring/.gitignore @@ -0,0 +1,2 @@ +/target/ +/*.target diff --git a/dep/org.argeo.slc.dep.spring/META-INF/MANIFEST.MF b/dep/org.argeo.slc.dep.spring/META-INF/MANIFEST.MF new file mode 100644 index 000000000..a0edd6303 --- /dev/null +++ b/dep/org.argeo.slc.dep.spring/META-INF/MANIFEST.MF @@ -0,0 +1,11 @@ +Manifest-Version: 1.0 +Automatic-Module-Name: org.argeo.slc.dep.spring +Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt +Bundle-ManifestVersion: 2 +Bundle-Name: SLC Agent based on Spring +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-SymbolicName: org.argeo.slc.dep.spring +Bundle-Version: 2.1.17.SNAPSHOT-r202001021027 +Private-Package: !* +SLC-Category: org.argeo.slc +SLC-ModularDistribution: default diff --git a/dep/org.argeo.slc.dep.spring/bnd.bnd b/dep/org.argeo.slc.dep.spring/bnd.bnd new file mode 100644 index 000000000..e69de29bb diff --git a/dep/org.argeo.slc.dep.spring/pom.xml b/dep/org.argeo.slc.dep.spring/pom.xml new file mode 100644 index 000000000..05ab65c55 --- /dev/null +++ b/dep/org.argeo.slc.dep.spring/pom.xml @@ -0,0 +1,345 @@ + + 4.0.0 + + org.argeo.slc + dep + 2.1.17-SNAPSHOT + .. + + org.argeo.slc.dep.spring + SLC Agent based on Spring + + + + org.apache.felix + maven-bundle-plugin + + + default + + + + + org.argeo.maven.plugins + argeo-osgi-plugin + + + generate-descriptors + + descriptors + + generate-resources + + + + + + + + + + + + + + + + + + + + + + org.argeo.commons + org.argeo.dep.cms.node + ${version.argeo-commons} + + + + + org.argeo.slc + org.argeo.slc.api + 2.1.17-SNAPSHOT + + + org.argeo.slc + org.argeo.slc.core + 2.1.17-SNAPSHOT + + + org.argeo.slc + org.argeo.slc.agent + 2.1.17-SNAPSHOT + + + + + org.argeo.tp.spring + org.springframework.beans + + + org.argeo.tp.spring + org.springframework.core + + + org.argeo.tp.javax + javax.el + + + org.argeo.tp.gemini + org.eclipse.gemini.blueprint.core + + + org.argeo.tp.gemini + org.eclipse.gemini.blueprint.extender + + + org.argeo.tp.gemini + org.eclipse.gemini.blueprint.io + + + org.argeo.tp.misc + org.aspectj.weaver + + + org.argeo.tp.misc + org.aopalliance + + + org.argeo.tp.spring + org.springframework.aop + + + org.argeo.tp.spring + org.springframework.context + + + org.argeo.tp.spring + org.springframework.expression + + + org.argeo.tp.spring + org.springframework.instrument + + + + + org.argeo.tp.spring + org.springframework.aspects + + + org.argeo.tp.spring + org.springframework.context.support + + + org.argeo.tp.spring + org.springframework.jdbc + + + org.argeo.tp.spring + org.springframework.tx + + + org.argeo.tp.spring + org.springframework.web + + + org.argeo.tp.spring + org.springframework.web.servlet + + + + + + + + + + + + + + + + + org.argeo.slc + org.argeo.slc.agent.jcr + 2.1.17-SNAPSHOT + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rpmbuild + + + + maven-assembly-plugin + + + prepare-source + package + + single + + + + a2-source + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.codehaus.mojo + rpm-maven-plugin + + + rpm-argeo + package + + rpm + + + slc-agent + + + /usr/share/osgi + root + root + 644 + true + + + ${project.build.directory}/${project.artifactId}-${project.version}-a2-source + + **/*.jar + + + + + + + + + + + + + + argeo-cms-node + + + + + + + + + + \ No newline at end of file diff --git a/dep/pom.xml b/dep/pom.xml index 2aea9b4d5..2bf7f791d 100644 --- a/dep/pom.xml +++ b/dep/pom.xml @@ -11,8 +11,10 @@ pom org.argeo.slc.dep.minimal - org.argeo.slc.dep.backend + org.argeo.slc.dep.spring org.argeo.slc.dep.e4.rap + + org.argeo.slc.dep.backend diff --git a/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml b/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml index 7f2f8b405..6d31ddd11 100644 --- a/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml +++ b/org.argeo.slc.agent.jcr/META-INF/spring/jcr.xml @@ -34,8 +34,7 @@ - + class="org.argeo.slc.spring.AuthenticatedApplicationContextInitialization"> diff --git a/org.argeo.slc.agent/META-INF/spring/osgi.xml b/org.argeo.slc.agent/META-INF/spring/osgi.xml index b3e9aebe2..79d933cd0 100644 --- a/org.argeo.slc.agent/META-INF/spring/osgi.xml +++ b/org.argeo.slc.agent/META-INF/spring/osgi.xml @@ -39,14 +39,14 @@ - - - + + + - diff --git a/org.argeo.slc.core/src/org/argeo/slc/spring/AbstractSystemExecution.java b/org.argeo.slc.core/src/org/argeo/slc/spring/AbstractSystemExecution.java new file mode 100644 index 000000000..7813b9a5f --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/spring/AbstractSystemExecution.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed 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.argeo.slc.spring; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; +import javax.security.auth.login.LoginException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.node.NodeConstants; +import org.argeo.slc.SlcException; + +/** Provides base method for executing code with system authorization. */ +abstract class AbstractSystemExecution { + private final static Log log = LogFactory.getLog(AbstractSystemExecution.class); + private final Subject subject = new Subject(); + + /** Authenticate the calling thread */ + protected void authenticateAsSystem() { + ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + try { + LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject); + lc.login(); + } catch (LoginException e) { + throw new SlcException("Cannot login as system", e); + } finally { + Thread.currentThread().setContextClassLoader(origClassLoader); + } + if (log.isTraceEnabled()) + log.trace("System authenticated"); + } + + protected void deauthenticateAsSystem() { + ClassLoader origClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); + try { + LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN, subject); + lc.logout(); + } catch (LoginException e) { + throw new SlcException("Cannot logout as system", e); + } finally { + Thread.currentThread().setContextClassLoader(origClassLoader); + } + } + + protected Subject getSubject() { + return subject; + } +} diff --git a/org.argeo.slc.core/src/org/argeo/slc/spring/AuthenticatedApplicationContextInitialization.java b/org.argeo.slc.core/src/org/argeo/slc/spring/AuthenticatedApplicationContextInitialization.java new file mode 100644 index 000000000..68a9cc993 --- /dev/null +++ b/org.argeo.slc.core/src/org/argeo/slc/spring/AuthenticatedApplicationContextInitialization.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed 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.argeo.slc.spring; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.List; + +import javax.security.auth.Subject; + +import org.eclipse.gemini.blueprint.context.DependencyInitializationAwareBeanPostProcessor; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.AbstractBeanFactory; +import org.springframework.beans.factory.support.SecurityContextProvider; +import org.springframework.beans.factory.support.SimpleSecurityContextProvider; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +/** + * Executes with a system authentication the instantiation and initialization + * methods of the application context where it has been defined. + */ +public class AuthenticatedApplicationContextInitialization extends + AbstractSystemExecution implements + DependencyInitializationAwareBeanPostProcessor, ApplicationContextAware { + /** If non empty, restricts to these beans */ + private List beanNames = new ArrayList(); + + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + if (beanNames.size() == 0 || beanNames.contains(beanName)) + authenticateAsSystem(); + return bean; + } + + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (beanNames.size() == 0 || beanNames.contains(beanName)) + deauthenticateAsSystem(); + return bean; + } + + public void setBeanNames(List beanNames) { + this.beanNames = beanNames; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + if (applicationContext.getAutowireCapableBeanFactory() instanceof AbstractBeanFactory) { + final AbstractBeanFactory beanFactory = ((AbstractBeanFactory) applicationContext + .getAutowireCapableBeanFactory()); + // retrieve subject's access control context + // and set it as the bean factory security context + Subject.doAs(getSubject(), new PrivilegedAction() { + @Override + public Void run() { + SecurityContextProvider scp = new SimpleSecurityContextProvider( + AccessController.getContext()); + beanFactory.setSecurityContextProvider(scp); + return null; + } + }); + } + } +} diff --git a/org.argeo.slc.e4/SlcMain.java b/org.argeo.slc.e4/SlcMain.java new file mode 100644 index 000000000..a4bf3cd65 --- /dev/null +++ b/org.argeo.slc.e4/SlcMain.java @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed 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.argeo.slc.cli; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Method; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.UUID; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; + +import org.argeo.osgi.boot.OsgiBoot; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.launch.Framework; +import org.osgi.framework.launch.FrameworkFactory; + +/** Configures an SLC runtime and runs a process. */ +public class SlcMain implements PrivilegedAction { + public final static String NIX = "NIX"; + public final static String WINDOWS = "WINDOWS"; + public final static String SOLARIS = "SOLARIS"; + + public final static String os; + public final static String slcDirName = ".slc"; + final static File homeDir = new File(System.getProperty("user.home")); + + static { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Win")) + os = WINDOWS; + else if (osName.startsWith("Solaris")) + os = SOLARIS; + else + os = NIX; + } + + private Long timeout = 30 * 1000l; + private final String[] args; + private final File confDir; + private final File dataDir; + private final File modulesDir; + + private final List bundlesToStart = new ArrayList(); + + public SlcMain(String[] args, File confDir, File dataDir, File modulesDir) { + this.args = args; + this.confDir = confDir; + this.dataDir = dataDir; + this.modulesDir = modulesDir; + + bundlesToStart.add("org.eclipse.equinox.cm"); + bundlesToStart.add("org.argeo.cms"); + bundlesToStart.add("org.eclipse.gemini.blueprint.extender"); + bundlesToStart.add("org.argeo.slc.agent"); + bundlesToStart.add("org.argeo.slc.agent.jcr"); + + // bundlesToStart.add("org.springframework.osgi.extender"); + // bundlesToStart.add("org.argeo.node.repo.jackrabbit"); + // bundlesToStart.add("org.argeo.security.dao.os"); + // bundlesToStart.add("org.argeo.slc.node.jackrabbit"); + // bundlesToStart.add("org.argeo.slc.agent"); + // bundlesToStart.add("org.argeo.slc.agent.jcr"); + // if (args.length == 0) + // bundlesToStart.add("org.argeo.slc.support.equinox"); + // bundlesToStart.add("org.argeo.slc.agent.cli"); + } + + public String run() { + long begin = System.currentTimeMillis(); + + Framework framework = null; + try { + info("## Date : " + new Date()); + info("## Data : " + dataDir.getCanonicalPath()); + + // Start Equinox + ServiceLoader ff = ServiceLoader.load(FrameworkFactory.class); + FrameworkFactory frameworkFactory = ff.iterator().next(); + Map configuration = new HashMap(); + configuration.put("osgi.configuration.area", confDir.getCanonicalPath()); + configuration.put("osgi.instance.area", dataDir.getCanonicalPath()); + // Do clean + configuration.put("osgi.clean", "true"); + if (args.length == 0) { + configuration.put("osgi.console", ""); + } + + // Spring configs currently require System properties + System.getProperties().putAll(configuration); + + framework = frameworkFactory.newFramework(configuration); + framework.start(); + BundleContext bundleContext = framework.getBundleContext(); + + // OSGi bootstrap + OsgiBoot osgiBoot = new OsgiBoot(bundleContext); + + // working copy modules + if (modulesDir.exists()) + osgiBoot.installUrls(osgiBoot.getBundlesUrls(modulesDir.getCanonicalPath() + ";in=*;ex=.gitignore")); + + // system modules + if (System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BUNDLES) != null) + osgiBoot.installUrls(osgiBoot.getBundlesUrls(System.getProperty(OsgiBoot.PROP_ARGEO_OSGI_BUNDLES))); + else + osgiBoot.installUrls(osgiBoot.getBundlesUrls(System.getProperty("user.home") + "/.slc/modules/;in=**")); + + // Start runtime + osgiBoot.startBundles(bundlesToStart); + + // Find SLC Agent + ServiceReference sr = null; + while (sr == null) { + sr = bundleContext.getServiceReference("org.argeo.slc.execution.SlcAgentCli"); + if (System.currentTimeMillis() - begin > timeout) + throw new RuntimeException("Cannot find SLC agent CLI"); + Thread.sleep(100); + } + Object agentCli = bundleContext.getService(sr); + + // Initialization completed + long duration = System.currentTimeMillis() - begin; + info("[[ Initialized in " + (duration / 1000) + "s " + (duration % 1000) + "ms ]]"); + + if (args.length == 0) + return null;// console mode + + // Subject.doAs(Subject.getSubject(AccessController.getContext()), + // new AgentCliCall(agentCli)); + Class[] parameterTypes = { String[].class }; + Method method = agentCli.getClass().getMethod("process", parameterTypes); + Object[] methodArgs = { args }; + Object ret = method.invoke(agentCli, methodArgs); + + // Shutdown OSGi runtime + framework.stop(); + framework.waitForStop(60 * 1000); + + return ret.toString(); + } catch (Exception e) { + // Shutdown OSGi runtime + if (framework != null) + try { + framework.stop(); + framework.waitForStop(15 * 1000); + } catch (Exception silent) { + } + throw new RuntimeException("Cannot run SLC command line", e); + } finally { + + } + } + + public static void main(String[] args) { + try { + // Prepare directories + File executionDir = new File(System.getProperty("user.dir")); + File slcDir; + Boolean isTransient = false; + if (isTransient) { + File tempDir = new File(System.getProperty("java.io.tmpdir") + "/" + System.getProperty("user.name")); + slcDir = new File(tempDir, "slc-" + UUID.randomUUID().toString()); + slcDir.mkdirs(); + System.setProperty("argeo.node.repo.configuration", "osgibundle:repository-memory.xml"); + } else { + slcDir = findSlcDir(executionDir); + if (slcDir == null) { + slcDir = new File(executionDir, slcDirName); + slcDir.mkdirs(); + info("## Creating an SLC node at " + slcDir + " ..."); + } + } + + File dataDir = new File(slcDir, "data"); + if (!dataDir.exists()) + dataDir.mkdirs(); + + File confDir = new File(slcDir, "conf"); + if (!confDir.exists()) + confDir.mkdirs(); + + File modulesDir = new File(slcDir, "modules"); + + // JAAS + // File jaasFile = new File(confDir, "jaas.config"); + // if (!jaasFile.exists()) + // copyResource("/org/argeo/slc/cli/jaas.config", jaasFile); + // System.setProperty("java.security.auth.login.config", + // jaasFile.getCanonicalPath()); + + // log4j + File log4jFile = new File(confDir, "log4j.properties"); + if (!log4jFile.exists()) + copyResource("/org/argeo/slc/cli/log4j.properties", log4jFile); + System.setProperty("log4j.configuration", "file://" + log4jFile.getCanonicalPath()); + // Run as a privileged action + // LoginContext lc = new LoginContext(os); + // lc.login(); + // + // Subject subject = + // Subject.getSubject(AccessController.getContext()); + // Subject.doAs(subject, new SlcMain(args, confDir, dataDir, + // modulesDir)); + SlcMain slcMain = new SlcMain(args, confDir, dataDir, modulesDir); + slcMain.run(); + if (args.length != 0) + System.exit(0); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + } + + /** + * Recursively look in parent directories for a directory named + * {@link #slcDirName} + */ + protected static File findSlcDir(File currentDir) { + File slcDir = new File(currentDir, slcDirName); + // covers the use case of running from the home directory + if (slcDir.exists() && slcDir.isDirectory()) + return slcDir; + File parentDir = currentDir.getParentFile(); + if (parentDir == null) + return null; + try { + // ~/.slc reserved for agent + if (parentDir.getCanonicalPath().equals(homeDir.getCanonicalPath())) + return null; + } catch (IOException e) { + throw new RuntimeException("Cannot check home directory", e); + } + return findSlcDir(parentDir); + } + + protected static void copyResource(String resource, File targetFile) { + InputStream input = null; + FileOutputStream output = null; + try { + input = SlcMain.class.getResourceAsStream(resource); + output = new FileOutputStream(targetFile); + byte[] buf = new byte[8192]; + while (true) { + int length = input.read(buf); + if (length < 0) + break; + output.write(buf, 0, length); + } + } catch (Exception e) { + throw new RuntimeException("Cannot write " + resource + " file to " + targetFile, e); + } finally { + try { + input.close(); + } catch (Exception ignore) { + } + try { + output.close(); + } catch (Exception ignore) { + } + } + + } + + protected static void info(Object msg) { + System.out.println(msg); + } + + protected static void err(Object msg) { + System.err.println(msg); + } + + protected static void debug(Object msg) { + System.out.println(msg); + } + +} + +// private String bundlesToInstall = System.getProperty("user.home") +// + +// "/dev/src/slc/dep/org.argeo.slc.dep.minimal/target/dependency;in=*.jar," +// + System.getProperty("user.home") +// + "/dev/src/slc/demo/modules;in=*;ex=pom.xml;ex=.svn"; + +// ServiceTracker agentTracker = new ServiceTracker(bundleContext, +// "org.argeo.slc.execution.SlcAgentCli", null); +// agentTracker.open(); +// final Object agentCli = agentTracker.waitForService(30 * 1000); +// if (agentCli == null) +// throw new RuntimeException("Cannot find SLC agent CLI"); + +// protected class AgentCliCall implements PrivilegedAction { +// private final Object agentCli; +// +// public AgentCliCall(Object agentCli) { +// super(); +// this.agentCli = agentCli; +// } +// +// public String run() { +// try { +// Class[] parameterTypes = { String[].class }; +// Method method = agentCli.getClass().getMethod("process", +// parameterTypes); +// Object[] methodArgs = { args }; +// Object ret = method.invoke(agentCli, methodArgs); +// return ret.toString(); +// } catch (Exception e) { +// throw new RuntimeException("Cannot run " +// + Arrays.toString(args) + " on " + agentCli, e); +// } +// } +// +// } diff --git a/org.argeo.slc.launcher/.gitignore b/org.argeo.slc.launcher/.gitignore index b83d22266..c2bdee88c 100644 --- a/org.argeo.slc.launcher/.gitignore +++ b/org.argeo.slc.launcher/.gitignore @@ -1 +1,2 @@ /target/ +/.slc/