package org.kohsuke.args4j.spi; import org.kohsuke.args4j.CmdLineParser; import org.kohsuke.args4j.IllegalAnnotationError; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.Field; /** * {@link Setter} that allows multiple values to be stored into one array field. * * <p> * Because of the {@link CmdLineParser} abstractions of allowing incremental parsing of options, * this implementation creates a whole new array each time a new value is found. * * This is also why we don't support a setter method that takes list/array as arguments. * * @author Kohsuke Kawaguchi */ final class ArrayFieldSetter implements Setter { private final Object bean; private final Field f; public ArrayFieldSetter(Object bean, Field f) { this.bean = bean; this.f = f; if(!f.getType().isArray()) throw new IllegalAnnotationError(Messages.ILLEGAL_FIELD_SIGNATURE.format(f.getType())); } public FieldSetter asFieldSetter() { return new FieldSetter(bean,f); } public AnnotatedElement asAnnotatedElement() { return f; } public boolean isMultiValued() { return true; } public Class getType() { return f.getType().getComponentType(); } public void addValue(Object value) { try { doAddValue(bean, value); } catch (IllegalAccessException _) { // try again f.setAccessible(true); try { doAddValue(bean,value); } catch (IllegalAccessException e) { throw new IllegalAccessError(e.getMessage()); } } } private void doAddValue(Object bean, Object value) throws IllegalAccessException { Object ary = f.get(bean); if(ary==null) { ary = Array.newInstance(getType(),1); Array.set(ary,0,value); } else { int len = Array.getLength(ary); Object newAry = Array.newInstance(ary.getClass().getComponentType(), len +1); System.arraycopy(ary,0,newAry,0,len); Array.set(newAry,len,value); ary = newAry; } f.set(bean, ary); } }