Home | History | Annotate | Download | only in internal
      1 /*******************************************************************************
      2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Marc R. Hoffmann - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.agent.rt.internal;
     13 
     14 import java.io.IOException;
     15 import java.io.InputStream;
     16 import java.util.Map;
     17 import java.util.Properties;
     18 import java.util.regex.Matcher;
     19 import java.util.regex.Pattern;
     20 
     21 /**
     22  * Internal utility to load runtime configuration from a classpath resource and
     23  * from system properties. System property keys are prefixed with
     24  * <code>jacoco.</code>. If the same property is defined twice the system
     25  * property takes precedence.
     26  */
     27 final class ConfigLoader {
     28 
     29 	private static final String SYS_PREFIX = "jacoco-agent.";
     30 
     31 	private static final Pattern SUBST_PATTERN = Pattern
     32 			.compile("\\$\\{([^\\}]+)\\}");
     33 
     34 	static Properties load(final String resource, final Properties system) {
     35 		final Properties result = new Properties();
     36 		loadResource(resource, result);
     37 		loadSystemProperties(system, result);
     38 		substSystemProperties(result, system);
     39 		return result;
     40 	}
     41 
     42 	private static void loadResource(final String resource,
     43 			final Properties result) {
     44 		final InputStream file = Offline.class.getResourceAsStream(resource);
     45 		if (file != null) {
     46 			try {
     47 				result.load(file);
     48 			} catch (final IOException e) {
     49 				throw new RuntimeException(e);
     50 			}
     51 		}
     52 	}
     53 
     54 	private static void loadSystemProperties(final Properties system,
     55 			final Properties result) {
     56 		for (final Map.Entry<Object, Object> entry : system.entrySet()) {
     57 			final String keystr = entry.getKey().toString();
     58 			if (keystr.startsWith(SYS_PREFIX)) {
     59 				result.put(keystr.substring(SYS_PREFIX.length()),
     60 						entry.getValue());
     61 			}
     62 		}
     63 	}
     64 
     65 	private static void substSystemProperties(final Properties result,
     66 			final Properties system) {
     67 		for (final Map.Entry<Object, Object> entry : result.entrySet()) {
     68 			final String oldValue = (String) entry.getValue();
     69 			final StringBuilder newValue = new StringBuilder();
     70 			final Matcher m = SUBST_PATTERN.matcher(oldValue);
     71 			int pos = 0;
     72 			while (m.find()) {
     73 				newValue.append(oldValue.substring(pos, m.start()));
     74 				final String sub = system.getProperty(m.group(1));
     75 				newValue.append(sub == null ? m.group(0) : sub);
     76 				pos = m.end();
     77 			}
     78 			newValue.append(oldValue.substring(pos));
     79 			entry.setValue(newValue.toString());
     80 		}
     81 	}
     82 
     83 	private ConfigLoader() {
     84 	}
     85 
     86 }
     87