/*
* Copyright (C) 2011-2014 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, 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
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* 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.bytedeco.javacpp;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.bytedeco.javacpp.annotation.Platform;
/**
* Does the heavy lifting of collecting values off Properties annotations found
* on enclosing classes. Operates for the desired "platform" value specified
* in {@link java.util.Properties}. As a {@link HashMap}, it makes the result
* easily accessible, and mutable.
*
* @see Loader#loadProperties(Class, java.util.Properties, boolean)
*/
public class ClassProperties extends HashMap<String,List<String>> {
public ClassProperties() { }
public ClassProperties(Properties properties) {
platform = properties.getProperty("platform");
platformRoot = properties.getProperty("platform.root");
pathSeparator = properties.getProperty("platform.path.separator");
if (platformRoot == null || platformRoot.length() == 0) {
platformRoot = ".";
}
if (!platformRoot.endsWith(File.separator)) {
platformRoot += File.separator;
}
for (Map.Entry e : properties.entrySet()) {
String k = (String)e.getKey(), v = (String)e.getValue();
if (v == null || v.length() == 0) {
continue;
}
if (k.equals("platform.includepath") || k.equals("platform.include") ||
k.equals("platform.linkpath") || k.equals("platform.link") ||
k.equals("platform.preloadpath") || k.equals("platform.preload") ||
k.equals("platform.frameworkpath") || k.equals("platform.framework") ||
k.equals("platform.library.suffix")) {
addAll(k, v.split(pathSeparator));
} else {
setProperty(k, v);
}
}
}
String[] defaultNames = {};
String platform, platformRoot, pathSeparator;
List<Class> inheritedClasses = null;
List<Class> effectiveClasses = null;
boolean loaded = false;
public List<String> get(String key) {
List<String> list = super.get(key);
if (list == null) {
put((String)key, list = new ArrayList<String>());
}
return list;
}
public void addAll(String key, String ... values) {
if (values != null) {
addAll(key, Arrays.asList(values));
}
}
public void addAll(String key, Collection<String> values) {
if (values != null) {
String root = null;
if (key.equals("platform.compiler") || key.equals("platform.sysroot") ||
key.equals("platform.includepath") || key.equals("platform.linkpath")) {
root = platformRoot;
}
List<String> values2 = get(key);
for (String value : values) {
if (value == null) {
continue;
}
if (root != null && !new File(value).isAbsolute() &&
new File(root + value).exists()) {
value = root + value;
}
if (!values2.contains(value)) {
values2.add(value);
}
}
}
}
public String getProperty(String key) {
return getProperty(key, null);
}
public String getProperty(String key, String defaultValue) {
List<String> values = get(key);
return values.isEmpty() ? defaultValue : values.get(0);
}
public String setProperty(String key, String value) {
List<String> values = get(key);
String oldValue = values.isEmpty() ? null : values.get(0);
values.clear();
addAll(key, value);
return oldValue;
}
public void load(Class cls, boolean inherit) {
Class<?> c = Loader.getEnclosingClass(cls);
List<Class> classList = new ArrayList<Class>();
classList.add(0, c);
while (!c.isAnnotationPresent(org.bytedeco.javacpp.annotation.Properties.class)
&& !c.isAnnotationPresent(Platform.class) && c.getSuperclass() != null
&& c.getSuperclass() != Object.class) {
// accumulate superclasses to process native methods from those as well
classList.add(0, c = c.getSuperclass());
}
if (effectiveClasses == null) {
effectiveClasses = classList;
}
org.bytedeco.javacpp.annotation.Properties classProperties =
c.getAnnotation(org.bytedeco.javacpp.annotation.Properties.class);
Platform[] platforms = null;
if (classProperties == null) {
Platform platform = c.getAnnotation(Platform.class);
if (platform != null) {
platforms = new Platform[] { platform };
}
} else {
Class[] classes = classProperties.inherit();
if (inherit && classes != null) {
if (inheritedClasses == null) {
inheritedClasses = new ArrayList<Class>();
}
for (Class c2 : classes) {
load(c2, inherit);
if (!inheritedClasses.contains(c2)) {
inheritedClasses.add(c2);
}
}
}
String target = classProperties.target();
if (target.length() > 0) {
addAll("target", target);
}
String helper = classProperties.helper();
if (helper.length() > 0) {
addAll("helper", helper);
}
String[] names = classProperties.names();
if (names.length > 0) {
defaultNames = names;
}
platforms = classProperties.value();
}
String[] pragma = {}, define = {}, include = {}, cinclude = {}, includepath = {}, compiler = {},
linkpath = {}, link = {}, frameworkpath = {}, framework = {}, preloadpath = {}, preload = {};
String library = "jni" + c.getSimpleName();
for (Platform p : platforms != null ? platforms : new Platform[0]) {
String[][] names = { p.value().length > 0 ? p.value() : defaultNames, p.not() };
boolean[] matches = { false, false };
for (int i = 0; i < names.length; i++) {
for (String s : names[i]) {
if (platform.startsWith(s)) {
matches[i] = true;
break;
}
}
}
if ((names[0].length == 0 || matches[0]) && (names[1].length == 0 || !matches[1])) {
if (p.pragma() .length > 0) { pragma = p.pragma(); }
if (p.define() .length > 0) { define = p.define(); }
if (p.include() .length > 0) { include = p.include(); }
if (p.cinclude() .length > 0) { cinclude = p.cinclude(); }
if (p.includepath().length > 0) { includepath = p.includepath(); }
if (p.compiler() .length > 0) { compiler = p.compiler(); }
if (p.linkpath() .length > 0) { linkpath = p.linkpath(); }
if (p.link() .length > 0) { link = p.link(); }
if (p.frameworkpath().length > 0) { frameworkpath = p.frameworkpath(); }
if (p.framework() .length > 0) { framework = p.framework(); }
if (p.preloadpath().length > 0) { preloadpath = p.preloadpath(); }
if (p.preload() .length > 0) { preload = p.preload(); }
if (p.library().length() > 0) { library = p.library(); }
}
}
addAll("platform.pragma", pragma);
addAll("platform.define", define);
addAll("platform.include", include);
addAll("platform.cinclude", cinclude);
addAll("platform.includepath", includepath);
addAll("platform.compiler.*", compiler);
addAll("platform.linkpath", linkpath);
addAll("platform.link", link);
addAll("platform.frameworkpath", frameworkpath);
addAll("platform.framework", framework);
addAll("platform.preloadpath", preloadpath);
addAll("platform.preload", preload);
setProperty("platform.library", library);
if (platforms != null && platforms.length > 0) {
loaded = true;
}
}
public List<Class> getInheritedClasses() {
return inheritedClasses;
}
public List<Class> getEffectiveClasses() {
return effectiveClasses;
}
public boolean isLoaded() {
return loaded;
}
}