/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.core.common.osgi; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.net.URL; import java.nio.charset.Charset; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.Properties; import org.osgi.framework.Bundle; /** * The {@link ResourceBundleClassLoader} is a user defined classloader which is * responsible to map files within an <i>OSGi</i> bundle to {@link URL}s. This * implementation only supports the method {@link #getResource(String)} for * mappings. * * @author Michael Grammling - Initial Contribution * @author Martin Herbst - UTF-8 replaced by ISO-8859-1 to follow Java standards */ public class ResourceBundleClassLoader extends ClassLoader { private static final Charset SUPPORTED_CHARSET = Charset.forName("ISO-8859-1"); private Bundle bundle; private String path; private String filePattern; /** * Creates a new instance of this class with the specified parameters. * * @param bundle * the bundle whose files should be mapped (must not be null) * * @param path * the path within the bundle which should be considered to be * mapped. If null is set, all files within the bundle are * considered. * * @param filePattern * the pattern for files to be considered within the specified * path. If null is set, all files within the specified path are * considered. * * @throws IllegalArgumentException * if the bundle is null */ public ResourceBundleClassLoader(Bundle bundle, String path, String filePattern) throws IllegalArgumentException { if (bundle == null) { throw new IllegalArgumentException("The bundle must not be null!"); } this.bundle = bundle; this.path = (path != null) ? path : "/"; this.filePattern = (filePattern != null) ? filePattern : "*"; } @Override public URL getResource(String name) { Enumeration<URL> resourceFiles = this.bundle.findEntries(this.path, this.filePattern, true); List<URL> allResources = new LinkedList<URL>(); if (resourceFiles != null) { while (resourceFiles.hasMoreElements()) { URL resourceURL = resourceFiles.nextElement(); String resourcePath = resourceURL.getFile(); File resourceFile = new File(resourcePath); String resourceFileName = resourceFile.getName(); if (resourceFileName.equals(name)) { allResources.add(resourceURL); } } } if (allResources.isEmpty()) { return null; } if (allResources.size() == 1) { return allResources.get(0); } // handle fragment resources. return first one. for (URL url : allResources) { boolean isHostResource = bundle.getEntry(url.getPath()) != null && bundle.getEntry(url.getPath()).equals(url); if (isHostResource) { continue; } return url; } return null; } @Override public InputStream getResourceAsStream(String name) { URL resourceURL = getResource(name); if (resourceURL != null) { try (InputStream resourceStream = resourceURL.openStream()) { if (resourceStream != null) { try (Reader resourceReader = new InputStreamReader(resourceStream, SUPPORTED_CHARSET)) { Properties props = new Properties(); props.load(resourceReader); ByteArrayOutputStream baos = new ByteArrayOutputStream(); props.store(baos, "converted"); return new ByteArrayInputStream(baos.toByteArray()); } } } catch (IOException e) { } return super.getResourceAsStream(name); } return null; } }