From f13697a39e4e56f0d99632307f5531b1f07d7f45 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 12 May 2019 10:43:04 +0200 Subject: [PATCH] Remove runner servlet --- .../execution/http/RunnerHttpContext.java | 84 ----- .../core/execution/http/RunnerServlet.java | 313 ------------------ .../http/RunnerServletContextHelper.java | 60 ---- .../core/execution/http/ServiceChannel.java | 77 ----- .../core/execution/http/WebServiceTask.java | 74 ----- 5 files changed, 608 deletions(-) delete mode 100644 org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerHttpContext.java delete mode 100644 org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServlet.java delete mode 100644 org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServletContextHelper.java delete mode 100644 org.argeo.slc.core/src/org/argeo/slc/core/execution/http/ServiceChannel.java delete mode 100644 org.argeo.slc.core/src/org/argeo/slc/core/execution/http/WebServiceTask.java diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerHttpContext.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerHttpContext.java deleted file mode 100644 index 6a67168de..000000000 --- a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerHttpContext.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.argeo.slc.core.execution.http; - -import java.io.IOException; -import java.net.URL; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.auth.HttpRequestCallbackHandler; -import org.argeo.node.NodeConstants; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; -import org.osgi.service.http.HttpContext; - -class RunnerHttpContext implements HttpContext { - final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; - private final static Log log = LogFactory.getLog(RunnerHttpContext.class); - - private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); - - private final String httpAuthRealm; - - public RunnerHttpContext(String httpAuthrealm) { - this.httpAuthRealm = httpAuthrealm; - } - - @Override - public boolean handleSecurity(final HttpServletRequest request, HttpServletResponse response) throws IOException { - LoginContext lc; - try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response)); - lc.login(); - } catch (LoginException e) { - lc = processUnauthorized(request, response); - if (lc == null) - return false; - } - Subject.doAs(lc.getSubject(), new PrivilegedAction() { - - @Override - public Void run() { - request.setAttribute(REMOTE_USER, AccessController.getContext()); - return null; - } - - }); - - return true; - } - - @Override - public URL getResource(String name) { - return bc.getBundle().getResource(name); - } - - @Override - public String getMimeType(String name) { - return null; - } - - protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) { - askForWwwAuth(request, response); - return null; - } - - protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) { - response.setStatus(401); - // if (org.argeo.cms.internal.kernel.Activator.getAcceptorCredentials() - // != null && !forceBasic)// SPNEGO - // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Negotiate"); - // else - response.setHeader(HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\""); - - } - -} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServlet.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServlet.java deleted file mode 100644 index eb9b43568..000000000 --- a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServlet.java +++ /dev/null @@ -1,313 +0,0 @@ -package org.argeo.slc.core.execution.http; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.channels.Channels; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.AccessControlContext; -import java.security.PrivilegedAction; -import java.util.Collection; -import java.util.GregorianCalendar; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -import javax.jcr.Node; -import javax.jcr.Property; -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.security.auth.Subject; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.cms.auth.CmsSession; -import org.argeo.jcr.JcrUtils; -import org.argeo.node.NodeUtils; -import org.argeo.slc.SlcException; -import org.argeo.slc.SlcNames; -import org.argeo.slc.SlcTypes; -import org.argeo.slc.execution.ExecutionProcess; -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.service.http.HttpContext; -import org.osgi.service.http.HttpService; -import org.osgi.util.tracker.ServiceTracker; - -public class RunnerServlet extends HttpServlet { - private final static Log log = LogFactory.getLog(RunnerServlet.class); - - private static final long serialVersionUID = -317016687309065291L; - - private Path baseDir; - private BundleContext bc; - private ExecutorService executor; - private boolean persistProcesses = true; - - public RunnerServlet(BundleContext bc, Path baseDir, ExecutorService executor) { - this.bc = bc; - this.baseDir = baseDir; - this.executor = executor; - } - - protected void setPersistProcesses(boolean persistProcesses) { - this.persistProcesses = persistProcesses; - } - - @Override - protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - super.service(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - InputStream in; - // Deal with x-www-form-urlencoded - // FIXME make it more robust an generic - Map params = req.getParameterMap(); - if (params.size() != 0) { - String json = params.keySet().iterator().next(); - in = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)); - } else { - in = req.getInputStream(); - } - - String path = req.getPathInfo(); - // InputStream in = req.getInputStream(); - OutputStream out = resp.getOutputStream(); - - String tokens[] = path.split("/"); - // first token alway empty - String workgroup = tokens[1]; - - CmsSession cmsSession = getByLocalId(req.getSession().getId()); - // FIXME make it more robust - if (cmsSession != null) {// multiuser - boolean authorized = false; - for (String role : cmsSession.getAuthorization().getRoles()) { - if (role.startsWith("cn=" + workgroup) || role.startsWith("uid=" + workgroup)) { - authorized = true; - break; - } - } - if (!authorized) { - resp.setStatus(403); - return; - } - } - // LdapName userDn = cmsSession.getUserDn(); - AccessControlContext acc = (AccessControlContext) req.getAttribute(HttpContext.REMOTE_USER); - Subject subject = Subject.getSubject(acc); - // flow path - StringBuilder sb = new StringBuilder(""); - for (int i = 2; i < tokens.length; i++) { - if (i != 2) - sb.append('/'); - sb.append(tokens[i]); - } - String flowName = sb.toString(); - String ext = FilenameUtils.getExtension(flowName.toString()); - - Session session = null; - Node realizedFlowNode = null; - if (persistProcesses) { - // JCR - Repository repository; - try { - ServiceReference sr = bc.getServiceReferences(Repository.class, "(cn=home)").iterator() - .next(); - repository = bc.getService(sr); - - } catch (InvalidSyntaxException e2) { - throw new SlcException("Cannot find home repository", e2); - } - session = Subject.doAs(subject, new PrivilegedAction() { - - @Override - public Session run() { - try { - return repository.login(); - } catch (RepositoryException e) { - throw new RuntimeException("Cannot login", e); - } - } - - }); - UUID processUuid = UUID.randomUUID(); - GregorianCalendar started = new GregorianCalendar(); - Node groupHome = NodeUtils.getGroupHome(session, workgroup); - if (groupHome == null) { - groupHome = NodeUtils.getUserHome(session); - } - String processPath = SlcNames.SLC_SYSTEM + "/" + SlcNames.SLC_PROCESSES + "/" - + JcrUtils.dateAsPath(started, true) + processUuid; - Node processNode = JcrUtils.mkdirs(groupHome, processPath, SlcTypes.SLC_PROCESS); - try { - processNode.setProperty(SlcNames.SLC_UUID, processUuid.toString()); - processNode.setProperty(SlcNames.SLC_STATUS, ExecutionProcess.RUNNING); - realizedFlowNode = processNode.addNode(SlcNames.SLC_FLOW); - realizedFlowNode.addMixin(SlcTypes.SLC_REALIZED_FLOW); - realizedFlowNode.setProperty(SlcNames.SLC_STARTED, started); - realizedFlowNode.setProperty(SlcNames.SLC_NAME, flowName); - Node addressNode = realizedFlowNode.addNode(SlcNames.SLC_ADDRESS, NodeType.NT_ADDRESS); - addressNode.setProperty(Property.JCR_PATH, flowName); - processNode.getSession().save(); - } catch (RepositoryException e1) { - throw new SlcException("Cannot register SLC process", e1); - } - if (log.isTraceEnabled()) - log.trace(session.getUserID() + " " + workgroup + " " + flowName); - } - - boolean isFailed = false; - try (ServiceChannel serviceChannel = new ServiceChannel(Channels.newChannel(in), Channels.newChannel(out), - executor)) { - resp.setHeader("Content-Type", "application/json"); - - Callable task; - if (ext.equals("api")) { - String uri = Files.readAllLines(baseDir.resolve(flowName)).get(0); - task = new WebServiceTask(serviceChannel, uri); - } else { - task = createTask(serviceChannel, flowName); - } - - if (task == null) - throw new SlcException("No task found for " + flowName); - - // execute - Future f = executor.submit(task); - int written = f.get(); - - if (written < 0) {// error - isFailed = true; - } - - if (log.isTraceEnabled()) - log.trace("Written " + written + " bytes"); - if (persistProcesses) - try { - Node processNode = realizedFlowNode.getParent(); - processNode.setProperty(SlcNames.SLC_STATUS, - isFailed ? ExecutionProcess.ERROR : ExecutionProcess.COMPLETED); - realizedFlowNode.setProperty(SlcNames.SLC_COMPLETED, new GregorianCalendar()); - processNode.getSession().save(); - } catch (RepositoryException e1) { - throw new SlcException("Cannot update SLC process status", e1); - } - } catch (Exception e) { - if (persistProcesses) - try { - Node processNode = realizedFlowNode.getParent(); - processNode.setProperty(SlcNames.SLC_STATUS, ExecutionProcess.ERROR); - realizedFlowNode.setProperty(SlcNames.SLC_COMPLETED, new GregorianCalendar()); - processNode.getSession().save(); - } catch (RepositoryException e1) { - throw new SlcException("Cannot update SLC process status", e1); - } - // throw new SlcException("Task " + flowName + " failed", e); - isFailed = true; - } finally { - JcrUtils.logoutQuietly(session); - } - - if (isFailed) { - resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } - } - - protected Callable createTask(ServiceChannel serviceChannel, String flowName) { - return null; - } - - protected Path getBaseDir() { - return baseDir; - } - - protected HttpContext getHttpContext(String httpAuthrealm) { - return null; - } - - public static void register(BundleContext bc, String alias, RunnerServlet runnerServlet, String httpAuthrealm) { - try { - ServiceTracker serviceTracker = new ServiceTracker(bc, - HttpService.class, null) { - - @Override - public HttpService addingService(ServiceReference reference) { - // TODO Auto-generated method stub - HttpService httpService = super.addingService(reference); - try { - HttpContext httpContext = runnerServlet.getHttpContext(httpAuthrealm); - if (httpContext == null) - httpContext = new RunnerHttpContext(httpAuthrealm); - httpService.registerServlet(alias, runnerServlet, null, httpContext); - } catch (Exception e) { - throw new SlcException("Cannot register servlet", e); - } - return httpService; - } - - }; - // ServiceReference ref = - // bc.getServiceReference(HttpService.class); - // HttpService httpService = bc.getService(ref); - // httpService.registerServlet(alias, runnerServlet, null, null); - // bc.ungetService(ref); - serviceTracker.open(); - } catch (Exception e) { - throw new SlcException("Cannot register servlet", e); - } - } - - public static void unregister(BundleContext bc, String alias) { - try { - ServiceReference ref = bc.getServiceReference(HttpService.class); - if (ref == null) - return; - HttpService httpService = bc.getService(ref); - httpService.unregister(alias); - bc.ungetService(ref); - } catch (Exception e) { - throw new SlcException("Cannot unregister servlet", e); - } - } - - CmsSession getByLocalId(String localId) { - // BundleContext bc = - // FrameworkUtil.getBundle(RunnerServlet.class).getBundleContext(); - Collection> sr; - try { - sr = bc.getServiceReferences(CmsSession.class, "(" + CmsSession.SESSION_LOCAL_ID + "=" + localId + ")"); - } catch (InvalidSyntaxException e) { - throw new SlcException("Cannot get CMS session for id " + localId, e); - } - ServiceReference cmsSessionRef; - if (sr.size() == 1) { - cmsSessionRef = sr.iterator().next(); - return (CmsSession) bc.getService(cmsSessionRef); - } else if (sr.size() == 0) { - return null; - } else - throw new SlcException(sr.size() + " CMS sessions registered for " + localId); - - } - - protected ExecutorService getExecutor() { - return executor; - } - -} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServletContextHelper.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServletContextHelper.java deleted file mode 100644 index 3af5e73fa..000000000 --- a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/RunnerServletContextHelper.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.argeo.slc.core.execution.http; - -import java.io.IOException; -import java.security.AccessController; -import java.security.PrivilegedAction; - -import javax.security.auth.Subject; -import javax.security.auth.login.LoginContext; -import javax.security.auth.login.LoginException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.argeo.cms.auth.HttpRequestCallbackHandler; -import org.argeo.node.NodeConstants; -import org.osgi.service.http.context.ServletContextHelper; - -public class RunnerServletContextHelper extends ServletContextHelper { - final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; - private final String httpAuthRealm = "Runner"; - - @Override - public boolean handleSecurity(final HttpServletRequest request, HttpServletResponse response) throws IOException { - LoginContext lc; - try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request, response)); - lc.login(); - } catch (LoginException e) { - // for CORS - // TODO: make it more robust - if ("OPTIONS".equals(request.getMethod())) - return true; - lc = processUnauthorized(request, response); - if (lc == null) - return false; - } - Subject.doAs(lc.getSubject(), new PrivilegedAction() { - - @Override - public Void run() { - request.setAttribute(REMOTE_USER, AccessController.getContext()); - return null; - } - - }); - - return true; - } - - protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) { - askForWwwAuth(request, response); - return null; - } - - protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) { - response.setStatus(401); - response.setHeader(HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\""); - - } - -} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/ServiceChannel.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/ServiceChannel.java deleted file mode 100644 index ef8febd00..000000000 --- a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/ServiceChannel.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.argeo.slc.core.execution.http; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousByteChannel; -import java.nio.channels.CompletionHandler; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; - -public class ServiceChannel implements AsynchronousByteChannel { - private final ReadableByteChannel in; - private final WritableByteChannel out; - - private boolean open = true; - - private ExecutorService executor; - - public ServiceChannel(ReadableByteChannel in, WritableByteChannel out, ExecutorService executor) { - this.in = in; - this.out = out; - this.executor = executor; - } - - @Override - public Future read(ByteBuffer dst) { - return executor.submit(() -> in.read(dst)); - } - - @Override - public void read(ByteBuffer dst, A attachment, CompletionHandler handler) { - try { - Future res = read(dst); - handler.completed(res.get(), attachment); - } catch (Exception e) { - handler.failed(e, attachment); - } - } - - @Override - public Future write(ByteBuffer src) { - return executor.submit(() -> out.write(src)); - } - - @Override - public void write(ByteBuffer src, A attachment, CompletionHandler handler) { - try { - Future res = write(src); - handler.completed(res.get(), attachment); - } catch (Exception e) { - handler.failed(e, attachment); - } - } - - @Override - public synchronized void close() throws IOException { - try { - in.close(); - } catch (Exception e) { - e.printStackTrace(); - } - try { - out.close(); - } catch (Exception e) { - e.printStackTrace(); - } - open = false; - notifyAll(); - } - - @Override - public synchronized boolean isOpen() { - return open; - } - -} diff --git a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/WebServiceTask.java b/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/WebServiceTask.java deleted file mode 100644 index b94223294..000000000 --- a/org.argeo.slc.core/src/org/argeo/slc/core/execution/http/WebServiceTask.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.argeo.slc.core.execution.http; - -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.channels.AsynchronousByteChannel; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; - -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.InputStreamRequestEntity; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.RequestEntity; - -public class WebServiceTask implements Callable { - private String url; - private String requContentType; - private String respContentType; - - private AsynchronousByteChannel channel; - - public WebServiceTask(AsynchronousByteChannel channel, String url) { - this(url, "application/json", "application/json", channel); - } - - public WebServiceTask(String url, String requContentType, String respContentType, AsynchronousByteChannel channel) { - this.url = url; - this.requContentType = requContentType; - this.respContentType = respContentType; - this.channel = channel; - } - - @Override - public Integer call() throws Exception { - // Webservice - HttpClient httpClient = new HttpClient(); - PostMethod postMethod = new PostMethod(url); - InputStream in = Channels.newInputStream(channel); - RequestEntity requestEntity = new InputStreamRequestEntity(in, requContentType); - // StringRequestEntity requestEntity = new - // StringRequestEntity(payloadStr, "application/json", "UTF-8"); - postMethod.setRequestEntity(requestEntity); - httpClient.executeMethod(postMethod); - InputStream answerIn = postMethod.getResponseBodyAsStream(); - ReadableByteChannel answer = Channels.newChannel(answerIn); - ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); - int read = 0; - Integer writeRes = 0; - while (read != -1) { - read = answer.read(buffer); - if (read <= 0) - break; - buffer.flip(); - Future f = channel.write(buffer); - writeRes = writeRes + f.get(); - buffer.clear(); - } - return writeRes; - } - - public String getUrl() { - return url; - } - - public String getRequContentType() { - return requContentType; - } - - public String getRespContentType() { - return respContentType; - } - -} -- 2.39.2