You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by dk...@apache.org on 2019/01/24 04:35:41 UTC

[sling-org-apache-sling-app-cms] branch master updated: Adding the ability to remove a job

This is an automated email from the ASF dual-hosted git repository.

dklco pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-app-cms.git


The following commit(s) were added to refs/heads/master by this push:
     new e0ce705  Adding the ability to remove a job
e0ce705 is described below

commit e0ce705e3884e2b0e4241be811a038e962b77019
Author: Dan Klco <dk...@apache.org>
AuthorDate: Wed Jan 23 22:35:35 2019 -0600

    Adding the ability to remove a job
---
 api/pom.xml                                        |   4 +
 .../java/org/apache/sling/cms/CMSJobManager.java   |   7 ++
 .../apache/sling/cms/ConfigurableJobExecutor.java  |  63 +++++++++-
 .../internal/jobs/FileMetadataExtractorJob.java    | 131 ++++++++++-----------
 .../cms/core/internal/jobs/RemoveJobServlet.java   |  66 +++++++++++
 .../internal/listeners/FileMetadataExtractor.java  |  28 +++--
 .../core/internal/models/CMSJobManagerImpl.java    |   5 +
 .../components/editor/fields/param/edit.json       |   5 +
 .../components/editor/fields/param/param.jsp       |  20 ++++
 .../libs/sling-cms/components/jobs/list/list.jsp   |   9 ++
 .../libs/sling-cms/content/jobs/delete.json        |  33 ++++++
 .../resources/jcr_root/libs/sling-cms/i18n.json    |  10 ++
 12 files changed, 291 insertions(+), 90 deletions(-)

diff --git a/api/pom.xml b/api/pom.xml
index 9c4beed..9cd4af5 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -104,5 +104,9 @@
             <groupId>org.jsoup</groupId>
             <artifactId>jsoup</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/api/src/main/java/org/apache/sling/cms/CMSJobManager.java b/api/src/main/java/org/apache/sling/cms/CMSJobManager.java
index 1c6ac49..0833580 100644
--- a/api/src/main/java/org/apache/sling/cms/CMSJobManager.java
+++ b/api/src/main/java/org/apache/sling/cms/CMSJobManager.java
@@ -54,4 +54,11 @@ public interface CMSJobManager {
      */
     Job startJob();
 
+    /**
+     * Deletes the specified job.
+     * 
+     * @param id the id of the job to delete
+     */
+    void deleteJob(String id);
+
 }
diff --git a/api/src/main/java/org/apache/sling/cms/ConfigurableJobExecutor.java b/api/src/main/java/org/apache/sling/cms/ConfigurableJobExecutor.java
index 6682bc1..0804a2f 100644
--- a/api/src/main/java/org/apache/sling/cms/ConfigurableJobExecutor.java
+++ b/api/src/main/java/org/apache/sling/cms/ConfigurableJobExecutor.java
@@ -16,27 +16,60 @@
  */
 package org.apache.sling.cms;
 
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.event.jobs.Job;
+import org.apache.sling.event.jobs.consumer.JobExecutionContext;
+import org.apache.sling.event.jobs.consumer.JobExecutionResult;
 import org.apache.sling.event.jobs.consumer.JobExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * A Configurable Job Executor is a Sling Job which can be manually triggered
- * by Sling CMS users.
+ * A Configurable Job Executor is a Sling Job which can be manually triggered by
+ * Sling CMS users.
  */
-public interface ConfigurableJobExecutor extends JobExecutor {
+public abstract class ConfigurableJobExecutor implements JobExecutor {
+
+    private static final Logger log = LoggerFactory.getLogger(ConfigurableJobExecutor.class);
+
+    private static final String USER_ID_KEY = "_userId";
+
+    /**
+     * A method for Configurable Job Executors to extend.
+     * 
+     * @param job      the job configuration
+     * @param context  the job context
+     * @param resolver an impersonated resource resolver for the user
+     * @return the result of executing the job
+     */
+    public abstract JobExecutionResult doProcess(Job job, JobExecutionContext context, ResourceResolver resolver);
 
     /**
      * Get the path to the resource to configure a job invocation.
      * 
      * @return the path to the resource to configure a resource invocation
      */
-    String getConfigurationPath();
+    public abstract String getConfigurationPath();
+
+    /**
+     * A method to get the resource resolver factory, should be injected as a
+     * service.
+     * 
+     * @return the resource resolver factory
+     */
+    public abstract ResourceResolverFactory getResolverFactory();
 
     /**
      * Get the i18n key for this job.
      * 
      * @return the job title i18n key
      */
-    String getTitleKey();
+    public abstract String getTitleKey();
 
     /**
      * Gets the topic of the job. This will be used as the Sling Job Topic for
@@ -44,5 +77,23 @@ public interface ConfigurableJobExecutor extends JobExecutor {
      * 
      * @return the Sling Job Topic
      */
-    String getTopic();
+    public abstract String getTopic();
+
+    @SuppressWarnings("deprecation")
+    public final JobExecutionResult process(Job job, JobExecutionContext context) {
+        ResourceResolver resolver = null;
+        try {
+            Map<String, Object> authenticationInfo = new HashMap<>();
+            authenticationInfo.put(ResourceResolverFactory.USER_IMPERSONATION, job.getProperty(USER_ID_KEY));
+            resolver = getResolverFactory().getAdministrativeResourceResolver(authenticationInfo);
+            return doProcess(job, context, resolver);
+        } catch (LoginException e) {
+            log.warn("Failed to login", e);
+            return context.result().failed();
+        } finally {
+            if (resolver != null) {
+                resolver.close();
+            }
+        }
+    }
 }
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/jobs/FileMetadataExtractorJob.java b/core/src/main/java/org/apache/sling/cms/core/internal/jobs/FileMetadataExtractorJob.java
index dcd61ec..b09d0ce 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/jobs/FileMetadataExtractorJob.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/jobs/FileMetadataExtractorJob.java
@@ -17,12 +17,9 @@
 package org.apache.sling.cms.core.internal.jobs;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 import org.apache.sling.api.SlingConstants;
-import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
@@ -46,20 +43,66 @@ import org.slf4j.LoggerFactory;
  */
 @Component(service = { JobExecutor.class, ConfigurableJobExecutor.class }, property = {
         JobConsumer.PROPERTY_TOPICS + "=" + FileMetadataExtractorJob.TOPIC })
-public class FileMetadataExtractorJob implements ConfigurableJobExecutor {
+public class FileMetadataExtractorJob extends ConfigurableJobExecutor {
 
     public static final Logger log = LoggerFactory.getLogger(FileMetadataExtractorJob.class);
 
-    public static final String TOPIC = "cmsjob/org/apache/sling/cms/file/ExtractMetadata";
-
     public static final String PN_RECURSIVE = "recursive";
 
+    public static final String TOPIC = "cmsjob/org/apache/sling/cms/file/ExtractMetadata";
+
     @Reference
     private FileMetadataExtractor extractor;
 
     @Reference
     private ResourceResolverFactory factory;
 
+    private void collectFiles(Resource root, List<File> files) {
+        for (Resource child : root.getChildren()) {
+            if (CMSConstants.NT_FILE.equals(child.getResourceType())) {
+                files.add(child.adaptTo(File.class));
+            } else {
+                collectFiles(child, files);
+            }
+        }
+    }
+
+    @Override
+    public JobExecutionResult doProcess(Job job, JobExecutionContext context, ResourceResolver resolver) {
+        String path = job.getProperty(SlingConstants.PROPERTY_PATH, "");
+
+        Resource root = resolver.getResource(path);
+        if (root != null) {
+            List<File> files = new ArrayList<>();
+            if (CMSConstants.NT_FILE.equals(root.getResourceType())) {
+                files.add(root.adaptTo(File.class));
+            } else {
+                collectFiles(root, files);
+            }
+            context.log("Found {0} files to extract metadata", files.size());
+
+            context.initProgress(files.size(), -1);
+
+            int processed = 1;
+            for (File file : files) {
+                try {
+                    extractor.extractMetadata(file);
+                    context.incrementProgressCount(processed++);
+                    context.log("Extracted metadata for {0}", file.getPath());
+                } catch (Throwable t) {
+                    context.log("Failed to extract matadata for {0}", file.getPath());
+                    context.incrementProgressCount(processed++);
+                    context.log("Exception {0}", t.getMessage());
+                    log.warn("Failed to extract metadata for " + file.getPath(), t);
+                }
+            }
+
+            return context.result().message("Metadata Extracted").succeeded();
+        } else {
+            return context.result().message("No file found at " + path).failed();
+        }
+    }
+
     /*
      * (non-Javadoc)
      * 
@@ -70,6 +113,16 @@ public class FileMetadataExtractorJob implements ConfigurableJobExecutor {
         return "/mnt/overlay/sling-cms/content/jobs/filemetadataextractor";
     }
 
+    @Override
+    public ResourceResolverFactory getResolverFactory() {
+        return this.factory;
+    }
+
+    @Override
+    public String getTitleKey() {
+        return "slingcms.filemetadata.title";
+    }
+
     /*
      * (non-Javadoc)
      * 
@@ -80,70 +133,4 @@ public class FileMetadataExtractorJob implements ConfigurableJobExecutor {
         return TOPIC;
     }
 
-    @Override
-    public JobExecutionResult process(Job job, JobExecutionContext context) {
-        String path = job.getProperty(SlingConstants.PROPERTY_PATH, "");
-
-        ResourceResolver resolver = null;
-
-        try {
-            Map<String, Object> serviceParams = new HashMap<>();
-            serviceParams.put(ResourceResolverFactory.SUBSERVICE, "sling-cms-metadata");
-            resolver = factory.getServiceResourceResolver(serviceParams);
-
-            Resource root = resolver.getResource(path);
-            if (root != null) {
-                List<File> files = new ArrayList<>();
-                if (CMSConstants.NT_FILE.equals(root.getResourceType())) {
-                    files.add(root.adaptTo(File.class));
-                } else {
-                    collectFiles(root, files);
-                }
-                context.log("Found {0} files to extract metadata", files.size());
-
-                context.initProgress(files.size(), -1);
-
-                int processed = 1;
-                for (File file : files) {
-                    try {
-                        extractor.extractMetadata(file);
-                        context.incrementProgressCount(processed++);
-                        context.log("Extracted metadata for {0}", file.getPath());
-                    } catch (Throwable t) {
-                        context.log("Failed to extract matadata for {0}", file.getPath());
-                        context.incrementProgressCount(processed++);
-                        context.log("Exception {0}", t.getMessage());
-                        log.warn("Failed to extract metadata for " + file.getPath(), t);
-                    }
-                }
-
-                return context.result().message("Metadata Extracted").succeeded();
-            } else {
-                return context.result().message("No file found at " + path).failed();
-            }
-        } catch (LoginException e) {
-            log.warn("Unable to get service user", e);
-            return context.result().message("Unable to get service user").failed();
-        } finally {
-            if (resolver != null) {
-                resolver.close();
-            }
-        }
-    }
-
-    private void collectFiles(Resource root, List<File> files) {
-        for (Resource child : root.getChildren()) {
-            if (CMSConstants.NT_FILE.equals(child.getResourceType())) {
-                files.add(child.adaptTo(File.class));
-            } else {
-                collectFiles(child, files);
-            }
-        }
-    }
-
-    @Override
-    public String getTitleKey() {
-        return "slingcms.filemetadata.title";
-    }
-
 }
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/jobs/RemoveJobServlet.java b/core/src/main/java/org/apache/sling/cms/core/internal/jobs/RemoveJobServlet.java
new file mode 100644
index 0000000..2012f8a
--- /dev/null
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/jobs/RemoveJobServlet.java
@@ -0,0 +1,66 @@
+
+/*
+ * 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.cms.core.internal.jobs;
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.servlets.HttpConstants;
+import org.apache.sling.api.servlets.SlingAllMethodsServlet;
+import org.apache.sling.cms.CMSJobManager;
+import org.apache.sling.cms.i18n.I18NDictionary;
+import org.apache.sling.cms.i18n.I18NProvider;
+import org.apache.sling.event.jobs.JobManager;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(service = Servlet.class, property = { "sling.servlet.paths=/bin/cms/removejob",
+        "sling.servlet.methods=" + HttpConstants.METHOD_POST })
+public class RemoveJobServlet extends SlingAllMethodsServlet {
+
+    private static final long serialVersionUID = -8206750437666627792L;
+
+    @Reference
+    private transient I18NProvider provider;
+
+    @Reference
+    private transient JobManager jobManager;
+
+    @Override
+    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
+            throws ServletException, IOException {
+
+        I18NDictionary dictionary = provider.getDictionary(request);
+        String message = null;
+        CMSJobManager jobMgr = request.adaptTo(CMSJobManager.class);
+        String id = request.getParameter("id");
+        if (jobMgr != null && id != null) {
+            jobMgr.deleteJob(id);
+            message = dictionary.get("slingcms.jobs.jobremoved");
+        } else {
+            message = dictionary.get("slingcms.jobs.badrequest");
+            response.sendError(400, message);
+        }
+        response.setContentType("application/json");
+        response.getWriter().write("{\"title\":\"" + message + "\"}");
+    }
+}
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractor.java b/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractor.java
index 5718ff2..d2b94a6 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractor.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractor.java
@@ -86,19 +86,23 @@ public class FileMetadataExtractor implements ResourceChangeListener, ExternalRe
         } else {
             properties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
         }
-        Parser parser = new AutoDetectParser();
-        BodyContentHandler handler = new BodyContentHandler();
-        Metadata md = new Metadata();
-        ParseContext context = new ParseContext();
-        parser.parse(is, handler, md, context);
-        for (String name : md.names()) {
-            updateProperty(properties, name, md);
-        }
-        if (metadata == null) {
-            resolver.create(content, NN_METADATA, properties);
+        if (properties != null) {
+            Parser parser = new AutoDetectParser();
+            BodyContentHandler handler = new BodyContentHandler();
+            Metadata md = new Metadata();
+            ParseContext context = new ParseContext();
+            parser.parse(is, handler, md, context);
+            for (String name : md.names()) {
+                updateProperty(properties, name, md);
+            }
+            if (metadata == null) {
+                resolver.create(content, NN_METADATA, properties);
+            }
+            resolver.commit();
+            log.info("Metadata extracted from {}", resource.getPath());
+        } else {
+            log.warn("Failed to update metadata for {}", resource.getPath());
         }
-        resolver.commit();
-        log.info("Metadata extracted from {}", resource.getPath());
 
     }
 
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/models/CMSJobManagerImpl.java b/core/src/main/java/org/apache/sling/cms/core/internal/models/CMSJobManagerImpl.java
index 40821de..d7a46f0 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/models/CMSJobManagerImpl.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/models/CMSJobManagerImpl.java
@@ -67,6 +67,11 @@ public class CMSJobManagerImpl implements CMSJobManager {
     }
 
     @Override
+    public void deleteJob(String id) {
+        jobManager.removeJobById(id);
+    }
+
+    @Override
     public Collection<ConfigurableJobExecutor> getAvailableJobs() {
         return cmsJobManager.getJobs();
     }
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/edit.json b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/edit.json
new file mode 100644
index 0000000..ae6c823
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/edit.json
@@ -0,0 +1,5 @@
+{
+    "jcr:primaryType": "nt:unstructured",
+    "sling:resourceType": "sling-cms/components/editor/slingform",
+    "button": "No Need to Edit"
+}
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/param.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/param.jsp
new file mode 100644
index 0000000..9342684
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/editor/fields/param/param.jsp
@@ -0,0 +1,20 @@
+<%-- /*
+ * 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.
+ */ --%>
+<%@include file="/libs/sling-cms/global.jsp"%>
+<input type="hidden" name="${properties.name}" value="${sling:encode(param[properties.param],'HTML_ATTR')}" />
\ No newline at end of file
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/components/jobs/list/list.jsp b/ui/src/main/resources/jcr_root/libs/sling-cms/components/jobs/list/list.jsp
index a83d646..140baa4 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/components/jobs/list/list.jsp
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/components/jobs/list/list.jsp
@@ -36,6 +36,8 @@
                 <th>
                     <fmt:message key="slingcms.state" />
                 </th>
+                <th class="is-hidden">
+                </th>
             </tr>
         </thead>
         <tbody>
@@ -64,7 +66,14 @@
                     <td>
                         <sling:encode value="${job.jobState}" mode="HTML" />
                     </td>
+                    <td class="is-hidden cell-actions">
+                        <a class="button Fetch-Modal" data-title="<fmt:message key="slingcms.jobs.remove" />" data-path=".Main-Content form" href="/cms/jobs/delete.html/bin/cms/removejob?id=${job.id}" title="<fmt:message key="slingcms.jobs.remove" />">
+                            <span class="jam jam-trash">
+                            </span>
+                        </a>
+                    </td>
                 </tr>
+                
                 <c:set var="count" value="${count + 1}" />
             </c:forEach>
         </tbody>
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/content/jobs/delete.json b/ui/src/main/resources/jcr_root/libs/sling-cms/content/jobs/delete.json
new file mode 100644
index 0000000..a4adcc0
--- /dev/null
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/content/jobs/delete.json
@@ -0,0 +1,33 @@
+{
+    "jcr:primaryType": "sling:Page",
+    "jcr:content": {
+        "sling:resourceType": "sling-cms/components/pages/modal",
+        "jcr:title": "Remove Job",
+        "jcr:primaryType": "nt:unstructured",
+        "container": {
+            "jcr:primaryType": "nt:unstructured",
+            "sling:resourceType": "sling-cms/components/general/container",
+            "slingform": {
+                "jcr:primaryType": "nt:unstructured",
+                "sling:resourceType": "sling-cms/components/editor/slingform",
+                "button": "Delete",
+                "callback": "handledelete",
+                "fields": {
+                    "jcr:primaryType": "nt:unstructured",
+                    "sling:resourceType": "sling-cms/components/general/container",
+                    "param": {
+                        "jcr:primaryType": "nt:unstructured",
+                        "sling:resourceType": "sling-cms/components/editor/fields/param",
+                        "name": "id",
+                        "param":"id"
+                    },
+                    "path": {
+                        "jcr:primaryType": "nt:unstructured",
+                        "sling:resourceType": "sling-cms/components/general/richtext",
+                        "text": "<div class=\"field\">Do you want to delete this job?</div>"
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json
index e74c0d2..737c7ba 100644
--- a/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json
+++ b/ui/src/main/resources/jcr_root/libs/sling-cms/i18n.json
@@ -50,6 +50,11 @@
             "sling:message": "Invalid Job Request",
             "sling:key": "slingcms.jobs.badrequest"
         },
+        "slingcms-jobs-jobremoved": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Job Removed",
+            "sling:key": "slingcms.jobs.jobremoved"
+        },
         "slingcms-jobs-jobstarted": {
             "jcr:primaryType": "sling:MessageEntry",
             "sling:message": "Job Started",
@@ -75,6 +80,11 @@
             "sling:message": "Job Properties",
             "sling:key": "slingcms.jobs.properties"
         },
+        "slingcms-jobs-remove": {
+            "jcr:primaryType": "sling:MessageEntry",
+            "sling:message": "Remove Job",
+            "sling:key": "slingcms.jobs.remove"
+        },
         "slingcms-jobs-resultmessage": {
             "jcr:primaryType": "sling:MessageEntry",
             "sling:message": "Result Message",