View Javadoc
1   package de.funfried.netbeans.plugins.external.formatter.eclipse.mechanic;
2   
3   import java.io.File;
4   import java.io.FileInputStream;
5   import java.io.IOException;
6   import java.net.URL;
7   import java.util.ArrayList;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Properties;
11  import java.util.logging.Level;
12  import java.util.logging.Logger;
13  
14  import org.apache.commons.lang3.StringUtils;
15  import org.apache.commons.validator.routines.UrlValidator;
16  import org.netbeans.api.annotations.common.NonNull;
17  
18  import de.funfried.netbeans.plugins.external.formatter.eclipse.xml.EclipseFormatterUtils;
19  
20  /**
21   * A parser for Workspace Mechanic configuration files.
22   */
23  public class WorkspaceMechanicConfigParser {
24  	private static final Logger log = Logger.getLogger(WorkspaceMechanicConfigParser.class.getName());
25  
26  	private static final String MULTI_FILE_SETUP_PREFIX = "/instance/com.google.eclipse.mechanic/mechanicSourceDirectories";
27  
28  	/**
29  	 * Parses and returns properties of the given {@code path} into a key value {@link Map}. If an optional
30  	 * {@code prefix} is specified, only the properties where the key starts with the given {@code prefix}
31  	 * are returned and the {@code prefix} will be removed from the keys in the returned {@link Map}.
32  	 *
33  	 * @param path a configuration file path or URL
34  	 * @param prefix an optional key prefix
35  	 *
36  	 * @return properties of the given {@code path} as a key value {@link Map}
37  	 *
38  	 * @throws IOException if there is an issue accessing the given configuration file
39  	 */
40  	@NonNull
41  	public static Map<String, String> readPropertiesFromConfiguration(String path, String prefix) throws IOException {
42  		Properties properties = createPropertiesFromPath(path);
43  		if (properties.containsKey(MULTI_FILE_SETUP_PREFIX)) {
44  			parseAdditionalFiles((String) properties.get(MULTI_FILE_SETUP_PREFIX)).stream().forEach(p -> properties.putAll(p));
45  
46  			properties.remove(MULTI_FILE_SETUP_PREFIX);
47  		}
48  
49  		return EclipseFormatterUtils.toMap(properties, prefix);
50  	}
51  
52  	@NonNull
53  	private static List<Properties> parseAdditionalFiles(String pathStruct) throws IOException {
54  		// the pathStruct looks as follows:
55  		// ["/path/to/additional/mechanic/files","/path/to/origin/mechanic/file"]
56  		pathStruct = StringUtils.trimToEmpty(pathStruct);
57  		pathStruct = StringUtils.removeStart(pathStruct, "[");
58  		pathStruct = StringUtils.removeEnd(pathStruct, "]");
59  
60  		List<Properties> result = new ArrayList<>();
61  		String[] additionalFilesPaths = StringUtils.split(pathStruct, ",");
62  		for (String additionalFilesPath : additionalFilesPaths) {
63  			additionalFilesPath = StringUtils.removeStart(additionalFilesPath, "\"");
64  			additionalFilesPath = StringUtils.removeEnd(additionalFilesPath, "\"");
65  
66  			Properties additionalProperties = createPropertiesFromPath(additionalFilesPath);
67  			result.add(additionalProperties);
68  		}
69  
70  		return result;
71  	}
72  
73  	@NonNull
74  	private static Properties createPropertiesFromPath(String path) throws IOException {
75  		if (StringUtils.isBlank(path)) {
76  			return new Properties();
77  		}
78  
79  		if (UrlValidator.getInstance().isValid(path)) {
80  			try {
81  				URL url = new URL(path);
82  
83  				Properties properties = new Properties();
84  				properties.load(url.openStream());
85  
86  				return properties;
87  			} catch (IOException ex) {
88  				log.log(Level.WARNING, "Could not read given path as URL, fallback to local file reading", ex);
89  			}
90  		}
91  
92  		return createPropertiesFromFile(new File(path));
93  	}
94  
95  	@NonNull
96  	private static Properties createPropertiesFromFile(File file) throws IOException {
97  		Properties properties = new Properties();
98  
99  		if (file != null && file.exists()) {
100 			if (file.isFile()) {
101 				try (FileInputStream is = new FileInputStream(file)) {
102 					properties.load(is);
103 				}
104 			} else if (file.isDirectory()) {
105 				File[] files = file.listFiles();
106 				for (File f : files) {
107 					if (file.isDirectory() || (file.isFile() && StringUtils.endsWith(file.getName(), EclipseFormatterUtils.EPF_FILE_EXTENSION))) {
108 						Properties additionalProperties = createPropertiesFromFile(f);
109 						properties.putAll(additionalProperties);
110 					}
111 				}
112 			}
113 		}
114 
115 		return properties;
116 	}
117 }