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    
015    package org.apache.hivemind.ant;
016    
017    import java.io.File;
018    
019    import org.apache.tools.ant.BuildException;
020    import org.apache.tools.ant.Task;
021    import 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     */
035    public 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    }