Return-Path: Delivered-To: apmail-sling-commits-archive@www.apache.org Received: (qmail 11656 invoked from network); 27 Jul 2010 14:42:20 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 27 Jul 2010 14:42:20 -0000 Received: (qmail 40201 invoked by uid 500); 27 Jul 2010 14:42:20 -0000 Delivered-To: apmail-sling-commits-archive@sling.apache.org Received: (qmail 40142 invoked by uid 500); 27 Jul 2010 14:42:20 -0000 Mailing-List: contact commits-help@sling.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@sling.apache.org Delivered-To: mailing list commits@sling.apache.org Received: (qmail 40135 invoked by uid 99); 27 Jul 2010 14:42:19 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Jul 2010 14:42:19 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 27 Jul 2010 14:42:12 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D91632388A3B; Tue, 27 Jul 2010 14:41:17 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r979727 - in /sling/trunk/contrib/extensions/bgservlets: ./ src/main/java/org/apache/sling/bgservlets/ src/main/java/org/apache/sling/bgservlets/impl/ src/main/java/org/apache/sling/bgservlets/impl/servlets/ src/main/java/org/apache/sling/b... Date: Tue, 27 Jul 2010 14:41:17 -0000 To: commits@sling.apache.org From: bdelacretaz@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100727144117.D91632388A3B@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: bdelacretaz Date: Tue Jul 27 14:41:16 2010 New Revision: 979727 URL: http://svn.apache.org/viewvc?rev=979727&view=rev Log: SLING-550 - JobConsole backend added, gets job data from persistent storage Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java (with props) sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java (with props) sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java (with props) sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java (with props) sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/JobConsolePlugin.java - copied, changed from r979652, sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java Removed: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java Modified: sling/trunk/contrib/extensions/bgservlets/pom.xml sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobData.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/Activator.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundRequestExecutionJob.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobStorageException.java Modified: sling/trunk/contrib/extensions/bgservlets/pom.xml URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/pom.xml?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/pom.xml (original) +++ sling/trunk/contrib/extensions/bgservlets/pom.xml Tue Jul 27 14:41:16 2010 @@ -109,6 +109,11 @@ 2.0.4-incubator + org.apache.sling + org.apache.sling.jcr.api + 2.0.6 + + javax.servlet servlet-api Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java?rev=979727&view=auto ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java (added) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java Tue Jul 27 14:41:16 2010 @@ -0,0 +1,50 @@ +/* + * 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.apache.sling.bgservlets; + +import java.util.Iterator; + +import javax.jcr.Session; +import javax.servlet.http.HttpServletRequest; + +/** Back-end for management consoles that + * give access to background jobs. + */ +public interface JobConsole { + /** Return Iterator on JobStatus, in descending order of + * creation date. + * + * @param session not used if activeOnly = true + * @param activeOnly if true, only jobs that are currently + * active in the ExecutionEngine are returned. + */ + Iterator getJobStatus(Session session, boolean activeOnly); + + /** Return a single JobStatus, null if not found. + * + * @param session Session to use if reading from persistent storage + * @param path the job path + */ + JobStatus getJobStatus(Session session, String path); + + /** Return the full path, including extension, to use to display + * the given job status' page. + */ + String getJobStatusPagePath(HttpServletRequest request, JobStatus jobStatus, String extension); +} Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobConsole.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobData.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobData.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobData.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/JobData.java Tue Jul 27 14:41:16 2010 @@ -26,6 +26,7 @@ import java.io.OutputStream; */ public interface JobData { String JOB_DATA_MIXIN = "sling:bgJobData"; + String PROP_EXTENSION = "sling;jobExtension"; /** Return unique path of this data item */ String getPath(); @@ -40,4 +41,10 @@ public interface JobData { * @return null if no stream stored yet */ InputStream getInputStream(); + + /** Set a named property */ + void setProperty(String name, String value); + + /** Get a named property, null if non-existent */ + String getProperty(String name); } Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/Activator.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/Activator.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/Activator.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/Activator.java Tue Jul 27 14:41:16 2010 @@ -18,7 +18,7 @@ */ package org.apache.sling.bgservlets.impl; -import org.apache.sling.bgservlets.impl.webconsole.ExecutionEngineConsolePlugin; +import org.apache.sling.bgservlets.impl.webconsole.JobConsolePlugin; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.slf4j.Logger; @@ -33,7 +33,7 @@ public class Activator implements Bundle */ public void start(BundleContext context) throws Exception { try { - ExecutionEngineConsolePlugin.initPlugin(context); + JobConsolePlugin.initPlugin(context); } catch (Throwable ignore) { // Happens for example if the webconsole is not installed log.debug("Exception in start()", ignore); @@ -45,7 +45,7 @@ public class Activator implements Bundle */ public void stop(BundleContext context) throws Exception { try { - ExecutionEngineConsolePlugin.destroyPlugin(); + JobConsolePlugin.destroyPlugin(); } catch (Throwable ignore) { log.debug("Exception in stop()", ignore); } Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundRequestExecutionJob.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundRequestExecutionJob.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundRequestExecutionJob.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundRequestExecutionJob.java Tue Jul 27 14:41:16 2010 @@ -24,6 +24,7 @@ import javax.jcr.Session; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.LoginException; import org.apache.sling.api.resource.ResourceResolver; import org.apache.sling.api.resource.ResourceResolverFactory; @@ -51,7 +52,7 @@ class BackgroundRequestExecutionJob impl private final String path; BackgroundRequestExecutionJob(SlingServlet slingServlet, - ResourceResolverFactory rrf, JobStorage storage, HttpServletRequest request, + ResourceResolverFactory rrf, JobStorage storage, SlingHttpServletRequest request, HttpServletResponse hsr, String[] parametersToRemove) throws IOException, LoginException { this.request = new BackgroundHttpServletRequest(request, @@ -77,6 +78,10 @@ class BackgroundRequestExecutionJob impl throw new IOException("Unable to get Session from ResourceResolver " + resourceResolver); } final JobData d = storage.createJobData(s); + final String ext = request.getRequestPathInfo().getExtension(); + if(ext != null) { + d.setProperty(JobData.PROP_EXTENSION, ext); + } path = d.getPath(); stream = new SuspendableOutputStream(d.getOutputStream()); response = new BackgroundHttpServletResponse(hsr, stream); Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundServletStarterFilter.java Tue Jul 27 14:41:16 2010 @@ -88,15 +88,15 @@ public class BackgroundServletStarterFil + sresp.getClass().getName()); } final HttpServletRequest request = (HttpServletRequest) sreq; - final SlingHttpServletRequest slingRequest = (request instanceof SlingHttpServletRequest ? (SlingHttpServletRequest) request - : null); + final SlingHttpServletRequest slingRequest = + (request instanceof SlingHttpServletRequest ? (SlingHttpServletRequest) request : null); final HttpServletResponse response = (HttpServletResponse) sresp; final String bgParam = sreq.getParameter(BG_PARAM); if (Boolean.valueOf(bgParam)) { try { final BackgroundRequestExecutionJob job = new BackgroundRequestExecutionJob( slingServlet, resourceResolverFactory, jobStorage, - request, response, PARAM_TO_REMOVE); + slingRequest, response, PARAM_TO_REMOVE); log.debug("{} parameter true, running request in the background ({})", BG_PARAM, job); if (slingRequest != null) { Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ExecutionEngineImpl.java Tue Jul 27 14:41:16 2010 @@ -18,6 +18,7 @@ */ package org.apache.sling.bgservlets.impl; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -48,7 +49,7 @@ public class ExecutionEngineImpl impleme private final Logger log = LoggerFactory.getLogger(getClass()); private Executor executor; - private final Map jobs = new HashMap(); + private final Map jobs = Collections.synchronizedMap(new HashMap()); private class RunnableWrapper implements Runnable { private final Runnable inputJob; @@ -70,7 +71,9 @@ public class ExecutionEngineImpl impleme inputJob.run(); } finally { if (jobStatus != null) { + log.debug("Job is done, cleaning up {}", jobStatus.getPath()); jobStatus.requestStateChange(JobStatus.State.DONE); + jobs.remove(jobStatus.getPath()); } } log.info("Done running job {}", inputJob); @@ -126,7 +129,6 @@ public class ExecutionEngineImpl impleme final RunnableWrapper w = new RunnableWrapper(inputJob); if (w.getJobStatus() != null) { w.getJobStatus().requestStateChange(JobStatus.State.QUEUED); - // TODO when to cleanup? jobs.put(w.getJobStatus().getPath(), w.getJobStatus()); } executor.execute(w); Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java?rev=979727&view=auto ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java (added) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java Tue Jul 27 14:41:16 2010 @@ -0,0 +1,123 @@ +/* + * 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.apache.sling.bgservlets.impl; + +import java.util.Iterator; + +import javax.jcr.Item; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.servlet.http.HttpServletRequest; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.bgservlets.ExecutionEngine; +import org.apache.sling.bgservlets.JobConsole; +import org.apache.sling.bgservlets.JobStatus; +import org.apache.sling.bgservlets.impl.storage.JobStorageException; +import org.apache.sling.bgservlets.impl.storage.NodeJobStatusFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** JobConsole implementation */ +@Component +@Service +public class JobConsoleImpl implements JobConsole { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + public static final String JOB_QUERY = "select * from sling:bgJobData order by jcr:created desc"; + + @Reference + private ExecutionEngine executionEngine; + + @Reference + private NodeJobStatusFactory jobStatusFactory; + + public Iterator getJobStatus(Session session, boolean activeOnly) { + if(activeOnly) { + log.debug("activeOnly is set, getting jobs from ExecutionEngine"); + return getEngineJobs(); + } else { + log.debug("activeOnly is set, getting jobs from repository query"); + try { + return getStoredJobs(session); + } catch(RepositoryException re) { + throw new JobStorageException("RepositoryException in getJobStatus(query)", re); + } + } + } + + public JobStatus getJobStatus(Session session, String path) { + // Try ExecutionEngine first, persistent storage if not found + JobStatus result = executionEngine.getJobStatus(path); + if(result == null) { + try { + if(session.itemExists(path)) { + final Item i = session.getItem(path); + if(i.isNode()) { + result = jobStatusFactory.getJobStatus((Node)i); + } + } + } catch(RepositoryException re) { + throw new JobStorageException("RepositoryException in getJobStatus(path)", re); + } + } + return result; + } + + private Iterator getEngineJobs() { + return executionEngine.getMatchingJobStatus(null); + } + + private Iterator getStoredJobs(Session s) throws RepositoryException { + final Query q = s.getWorkspace().getQueryManager().createQuery(JOB_QUERY, Query.SQL); + final NodeIterator it = q.execute().getNodes(); + return new Iterator() { + + public boolean hasNext() { + return it.hasNext(); + } + + public JobStatus next() { + try { + return jobStatusFactory.getJobStatus(it.nextNode()); + } catch(RepositoryException re) { + throw new JobStorageException("RepositoryException in next()", re); + } + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + } + + public String getJobStatusPagePath(HttpServletRequest request, JobStatus jobStatus, String extension) { + if(!extension.startsWith(".")) { + extension = "." + extension; + } + return request.getContextPath() + jobStatus.getPath() + extension; + } +} Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/JobConsoleImpl.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/servlets/JobInfoServlet.java Tue Jul 27 14:41:16 2010 @@ -23,16 +23,20 @@ import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; +import javax.jcr.Node; import javax.servlet.ServletException; import javax.servlet.http.HttpServletResponse; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Property; +import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.SlingSafeMethodsServlet; import org.apache.sling.bgservlets.BackgroundServletConstants; +import org.apache.sling.bgservlets.JobData; +import org.apache.sling.bgservlets.JobStorage; import org.apache.sling.commons.json.JSONException; import org.apache.sling.commons.json.io.JSONWriter; @@ -56,13 +60,16 @@ public class JobInfoServlet extends Slin renderers.put("json", new JsonRenderer()); } + @Reference + private JobStorage jobStorage; + static interface Renderer { void render(PrintWriter pw, String streamPath, String streamResource) throws IOException; } private static class TextRenderer implements Renderer { public void render(PrintWriter pw, String streamPath, String streamResource) { - pw.println("Background execution scheduled, job output available at "); + pw.println("Background execution: job output available at "); pw.println(streamPath); } } @@ -72,9 +79,9 @@ public class JobInfoServlet extends Slin pw.println("Background job"); pw.println(""); pw.println(""); - pw.println("

Background job scheduled

"); + pw.println("

Background job information

"); pw.println("Job output available at"); - pw.println("" + streamResource + "."); + pw.println("" + streamResource + ""); pw.println(""); } } @@ -85,7 +92,7 @@ public class JobInfoServlet extends Slin try { w.object(); w.key("info"); - w.value("Background job scheduled"); + w.value("Background job information"); w.key("jobStreamPath"); w.value(streamPath); w.endObject(); @@ -99,7 +106,14 @@ public class JobInfoServlet extends Slin protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException { - final String streamResource = request.getResource().getPath() + "/stream." + request.getRequestPathInfo().getExtension(); + final JobData j = jobStorage.getJobData(request.getResource().adaptTo(Node.class)); + String jobExt = j.getProperty(JobData.PROP_EXTENSION); + if(jobExt == null || jobExt.length() == 0) { + jobExt = ""; + } else { + jobExt = "." + jobExt; + } + final String streamResource = request.getResource().getPath() + "/stream" + jobExt; final String streamPath = request.getContextPath() + streamResource; final String ext = request.getRequestPathInfo().getExtension(); Renderer r = renderers.get(ext); Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobDataImpl.java Tue Jul 27 14:41:16 2010 @@ -75,4 +75,25 @@ class JobDataImpl implements JobData { public String getPath() { return path; } + + public String getProperty(String name) { + String result = null; + try { + if(node.hasProperty(name)) { + result = node.getProperty(name).getValue().getString(); + } + } catch(RepositoryException re) { + throw new JobStorageException("RepositoryException in getProperty", re); + } + return result; + } + + public void setProperty(String name, String value) { + try { + node.setProperty(name, value); + node.save(); + } catch(RepositoryException re) { + throw new JobStorageException("RepositoryException in setProperty", re); + } + } } Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobStorageException.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobStorageException.java?rev=979727&r1=979726&r2=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobStorageException.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/JobStorageException.java Tue Jul 27 14:41:16 2010 @@ -20,11 +20,11 @@ package org.apache.sling.bgservlets.impl import org.apache.sling.api.SlingException; -/** Exception thrown by this package. Unchecked, meant +/** Exception related to job storage. Unchecked, meant * for non-recoverable problems. */ @SuppressWarnings("serial") -class JobStorageException extends SlingException { +public class JobStorageException extends SlingException { public JobStorageException(String reason) { super(reason); } Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java?rev=979727&view=auto ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java (added) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java Tue Jul 27 14:41:16 2010 @@ -0,0 +1,29 @@ +/* + * 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.apache.sling.bgservlets.impl.storage; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.sling.bgservlets.JobStatus; + +/** Builds JobStatus objects out of Nodes */ +public interface NodeJobStatusFactory { + public JobStatus getJobStatus(Node n) throws RepositoryException; +} Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactory.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Added: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java?rev=979727&view=auto ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java (added) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java Tue Jul 27 14:41:16 2010 @@ -0,0 +1,84 @@ +/* + * 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.apache.sling.bgservlets.impl.storage; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.Service; +import org.apache.sling.bgservlets.ExecutionEngine; +import org.apache.sling.bgservlets.JobStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** JobStatus that gets its data from a Node created + * by the JobDataImpl class. The state of such a job + * can be changed only if the job is currently active + * in the ExecutionEngine. */ +@Component +@Service +public class NodeJobStatusFactoryImpl implements NodeJobStatusFactory { + + private Logger log = LoggerFactory.getLogger(getClass()); + + @Reference + private ExecutionEngine executionEngine; + + private class NodeJobStatus implements JobStatus { + private final String path; + + public NodeJobStatus(Node n) throws RepositoryException { + path = n.getPath(); + } + + public String getPath() { + return path; + } + + public State getState() { + final JobStatus j = getActiveJob(); + if(j == null) { + log.debug("Job {} not found by getActiveJob, assuming status==DONE", path); + return State.DONE; + } + return j.getState(); + } + + public void requestStateChange(State s) { + final JobStatus j = getActiveJob(); + if(j == null) { + throw new JobStorageException("Job is not active, cannot change state, path=" + path); + } + j.requestStateChange(s); + } + + private JobStatus getActiveJob() { + if(executionEngine != null) { + return executionEngine.getJobStatus(path); + } + return null; + } + }; + + public JobStatus getJobStatus(Node n) throws RepositoryException { + return new NodeJobStatus(n); + } +} Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/storage/NodeJobStatusFactoryImpl.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Copied: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/JobConsolePlugin.java (from r979652, sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java) URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/JobConsolePlugin.java?p2=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/JobConsolePlugin.java&p1=sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java&r1=979652&r2=979727&rev=979727&view=diff ============================================================================== --- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java (original) +++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/JobConsolePlugin.java Tue Jul 27 14:41:16 2010 @@ -24,14 +24,17 @@ import java.util.Dictionary; import java.util.Hashtable; import java.util.Iterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.felix.webconsole.AbstractWebConsolePlugin; import org.apache.felix.webconsole.WebConsoleConstants; -import org.apache.sling.bgservlets.ExecutionEngine; +import org.apache.sling.bgservlets.JobConsole; import org.apache.sling.bgservlets.JobStatus; +import org.apache.sling.jcr.api.SlingRepository; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; @@ -40,12 +43,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** Felix OSGi console plugin for the ExecutionEngine */ -public class ExecutionEngineConsolePlugin { - private static final Logger log = LoggerFactory - .getLogger(ExecutionEngineConsolePlugin.class); +public class JobConsolePlugin { + private static final Logger log = LoggerFactory.getLogger(JobConsolePlugin.class); private static Plugin plugin; public static final String LABEL = "bgservlets"; public static final String TITLE = "Background Servlets & Jobs"; + public static final String STATUS_EXTENSION = "html"; public static void initPlugin(BundleContext context) { if (plugin == null) { @@ -70,26 +73,26 @@ public class ExecutionEngineConsolePlugi @SuppressWarnings("serial") public static final class Plugin extends AbstractWebConsolePlugin { private ServiceRegistration serviceRegistration; - private ServiceTracker executionEngineTracker; + private ServiceTracker jobConsoleTracker; + private ServiceTracker repositoryTracker; public void activate(BundleContext ctx) { super.activate(ctx); - executionEngineTracker = new ServiceTracker(ctx, - ExecutionEngine.class.getName(), null); - executionEngineTracker.open(); + jobConsoleTracker = new ServiceTracker(ctx, JobConsole.class.getName(), null); + jobConsoleTracker.open(); + repositoryTracker = new ServiceTracker(ctx, SlingRepository.class.getName(), null); + repositoryTracker.open(); Dictionary props = new Hashtable(); - props - .put(Constants.SERVICE_DESCRIPTION, - "Web Console Plugin to display Background servlets and ExecutionEngine status"); + props.put(Constants.SERVICE_DESCRIPTION, + "Web Console Plugin to display Background servlets and ExecutionEngine status"); props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation"); props.put(Constants.SERVICE_PID, getClass().getName()); props.put(WebConsoleConstants.PLUGIN_LABEL, LABEL); - serviceRegistration = ctx.registerService( - WebConsoleConstants.SERVICE_NAME, this, props); + serviceRegistration = ctx.registerService(WebConsoleConstants.SERVICE_NAME, this, props); } public void deactivate() { @@ -97,9 +100,13 @@ public class ExecutionEngineConsolePlugi serviceRegistration.unregister(); serviceRegistration = null; } - if (executionEngineTracker != null) { - executionEngineTracker.close(); - executionEngineTracker = null; + if (jobConsoleTracker != null) { + jobConsoleTracker.close(); + jobConsoleTracker = null; + } + if (repositoryTracker != null) { + repositoryTracker.close(); + repositoryTracker = null; } super.deactivate(); } @@ -118,17 +125,37 @@ public class ExecutionEngineConsolePlugi protected void renderContent(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { final PrintWriter pw = res.getWriter(); - final ExecutionEngine ee = (ExecutionEngine) executionEngineTracker - .getService(); - if (ee == null) { - pw.println("No ExecutionEngine service found"); + + // Access required services + final JobConsole console = (JobConsole)jobConsoleTracker.getService(); + if (console == null) { + pw.println("No JobConsole service found"); return; } - + final SlingRepository repository = (SlingRepository)repositoryTracker.getService(); + if(repository == null) { + pw.println("No SlingRepository service found"); + return; + } + Session s = null; + try { + s = repository.loginAdministrative(repository.getDefaultWorkspace()); + processCommands(req, pw, s, console); + renderJobs(req, pw, s, console); + } catch(RepositoryException re) { + throw new ServletException("RepositoryExceptio in renderContent()", re); + } finally { + if(s != null) { + s.logout(); + } + } + } + + private void processCommands(HttpServletRequest req, PrintWriter pw, Session s, JobConsole console) { // TODO should use POST final String jobPath = req.getParameter("jobPath"); if (jobPath != null) { - final JobStatus job = ee.getJobStatus(jobPath); + final JobStatus job = console.getJobStatus(s, jobPath); if (job != null) { final String action = req.getParameter("action"); if ("suspend".equals(action)) { @@ -140,12 +167,13 @@ public class ExecutionEngineConsolePlugi } } } + } + + private void renderJobs(HttpServletRequest req, PrintWriter pw, Session s, JobConsole console) { + pw.println("TODO: action buttons look bad
"); + pw.println("TODO: options for max. number of jobs displayed + active only
"); - pw.println("TODO: provide a way to cleanup old jobs
"); - pw.println("TODO: optionally list active jobs only
"); - - pw - .println(""); + pw.println("
"); pw.println(""); pw.println(""); pw.println(""); @@ -155,19 +183,28 @@ public class ExecutionEngineConsolePlugi pw.println(""); pw.println(""); - final Iterator it = ee.getMatchingJobStatus(null); + final int maxJobsDisplayed = 100; + boolean truncated = false; + final boolean activeOnly = false; + final Iterator it = console.getJobStatus(s, activeOnly); int count = 0; while (it.hasNext()) { - renderJobStatus(pw, it.next()); + renderJobStatus(req, pw, console, it.next()); count++; + if(count > maxJobsDisplayed) { + truncated = true; + break; + } } pw.println(""); pw.println("
Controls
"); pw.println("Total " + count + " jobs.
"); + if(truncated) { + pw.println("(List truncated after " + maxJobsDisplayed + " jobs)
"); + } } - private void renderJobStatus(PrintWriter pw, JobStatus job) { - // TODO should use POST + private void renderJobStatus(HttpServletRequest request, PrintWriter pw, JobConsole console, JobStatus job) { pw.println(""); pw.println("
"); final String[] actions = { "suspend", "resume", "stop" }; @@ -181,8 +218,11 @@ public class ExecutionEngineConsolePlugi pw.println(""); pw.println(job.getState()); pw.println(""); - pw.println(""); - pw.println(job.getPath()); + pw.print("\n"); + pw.print(job.getPath()); + pw.println(""); pw.println(""); pw.println(""); }