Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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
*
* 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.apache.royale.compiler.config;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.internal.config.IConfigurationFilter;
import org.apache.royale.compiler.internal.config.annotations.ArgumentNameGenerator;
import org.apache.royale.compiler.internal.config.annotations.Arguments;
import org.apache.royale.compiler.internal.config.annotations.Config;
import org.apache.royale.compiler.internal.config.annotations.RoyaleOnly;
import org.apache.royale.compiler.internal.config.annotations.InfiniteArguments;
import org.apache.royale.compiler.internal.config.annotations.Mapping;
import org.apache.royale.compiler.internal.config.annotations.SoftPrerequisites;
import org.apache.royale.compiler.problems.ConfigurationProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.utils.Trace;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
/**
* The basic idea here is to let you keep all your configuration knowledge in
* your configuration object, and to automate as much as possible. Reflection is
* used to convert public fields and setters on your configuration object into
* settable vars. There are a few key concepts:
*
* - You should be able to configure absolutely any object.
* - Child configuration variables in your config become a dotted hierarchy of
* varnames
* - All sources of configuration data are buffered and merged (as string
* var/vals) before committing to the final configuration. This class acts as
* the buffer.
* - Hyphenated variables (i.e. "some-var") are automatically configured by
* calling your matching setter (i.e. setSomeVar)
* - Implementing an getSomeVarInfo() method on your class lets you set up more
* complicated config objects
* - You can make variables depend on other variables having been set first.
* This lets you set a root directory in one var and then use its value in
* another.
* - Per-variable validation can be performed in setters. Overall validation
* should take place as a post-process step.
* - You can keep ConfigurationBuffers around and merge multiple buffers
* together before committing. Most recent definitions always win.
*
* The contract with your configuration class:
*
* - You must provide a method with the signature
* "void setYourVar(ConfigurationValue val)" to set your config var. Your setter
* method should accept either a single arg of type List or String[], or else an
* arglist of simple types. For example
* "void myvar(int a, boolean b, String c")".
* - You can implement a function with the signature "int yourvar_argcount()" to
* require a different number of arguments. This limit will be enforced by
* configurators (command line, file, etc.)
* - If you provide a setter and explicit parameters (i.e. not List or String[])
* the number of arguments will be automatically determined.
* - Each argument to your configuration variable is assumed to have a
* (potentially non-unique) name. The default is the simple type of the argument
* (boolean, int, string). If the var takes an undetermined number of args via
* List or String[], the argname defaults to string.
* - You can implement a function with the signature
* "String yourvar_argnames(int)" to provide names for each of the parameters.
* The integer passed in is the argument number. Return the same name (i.e.
* "item") for infinite lists.
* - You can implement a function with the signature "String[] yourvar_deps()"
* to provide a list of other prerequisites for this var. You will be guaranteed
* that the deps are committed before your var, or else a configurationexception
* will be thrown if a prerequsite was unset. (Note that infinite cycles are not
* checked, so be careful.)
*/
public final class ConfigurationBuffer
{
public ConfigurationBuffer(Class extends Configuration> configClass)
{
this(configClass, new HashMap());
}
public ConfigurationBuffer(Class extends Configuration> configClass, Map aliases)
{
this(configClass, aliases, null);
}
/**
* Create a configuration buffer with an optional filter. The filter can be
* used to remove unwanted options from a super class.
*
* @param filter if null there is no filter, otherwise the set of
* configuration options is filtered.
*/
public ConfigurationBuffer(Class extends Configuration> configClass, Map aliases, IConfigurationFilter filter)
{
this.configClass = configClass;
this.varMap = new HashMap>();
this.committed = new HashSet();
loadCache(configClass, filter);
assert (varCache.size() > 0) : "coding error: nothing was configurable in the provided object!";
for (Map.Entry e : aliases.entrySet())
{
addAlias(e.getKey(), e.getValue());
}
}
public ConfigurationBuffer(ConfigurationBuffer copyFrom, boolean copyCommitted)
{
this.configClass = copyFrom.configClass;
this.varMap = new HashMap>(copyFrom.varMap);
this.committed = copyCommitted ? new HashSet(copyFrom.committed) : new HashSet();
this.varCache = copyFrom.varCache; // doesn't change after creation
this.varList = copyFrom.varList; // doesn't change after creation
this.tokens = new HashMap(copyFrom.tokens);
}
public final List dump()
{
final List dump = new ArrayList(varCache.size());
for (final Map.Entry entry : varCache.entrySet())
{
dump.add(entry.getKey() + "," + entry.getValue().toString());
}
Collections.sort(dump);
return dump;
}
public void setVar(String var, String val, String source, int line) throws ConfigurationException
{
List list = new LinkedList();
list.add(val);
setVar(var, list, source, line, null, false);
}
public void setVar(String var, List vals, String source, int line) throws ConfigurationException
{
setVar(var, vals, source, line, null, false);
}
public void setVar(String avar, List vals, String source, int line, String contextPath, boolean append) throws ConfigurationException
{
String var = unalias(avar);
if (!isValidVar(var))
throw new ConfigurationException.UnknownVariable(var, source, line);
int argCount = getVarArgCount(var);
// -1 means unspecified length, its up to the receiving setter to validate.
if (argCount != -1)
{
addAnyDefaultArgValues(var, argCount, vals);
if (vals.size() != argCount)
{
throw new ConfigurationException.IncorrectArgumentCount(argCount, // expected
vals.size(), //passed
var, source, line);
}
}
ConfigurationValue val = new ConfigurationValue(this, var,
vals, //processValues( var, vals, source, line ),
source, line, contextPath);
storeValue(var, val, append);
committed.remove(var);
}
public void clearVar(String avar, String source, int line) throws ConfigurationException
{
String var = unalias(avar);
if (!isValidVar(var))
throw new ConfigurationException.UnknownVariable(var, source, line);
varMap.remove(var);
committed.remove(var);
}
/**
* Remove the configuration values came from the given source.
*
* @param source source name
* @see CommandLineConfigurator#SOURCE_COMMAND_LINE
*/
public void clearSourceVars(String source)
{
List remove = new LinkedList();
for (Map.Entry> e : varMap.entrySet())
{
String var = e.getKey();
List vals = e.getValue();
List newvals = new LinkedList();
for (ConfigurationValue val : vals)
{
if (!val.getSource().equals(source))
{
newvals.add(val);
}
}
if (newvals.size() > 0)
varMap.put(var, newvals);
else
remove.add(var);
}
for (Iterator it = remove.iterator(); it.hasNext();)
{
varMap.remove(it.next());
}
}
public List processValues(String var, List args, String source, int line) throws ConfigurationException
{
List newArgs = new LinkedList();
for (Iterator it = args.iterator(); it.hasNext();)
{
String arg = it.next();
int depth = 100;
while (depth-- > 0)
{
int o = arg.indexOf("${");
if (o == -1)
break;
int c = arg.indexOf("}", o);
if (c == -1)
{
throw new ConfigurationException.Token(ConfigurationException.Token.MISSING_DELIMITER,
null, var, source, line);
}
String token = arg.substring(o + 2, c);
String value = getToken(token);
if (value == null)
{
if (value == null)
{
throw new ConfigurationException.Token(ConfigurationException.Token.UNKNOWN_TOKEN,
token, var, source, line);
}
}
arg = arg.substring(0, o) + value + arg.substring(c + 1);
}
if (depth == 0)
{
throw new ConfigurationException.Token(ConfigurationException.Token.RECURSION_LIMIT,
null, var, source, line);
}
newArgs.add(arg);
}
return newArgs;
}
public void setToken(String token, String value)
{
tokens.put(token, value);
}
public String getToken(String token)
{
if (tokens.containsKey(token))
return tokens.get(token);
else
{
try
{
return System.getProperty(token);
}
catch (SecurityException se)
{
return null;
}
}
}
private void storeValue(String avar, ConfigurationValue val, boolean append) throws ConfigurationException
{
String var = unalias(avar);
ConfigurationInfo info = getInfo(var);
List vals;
if (varMap.containsKey(var))
{
vals = varMap.get(var);
assert (vals.size() > 0);
ConfigurationValue first = vals.get(0);
if (!append && !first.getSource().equals(val.getSource()))
vals.clear();
else if (!info.allowMultiple())
throw new ConfigurationException.IllegalMultipleSet(
var,
val.getSource(), val.getLine());
}
else
{
vals = new LinkedList();
varMap.put(var, vals);
}
vals.add(val);
}
public List getVar(String avar)
{
String var = unalias(avar);
return varMap.get(var);
}
public Set getVars()
{
return varCache.keySet();
}
public void merge(ConfigurationBuffer other)
{
assert (configClass == other.configClass);
varMap.putAll(other.varMap);
committed.addAll(other.committed);
}
private final Map> varMap; // list of vars that have been set
private final Set committed; // set of vars committed to backing config
private final Class extends Configuration> configClass; // configuration class
private Map varCache // info cache
= new HashMap();
private List requiredList = new LinkedList(); // required vars
private List varList = new LinkedList(); // list of vars in order they should be set
private Map aliases = new HashMap(); // variable name aliases
private Map tokens = new HashMap(); // tokens for replacement
private List