    001    /*----------------------------------------------------------------------------
    002     This file is part of deegree, http://deegree.org/
    003     Copyright (C) 2001-2009 by:
    004       Department of Geography, University of Bonn
    005     and
    006       lat/lon GmbH
    007
    008     This library is free software; you can redistribute it and/or modify it under
    009     the terms of the GNU Lesser General Public License as published by the Free
    010     Software Foundation; either version 2.1 of the License, or (at your option)
    011     any later version.
    012     This library is distributed in the hope that it will be useful, but WITHOUT
    013     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    014     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    015     details.
    016     You should have received a copy of the GNU Lesser General Public License
    017     along with this library; if not, write to the Free Software Foundation, Inc.,
    018     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    019
    020     Contact information:
    021
    022     lat/lon GmbH
    023     Aennchenstr. 19, 53177 Bonn
    024     Germany
    025     http://lat-lon.de/
    026
    027     Department of Geography, University of Bonn
    028     Prof. Dr. Klaus Greve
    029     Postfach 1147, 53001 Bonn
    030     Germany
    031     http://www.geographie.uni-bonn.de/deegree/
    032
    033     e-mail: info@deegree.org
    034    ----------------------------------------------------------------------------*/
    035    package org.deegree.portal.standard.security.control;
    036
    037    import java.io.File;
    038    import java.text.ParseException;
    039    import java.util.Collection;
    040    import java.util.Iterator;
    041    import java.util.Vector;
    042
    043    /**
    044     * TODO add documentation here
    045     *
    046     * @author <a href="mailto:elmasry@lat-lon.de">Moataz Elmasry</a>
    047     * @author last edited by: $Author: elmasri$
    048     *
    049     * @version $Revision: $, $Date: 08-Mar-2007 16:46:12$
    050     */
    051    public class RelativePath {
    052
    053        /**
    054         * get the first match from the many delimiters give as input
    055         *
    056         * @param source
    057         * @param delimiters
    058         * @return String
    059         */
    060        public static String getFirstMatch( String source, String[] delimiters ) {
    061
    062            Vector<Delimiter> indices = new Vector<Delimiter>();
    063
    064            for ( int i = 0; i < delimiters.length; i++ ) {
    065                // we added the indices of all matches to the vector
    066                indices.add( new Delimiter( i, source.indexOf( delimiters[i] ), delimiters[i] ) );
    067            }
    068
    069            Delimiter delimiter = getFirstIndex( indices );
    070            if ( delimiter.getValue() == null ) {
    071                return null;
    072            }
    073
    074            return source.substring( 0, delimiter.getFoundAt() + 1 );
    075        }
    076
    077        /**
    078         * Gets the first index of a match from the many delimiters given as input Takes many delimiters
    079         * returns the delimiter that occured first
    080         *
    081         * @param collection
    082         * @return instance of Delimiter class
    083         */
    084        private static Delimiter getFirstIndex( Collection<Delimiter> collection ) {
    085
    086            Delimiter delimiter = new Delimiter( -1, 999, null );
    087            Iterator it = collection.iterator();
    088            // comparing the matches to see which match occured first
    089            while ( it.hasNext() ) {
    090                Delimiter temp = (Delimiter) it.next();
    091                int indexOf = temp.foundAt;
    092                if ( indexOf < delimiter.getFoundAt() && indexOf > -1 ) {
    093                    delimiter = temp;
    094                }
    095            }
    096
    097            if ( delimiter == null ) {
    098                return null;
    099            }
    100            return delimiter;
    101
    102        }
    103
    104        /**
    105         * Split a string based on the given delimiters and return an array of strings(tokens)
    106         *
    107         * @param source
    108         * @param delimiters
    109         * @return tokens from a given string
    110         */
    111        public static String[] splitString( String source, String[] delimiters ) {
    112
    113            if ( source == null || delimiters == null )
    114                return null;
    115
    116            Vector<String> returnedStrings = new Vector<String>();
    117            String tempSource = source;
    118
    119            while ( tempSource.length() != 0 ) {
    120
    121                int delimiterLength = 0;
    122                String match = getFirstMatch( tempSource, delimiters );
    123                // if this is the last token in the String
    124                if ( match == null ) {
    125                    returnedStrings.add( tempSource );
    126                    break;
    127                } else {
    128
    129                    // removing any delimiters that could exist
    130                    for ( int i = 0; i < delimiters.length; i++ ) {
    131                        if ( match.contains( delimiters[i] ) ) {
    132                            match = match.replace( delimiters[i], "" );
    133                            delimiterLength = delimiters[i].length();
    134                            break;
    135                        }
    136
    137                    }
    138                    // Ignore the ./ and don't add it to the array
    139                    if ( match.compareTo( "./" ) != 0 ) {
    140                        returnedStrings.add( match );
    141                    }
    142                    tempSource = tempSource.substring( match.length() + delimiterLength, tempSource.length() );
    143                }
    144
    145            }
    146
    147            String[] strings = new String[returnedStrings.size()];
    148            for ( int i = 0; i < returnedStrings.size(); i++ ) {
    149                strings[i] = returnedStrings.elementAt( i );
    150            }
    151            return strings;
    152        }
    153
    154        /**
    155         * Maps from a source sTring to a target String, based on the delimiters given the delimiters
    156         * are basically "\\" or "/", but it also could be anything else Two absolute pathes should be
    157         * given here Don't give relative or non existing pathes
    158         *
    159         * @param source
    160         * @param target
    161         * @param delimiters
    162         * @return the mapped path
    163         * @throws ParseException
    164         */
    165        public static String mapRelativePath( String source, String target, String[] delimiters )
    166                                throws ParseException {
    167
    168            if ( !new File( source ).isAbsolute() ) {
    169                throw new ParseException( "The source path is not absolute", 0 );
    170            }
    171            if ( !new File( target ).isAbsolute() ) {
    172                throw new ParseException( "The target path is not absolute", 0 );
    173            }
    174
    175            String[] sourceTokens = splitString( source, delimiters );
    176            String[] targetTokens = splitString( target, delimiters );
    177            if ( sourceTokens == null || targetTokens == null )
    178                return null;
    179            if ( sourceTokens.length == 0 || targetTokens.length == 0 )
    180                return null;
    181
    182            int lessTokens = 0;
    183            if ( sourceTokens.length < targetTokens.length ) {
    184                lessTokens = sourceTokens.length;
    185            } else {
    186                lessTokens = targetTokens.length;
    187            }
    188
    189            int counter = 0;
    190            for ( counter = 0; counter < lessTokens; counter++ ) {
    191                if ( !sourceTokens[counter].equals( targetTokens[counter] ) )
    192                    break;
    193            }
    194
    195            StringBuffer buffer = new StringBuffer();
    196            for ( int i = counter; i < sourceTokens.length; i++ ) {
    197                if ( i != sourceTokens.length - 1 ) {
    198                    buffer.append( "../" );
    199                } else {
    200                    // We are checking if the last token in the source String is a file or a directory
    201                    // if its a file we don'tn write it
    202                    File sourceFile = new File( source );
    203                    if ( sourceFile.isDirectory() ) {
    204                        buffer.append( "../" );
    205                    }
    206                }
    207
    208            }
    209
    210            // This is used when the target is only one token different/larger than the source, so we
    211            // just take
    212            // the last token in the target
    213            if ( ( counter == sourceTokens.length ) && ( sourceTokens.length == targetTokens.length + 1 )
    214                 && ( sourceTokens[counter - 1].equals( targetTokens[counter - 1] ) ) ) {
    215                return targetTokens[targetTokens.length - 1];
    216            }
    217            for ( int i = counter; i < targetTokens.length; i++ ) {
    218                if ( buffer.length() == 0 ) {
    219                    // This is the first token in the path
    220                    buffer.append( "./" );
    221                }
    222                buffer.append( targetTokens[i] );
    223                if ( i != targetTokens.length - 1 ) {
    224                    buffer.append( "/" );
    225                }
    226
    227            }
    228
    229            return buffer.toString();
    230        }
    231
    232        static class Delimiter {
    233            int index;
    234
    235            String value;
    236
    237            int foundAt;
    238
    239            /**
    240             * @param index
    241             * @param foundAt
    242             * @param value
    243             */
    244            public Delimiter( int index, int foundAt, String value ) {
    245                this.index = index;
    246                this.value = value;
    247                this.foundAt = foundAt;
    248            }
    249
    250            /**
    251             * @return int
    252             */
    253            public int getIndex() {
    254                return index;
    255            }
    256
    257            /**
    258             * @param index
    259             */
    260            public void setIndex( int index ) {
    261                this.index = index;
    262            }
    263
    264            /**
    265             * @return String
    266             */
    267            public String getValue() {
    268                return value;
    269            }
    270
    271            /**
    272             * @param value
    273             */
    274            public void setValue( String value ) {
    275                this.value = value;
    276            }
    277
    278            /**
    279             * @return int
    280             */
    281            public int getFoundAt() {
    282                return foundAt;
    283            }
    284
    285            /**
    286             * @param foundAt
    287             */
    288            public void setFoundAt( int foundAt ) {
    289                this.foundAt = foundAt;
    290            }
    291        }
    292
    293    }