| 
01 /*02  * Copyright 2008-2015 the original author or authors.
 03  *
 04  * Licensed under the Apache License, Version 2.0 (the "License");
 05  * you may not use this file except in compliance with the License.
 06  * You may obtain a copy of the License at
 07  *
 08  *     http://www.apache.org/licenses/LICENSE-2.0
 09  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 package griffon.util;
 17
 18 import org.slf4j.Logger;
 19 import org.slf4j.LoggerFactory;
 20
 21 import javax.annotation.Nonnull;
 22 import java.io.IOException;
 23 import java.net.URL;
 24 import java.util.Enumeration;
 25 import java.util.Scanner;
 26
 27 import static griffon.core.GriffonExceptionHandler.sanitize;
 28 import static griffon.util.GriffonNameUtils.isBlank;
 29 import static griffon.util.GriffonNameUtils.requireNonBlank;
 30 import static java.util.Objects.requireNonNull;
 31
 32 /**
 33  * @author Andres Almiray
 34  * @since 2.0.0
 35  */
 36 public class ServiceLoaderUtils {
 37     private static final Logger LOG = LoggerFactory.getLogger(ServiceLoaderUtils.class);
 38
 39     private ServiceLoaderUtils() {
 40
 41     }
 42
 43     public static interface LineProcessor {
 44         void process(@Nonnull ClassLoader classLoader, @Nonnull Class<?> type, @Nonnull String line);
 45     }
 46
 47     public static boolean load(@Nonnull ClassLoader classLoader, @Nonnull String path, @Nonnull Class<?> type, @Nonnull LineProcessor processor) {
 48         requireNonNull(classLoader, "Argument 'classLoader' must not be null");
 49         requireNonBlank(path, "Argument 'path' must not be blank");
 50         requireNonNull(type, "Argument 'type' must not be null");
 51         requireNonNull(processor, "Argument 'processor' must not be null");
 52         // "The name of a resource is a /-separated path name that identifies the resource."
 53         String normalizedPath = path.endsWith("/") ? path : path + "/";
 54
 55         Enumeration<URL> urls;
 56
 57         try {
 58             urls = classLoader.getResources(normalizedPath + type.getName());
 59         } catch (IOException ioe) {
 60             LOG.error(ioe.getClass().getName() + " error loading resources of type \"" + type.getName() + "\" from \"" + normalizedPath + "\".");
 61             return false;
 62         }
 63
 64         if (urls == null) return false;
 65
 66         while (urls.hasMoreElements()) {
 67             URL url = urls.nextElement();
 68             LOG.debug("Reading {} definitions from {}", type.getName(), url);
 69
 70             try (Scanner scanner = new Scanner(url.openStream())) {
 71                 while (scanner.hasNextLine()) {
 72                     String line = scanner.nextLine();
 73                     if (line.startsWith("#") || isBlank(line)) continue;
 74                     processor.process(classLoader, type, line);
 75                 }
 76             } catch (IOException e) {
 77                 LOG.warn("Could not load " + type.getName() + " definitions from " + url, sanitize(e));
 78             }
 79         }
 80
 81         return true;
 82     }
 83 }
 |