001// Copyright 2004, 2005 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014
015package org.apache.hivemind.ant;
016
017import java.io.File;
018
019import org.apache.tools.ant.BuildException;
020import org.apache.tools.ant.Task;
021import org.apache.tools.ant.types.Path;
022
023/**
024 * Utility used to create a manifest class path.
025 * It takes, as input, a reference to a path.  It converts this
026 * into a space-separated list of file names.  The default
027 * behavior is to simply strip off the directory portion of
028 * each file entirely.
029 * 
030 * <p>
031 * The final result is assigned to the property.
032 *
033 * @author Howard Lewis Ship
034 */
035public class ManifestClassPath extends Task
036{
037    private String _property;
038    private Path _classpath;
039    private File _directory;
040
041    public Path createClasspath()
042    {
043        _classpath = new Path(getProject());
044
045        return _classpath;
046    }
047
048    public String getProperty()
049    {
050        return _property;
051    }
052
053    public void setProperty(String string)
054    {
055        _property = string;
056    }
057
058    public void execute()
059    {
060        if (_classpath == null)
061            throw new BuildException("You must specify a classpath to generate the manifest entry from");
062
063        if (_property == null)
064            throw new BuildException("You must specify a property to assign the manifest classpath to");
065
066        StringBuffer buffer = new StringBuffer();
067
068        String[] paths = _classpath.list();
069
070        String stripPrefix = null;
071
072        if (_directory != null)
073            stripPrefix = _directory.getPath();
074
075        // Will paths ever be null?
076
077        boolean needSep = false;
078
079        for (int i = 0; i < paths.length; i++)
080        {
081            String path = paths[i];
082
083            if (stripPrefix != null)
084            {
085                if (!path.startsWith(stripPrefix))
086                    continue;
087
088                                // Sometimes, people put the prefix directory in as a
089                                // classpath entry; we ignore it (otherwise
090                                // we get a IndexOutOfBoundsException
091                                
092                                if (path.length() == stripPrefix.length())
093                                        continue;
094
095                if (needSep)
096                    buffer.append(' ');
097
098                // Strip off the directory and the seperator, leaving
099                // just the relative path.
100
101                buffer.append(filter(path.substring(stripPrefix.length() + 1)));
102
103                needSep = true;
104
105            }
106            else
107            {
108                if (needSep)
109                    buffer.append(' ');
110
111                File f = new File(path);
112
113                buffer.append(f.getName());
114
115                needSep = true;
116            }
117        }
118
119        getProject().setProperty(_property, buffer.toString());
120    }
121
122    public File getDirectory()
123    {
124        return _directory;
125    }
126
127    /**
128     * Sets a containing directory.  This has two effects:
129     * <ul>
130     * <li>Only files in the classpath that are contained by the directory are included.
131     * <li>The directory path is stripped from each path, leaving a relative path
132     * to the file.
133     * </ul>
134     */
135    public void setDirectory(File file)
136    {
137        _directory = file;
138    }
139
140    /**
141     * Classpath entries must use a forward slash, regardless of what the
142     * local filesystem uses.
143     */
144    protected String filter(String value)
145    {
146        if (File.separatorChar == '/')
147            return value;
148
149        return value.replace(File.separatorChar, '/');
150    }
151}