Removing duplicate code from the File Metadata Extractor
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/FileMetadataExtractorImpl.java b/core/src/main/java/org/apache/sling/cms/core/internal/FileMetadataExtractorImpl.java
index fd0623f..5971438 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/FileMetadataExtractorImpl.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/FileMetadataExtractorImpl.java
@@ -111,7 +111,6 @@
                 log.warn("Content resource is null");
                 return;
             }
-
             Map<String, Object> properties = null;
             Resource metadata = content.getChild(CMSConstants.NN_METADATA);
             if (metadata != null) {
@@ -151,7 +150,6 @@
             putMetadata(properties, name, md);
         }
         return properties;
-
     }
 
     private void putMetadata(Map<String, Object> properties, String name, Metadata metadata) {
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
deleted file mode 100644
index d2b94a6..0000000
--- a/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractor.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.listeners;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Calendar;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.jackrabbit.JcrConstants;
-import org.apache.jackrabbit.util.Text;
-import org.apache.sling.api.resource.LoginException;
-import org.apache.sling.api.resource.ModifiableValueMap;
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.apache.sling.api.resource.ResourceResolverFactory;
-import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
-import org.apache.sling.api.resource.observation.ResourceChange;
-import org.apache.sling.api.resource.observation.ResourceChangeListener;
-import org.apache.sling.cms.File;
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.metadata.Metadata;
-import org.apache.tika.metadata.Property;
-import org.apache.tika.parser.AutoDetectParser;
-import org.apache.tika.parser.ParseContext;
-import org.apache.tika.parser.Parser;
-import org.apache.tika.sax.BodyContentHandler;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-
-/**
- * A Resource Change Listener which extracts the metadata from sling:Files when
- * they are uploaded.
- */
-@Component(service = { FileMetadataExtractor.class, ResourceChangeListener.class,
-        ExternalResourceChangeListener.class }, property = { ResourceChangeListener.CHANGES + "=ADDED",
-                ResourceChangeListener.PATHS + "=/content",
-                ResourceChangeListener.PATHS + "=/static" }, immediate = true)
-public class FileMetadataExtractor implements ResourceChangeListener, ExternalResourceChangeListener {
-
-    public static final String NN_METADATA = "metadata";
-    public static final String PN_X_PARSED_BY = "X-Parsed-By";
-
-    @Reference
-    private ResourceResolverFactory factory;
-
-    private static final Logger log = LoggerFactory.getLogger(FileMetadataExtractor.class);
-
-    public void extractMetadata(File file) throws IOException, SAXException, TikaException {
-        extractMetadata(file.getResource());
-    }
-
-    public void extractMetadata(Resource resource) throws IOException, SAXException, TikaException {
-
-        log.info("Extracting metadata from {}", resource.getPath());
-        ResourceResolver resolver = resource.getResourceResolver();
-        InputStream is = resource.adaptTo(InputStream.class);
-        Resource content = resource.getChild(JcrConstants.JCR_CONTENT);
-        if (content == null) {
-            log.warn("Content resource is null");
-            return;
-        }
-        Map<String, Object> properties = new HashMap<>();
-        Resource metadata = content.getChild(NN_METADATA);
-        if (metadata != null) {
-            properties = metadata.adaptTo(ModifiableValueMap.class);
-        } else {
-            properties.put(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_UNSTRUCTURED);
-        }
-        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());
-        }
-
-    }
-
-    private void updateProperty(Map<String, Object> properties, String name, Metadata metadata) {
-        log.trace("Updating property: {}", name);
-        String filtered = Text.escapeIllegalJcrChars(name);
-        Property property = Property.get(name);
-        if (property != null) {
-            if (metadata.isMultiValued(property)) {
-                properties.put(filtered, metadata.getValues(property));
-            } else if (metadata.getDate(property) != null) {
-                Calendar cal = Calendar.getInstance();
-                cal.setTime(metadata.getDate(property));
-                properties.put(filtered, cal);
-            } else if (metadata.getInt(property) != null) {
-                properties.put(filtered, metadata.getInt(property));
-            } else {
-                properties.put(filtered, metadata.get(property));
-            }
-        } else {
-            properties.put(filtered, metadata.get(name));
-        }
-    }
-
-    @Override
-    public void onChange(List<ResourceChange> changes) {
-        Map<String, Object> serviceParams = new HashMap<>();
-        serviceParams.put(ResourceResolverFactory.SUBSERVICE, "sling-cms-metadata");
-        ResourceResolver serviceResolver = null;
-        try {
-            serviceResolver = factory.getServiceResourceResolver(serviceParams);
-            for (ResourceChange rc : changes) {
-                Resource changed = serviceResolver.getResource(rc.getPath());
-                try {
-                    extractMetadata(changed);
-                } catch (Throwable t) {
-                    log.warn("Failed to extract metadata due to exception", t);
-                }
-            }
-        } catch (LoginException e) {
-            log.error("Exception getting service user", e);
-        } finally {
-            if (serviceResolver != null) {
-                serviceResolver.close();
-            }
-        }
-
-    }
-
-}
diff --git a/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractorListener.java b/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractorListener.java
index 008c81f..7d78b3b 100644
--- a/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractorListener.java
+++ b/core/src/main/java/org/apache/sling/cms/core/internal/listeners/FileMetadataExtractorListener.java
@@ -16,18 +16,17 @@
  */
 package org.apache.sling.cms.core.internal.listeners;
 
-import java.io.IOException;
-import java.util.HashMap;
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
-import java.util.Optional;
 
 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;
 import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
 import org.apache.sling.api.resource.observation.ResourceChange;
 import org.apache.sling.api.resource.observation.ResourceChangeListener;
+import org.apache.sling.cms.CMSConstants;
 import org.apache.sling.cms.File;
 import org.apache.sling.cms.FileMetadataExtractor;
 import org.osgi.service.component.annotations.Component;
@@ -45,45 +44,37 @@
                 ResourceChangeListener.PATHS + "=/static" }, immediate = true)
 public class FileMetadataExtractorListener implements ResourceChangeListener, ExternalResourceChangeListener {
 
+    private static final Logger log = LoggerFactory.getLogger(FileMetadataExtractorListener.class);
+
     @Reference
     private FileMetadataExtractor extractor;
 
     @Reference
     private ResourceResolverFactory factory;
 
-    private static final Logger log = LoggerFactory.getLogger(FileMetadataExtractorListener.class);
+    private void handleChange(Resource changed) {
+        if (CMSConstants.NT_FILE.equals(changed.getResourceType())) {
+            log.debug("Extracting metadata from changed resource: {}", changed);
+            try {
+                extractor.updateMetadata(changed.adaptTo(File.class), true);
+            } catch (Exception e) {
+                log.warn("Failed to extract metadata from change: {}", changed, e);
+            }
+        } else {
+            log.trace("Not extracting metadata from changed resource: {}", changed);
+        }
+    }
 
     @Override
     public void onChange(List<ResourceChange> changes) {
-        Map<String, Object> serviceParams = new HashMap<>();
-        serviceParams.put(ResourceResolverFactory.SUBSERVICE, "sling-cms-metadata");
-        ResourceResolver serviceResolver = null;
-        try {
-            serviceResolver = factory.getServiceResourceResolver(serviceParams);
+        try (ResourceResolver serviceResolver = factory.getServiceResourceResolver(
+                Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, "sling-cms-metadata"))) {
             for (ResourceChange rc : changes) {
-                handleChange(serviceResolver, rc);
+                Resource changed = serviceResolver.getResource(rc.getPath());
+                handleChange(changed);
             }
         } catch (LoginException e) {
             log.error("Exception getting service user", e);
-        } finally {
-            if (serviceResolver != null) {
-                serviceResolver.close();
-            }
-        }
-
-    }
-
-    private void handleChange(ResourceResolver serviceResolver, ResourceChange rc) {
-        File changed = Optional.ofNullable(serviceResolver.getResource(rc.getPath())).map(r -> r.adaptTo(File.class))
-                .orElse(null);
-        try {
-            if (changed != null) {
-                extractor.updateMetadata(changed);
-            } else {
-                log.warn("Failed to get File from: {}", rc.getPath());
-            }
-        } catch (IOException t) {
-            log.warn("Failed to extract metadata due to exception", t);
         }
     }