001    package org.apache.archiva.repository.content.maven2;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *  http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import org.apache.archiva.common.utils.VersionUtil;
023    
024    import java.util.regex.Matcher;
025    import java.util.regex.Pattern;
026    
027    /**
028     * Generic Filename Parser for use with layout routines.
029     *
030     *
031     */
032    public class FilenameParser
033    {
034        private String name;
035    
036        private String extension;
037    
038        private int offset;
039    
040        private static final Pattern mavenPluginPattern = Pattern.compile( "(maven-.*-plugin)|(.*-maven-plugin)" );
041    
042        private static final Pattern extensionPattern =
043            Pattern.compile( "(\\.tar\\.gz$)|(\\.tar\\.bz2$)|(\\.[\\-a-z0-9]*$)", Pattern.CASE_INSENSITIVE );
044    
045        private static final Pattern SNAPSHOT_PATTERN = Pattern.compile( "^([0-9]{8}\\.[0-9]{6}-[0-9]+)(.*)$" );
046    
047        private static final Pattern section = Pattern.compile( "([^-]*)" );
048    
049        private Matcher matcher;
050    
051        public FilenameParser( String filename )
052        {
053            this.name = filename;
054    
055            Matcher mat = extensionPattern.matcher( name );
056            if ( mat.find() )
057            {
058                extension = filename.substring( mat.start() + 1 );
059                name = name.substring( 0, name.length() - extension.length() - 1 );
060            }
061    
062            matcher = section.matcher( name );
063    
064            reset();
065        }
066    
067        public void reset()
068        {
069            offset = 0;
070        }
071    
072        public String next()
073        {
074            // Past the end of the string.
075            if ( offset > name.length() )
076            {
077                return null;
078            }
079    
080            // Return the next section.
081            if ( matcher.find( offset ) )
082            {
083                // Return found section.
084                offset = matcher.end() + 1;
085                return matcher.group();
086            }
087    
088            // Nothing to return.
089            return null;
090        }
091    
092        protected String expect( String expected )
093        {
094            String value = null;
095    
096            if ( name.startsWith( expected, offset ) )
097            {
098                value = expected;
099            }
100            else if ( VersionUtil.isGenericSnapshot( expected ) )
101            {
102                String version = name.substring( offset );
103    
104                // check it starts with the same version up to the snapshot part
105                int leadingLength = expected.length() - 9;
106                if ( leadingLength > 0 && version.startsWith( expected.substring( 0, leadingLength ) ) &&
107                    version.length() > leadingLength )
108                {
109                    // If we expect a non-generic snapshot - look for the timestamp
110                    Matcher m = SNAPSHOT_PATTERN.matcher( version.substring( leadingLength + 1 ) );
111                    if ( m.matches() )
112                    {
113                        value = version.substring( 0, leadingLength + 1 ) + m.group( 1 );
114                    }
115                }
116            }
117    
118            if ( value != null )
119            {
120                // Potential hit. check for '.' or '-' at end of expected.
121                int seperatorOffset = offset + value.length();
122    
123                // Test for "out of bounds" first. 
124                if ( seperatorOffset >= name.length() )
125                {
126                    offset = name.length();
127                    return value;
128                }
129    
130                // Test for seperator char.
131                char seperatorChar = name.charAt( seperatorOffset );
132                if ( ( seperatorChar == '-' ) || ( seperatorChar == '.' ) )
133                {
134                    offset = seperatorOffset + 1;
135                    return value;
136                }
137            }
138    
139            return null;
140        }
141    
142        /**
143         * Get the current seperator character.
144         *
145         * @return the seperator character (either '.' or '-'), or 0 if no seperator character available.
146         */
147        protected char seperator()
148        {
149            // Past the end of the string?
150            if ( offset >= name.length() )
151            {
152                return 0;
153            }
154    
155            // Before the start of the string?
156            if ( offset <= 0 )
157            {
158                return 0;
159            }
160    
161            return name.charAt( offset - 1 );
162        }
163    
164        protected String getName()
165        {
166            return name;
167        }
168    
169        public String getExtension()
170        {
171            return extension;
172        }
173    
174        public String remaining()
175        {
176            if ( offset >= name.length() )
177            {
178                return null;
179            }
180    
181            String end = name.substring( offset );
182            offset = name.length();
183            return end;
184        }
185    
186        public String nextNonVersion()
187        {
188            boolean done = false;
189    
190            StringBuilder ver = new StringBuilder();
191    
192            // Any text upto the end of a special case is considered non-version. 
193            Matcher specialMat = mavenPluginPattern.matcher( name );
194            if ( specialMat.find() )
195            {
196                ver.append( name.substring( offset, specialMat.end() ) );
197                offset = specialMat.end() + 1;
198            }
199    
200            while ( !done )
201            {
202                int initialOffset = offset;
203                String section = next();
204                if ( section == null )
205                {
206                    done = true;
207                }
208                else if ( !VersionUtil.isVersion( section ) )
209                {
210                    if ( ver.length() > 0 )
211                    {
212                        ver.append( '-' );
213                    }
214                    ver.append( section );
215                }
216                else
217                {
218                    offset = initialOffset;
219                    done = true;
220                }
221            }
222    
223            return ver.toString();
224        }
225    
226        protected String nextVersion()
227        {
228            boolean done = false;
229    
230            StringBuilder ver = new StringBuilder();
231    
232            while ( !done )
233            {
234                int initialOffset = offset;
235                String section = next();
236                if ( section == null )
237                {
238                    done = true;
239                }
240                else if ( VersionUtil.isVersion( section ) )
241                {
242                    if ( ver.length() > 0 )
243                    {
244                        ver.append( '-' );
245                    }
246                    ver.append( section );
247                }
248                else
249                {
250                    offset = initialOffset;
251                    done = true;
252                }
253            }
254    
255            return ver.toString();
256        }
257    
258    
259    }