001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.weaver.ant;
020
021import java.io.File;
022import java.util.Arrays;
023import java.util.List;
024import java.util.Map;
025import java.util.Properties;
026
027import org.apache.commons.lang3.StringUtils;
028import org.apache.tools.ant.BuildException;
029import org.apache.tools.ant.Project;
030import org.apache.tools.ant.types.DataType;
031import org.apache.tools.ant.types.EnumeratedAttribute;
032import org.apache.tools.ant.types.Path;
033import org.apache.tools.ant.types.PropertySet;
034import org.apache.tools.ant.types.Reference;
035import org.apache.tools.ant.types.PropertySet.BuiltinPropertySetName;
036
037/**
038 * Standalone weaver settings datatype. Handles:
039 * <ul>
040 * <li>{@code target} attribute - {@link File}</li>
041 * <li>{@code classpath} attribute - {@link Path} (incompatible with {@code classpathref})</li>
042 * <li>{@code classpathref} attribute - {@link String} (incompatible with {@code classpath})</li>
043 * <li>nested {@code propertyset} - {@link PropertySet}</li>
044 * <li>nested {@code properties} - {@link InlineProperties}</li>
045 * </ul>
046 * {@code propertyset} and {@code properties} are merged, with the latter taking precedence.
047 */
048public class WeaverSettings extends DataType {
049    private File target;
050    private Path classpath;
051    private String classpathref;
052    private PropertySet propertySet;
053    private InlineProperties inlineProperties;
054
055    /**
056     * Create a new {@link WeaverSettings} object.
057     * @param project owner
058     */
059    public WeaverSettings(final Project project) {
060        super();
061        setProject(project);
062    }
063
064    /**
065     * Get the {@code target} directory.
066     * @return {@link File}
067     */
068    public File getTarget() {
069        if (isReference()) {
070            return getRef().getTarget();
071        }
072        return target;
073    }
074
075    /**
076     * Set the {@code target} directory.
077     * @param target {@link File}
078     */
079    public void setTarget(final File target) {
080        if (isReference()) {
081            throw tooManyAttributes();
082        }
083        this.target = target;
084    }
085
086    /**
087     * Get the {@code classpathref}.
088     * @return {@link String}
089     */
090    public String getClasspathref() {
091        if (isReference()) {
092            return getRef().getClasspathref();
093        }
094        return classpathref;
095    }
096
097    /**
098     * Set the {@code classpathref}.
099     * @param classpathref {@link String}
100     */
101    public void setClasspathRef(final String classpathref) {
102        if (isReference()) {
103            throw tooManyAttributes();
104        }
105        this.classpathref = classpathref;
106    }
107
108    /**
109     * Return the effective classpath (system classpath + configured classpath) as a {@link List} of {@link String}
110     * filesystem paths.
111     * @return List<String>
112     */
113    public List<String> getClasspathEntries() {
114        final Path path = new Path(getProject());
115        final Path classpath = getClasspath();
116        if (classpath != null) {
117            path.add(classpath);
118        }
119        path.add(Path.systemClasspath);
120
121        return Arrays.asList(path.list());
122    }
123
124    /**
125     * Get the {@code classpath}.
126     * @return {@link Path}
127     */
128    public Path getClasspath() {
129        if (isReference()) {
130            return getRef().getClasspath();
131        }
132        if (classpath == null) {
133            if (getClasspathref() != null) {
134                final Path ref = new Path(getProject());
135                ref.setRefid(new Reference(getProject(), getClasspathref()));
136                return ref;
137            }
138        } else if (StringUtils.isNotBlank(getClasspathref())) {
139            throw new BuildException("Only one of classpathref|classpath is permitted.");
140        }
141        return classpath;
142    }
143
144    /**
145     * Set the {@code classpath}.
146     * @param classpath {@link Path}
147     */
148    public void setClasspath(final Path classpath) {
149        if (isReference()) {
150            throw tooManyAttributes();
151        }
152        if (this.classpath != null) {
153            throw new BuildException("classpath already set");
154        }
155        this.classpath = classpath;
156    }
157
158    /**
159     * Create the nested {@code properties}.
160     * @return {@link InlineProperties}
161     */
162    public InlineProperties createProperties() {
163        if (isReference()) {
164            throw noChildrenAllowed();
165        }
166        if (inlineProperties != null) {
167            throw new BuildException("properties already specified");
168        }
169        inlineProperties = new InlineProperties();
170        return inlineProperties;
171    }
172
173    /**
174     * Create a nested {@code propertyset}.
175     * @return {@link PropertySet}
176     */
177    public PropertySet createPropertySet() {
178        if (isReference()) {
179            throw noChildrenAllowed();
180        }
181        if (propertySet != null) {
182            throw new BuildException("propertyset already specified");
183        }
184        propertySet = new PropertySet();
185        propertySet.setProject(getProject());
186        return propertySet;
187    }
188
189    /**
190     * Merge nested {@code propertyset} and {@code properties}; latter takes precedence.
191     * @return Properties
192     */
193    public Properties getProperties() {
194        if (isReference()) {
195            return getRef().getProperties();
196        }
197        if (propertySet == null && inlineProperties == null) {
198            createPropertySet().appendBuiltin(
199                (BuiltinPropertySetName) EnumeratedAttribute.getInstance(BuiltinPropertySetName.class, "all"));
200        }
201        final Properties result = new Properties();
202        if (propertySet != null) {
203            result.putAll(propertySet.getProperties());
204        }
205        if (inlineProperties != null) {
206            for (final Map.Entry<Object, Object> entry : inlineProperties.properties.entrySet()) {
207                result.put(entry.getKey(), StringUtils.trim((String) entry.getValue()));
208            }
209        }
210        return result;
211    }
212
213    private WeaverSettings getRef() {
214        return getCheckedRef(WeaverSettings.class, "settings");
215    }
216
217}