001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *   http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     * 
017     */
018    
019    package org.apache.commons.compress.utils;
020    
021    import java.io.UnsupportedEncodingException;
022    
023    import org.apache.commons.compress.archivers.ArchiveEntry;
024    
025    /**
026     * Generic Archive utilities
027     */
028    public class ArchiveUtils {
029        
030        /** Private constructor to prevent instantiation of this utility class. */
031        private ArchiveUtils(){    
032        }
033    
034        /**
035         * Generates a string containing the name, isDirectory setting and size of an entry.
036         * <p>
037         * For example:<br/>
038         * <tt>-    2000 main.c</tt><br/>
039         * <tt>d     100 testfiles</tt><br/>
040         * 
041         * @return the representation of the entry
042         */
043        public static String toString(ArchiveEntry entry){
044            StringBuffer sb = new StringBuffer();
045            sb.append(entry.isDirectory()? 'd' : '-');// c.f. "ls -l" output
046            String size = Long.toString((entry.getSize()));
047            sb.append(' ');
048            // Pad output to 7 places, leading spaces
049            for(int i=7; i > size.length(); i--){
050                sb.append(' ');
051            }
052            sb.append(size);
053            sb.append(' ').append(entry.getName());
054            return sb.toString();
055        }
056    
057        /**
058         * Check if buffer contents matches Ascii String.
059         * 
060         * @param expected
061         * @param buffer
062         * @param offset
063         * @param length
064         * @return <code>true</code> if buffer is the same as the expected string
065         */
066        public static boolean matchAsciiBuffer(
067                String expected, byte[] buffer, int offset, int length){
068            byte[] buffer1;
069            try {
070                buffer1 = expected.getBytes("ASCII");
071            } catch (UnsupportedEncodingException e) {
072                throw new RuntimeException(e); // Should not happen
073            }
074            return isEqual(buffer1, 0, buffer1.length, buffer, offset, length, false);
075        }
076        
077        /**
078         * Check if buffer contents matches Ascii String.
079         * 
080         * @param expected
081         * @param buffer
082         * @return <code>true</code> if buffer is the same as the expected string
083         */
084        public static boolean matchAsciiBuffer(String expected, byte[] buffer){
085            return matchAsciiBuffer(expected, buffer, 0, buffer.length);
086        }
087        
088        /**
089         * Convert a string to Ascii bytes.
090         * Used for comparing "magic" strings which need to be independent of the default Locale.
091         * 
092         * @param inputString
093         * @return the bytes
094         */
095        public static byte[] toAsciiBytes(String inputString){
096            try {
097                return inputString.getBytes("ASCII");
098            } catch (UnsupportedEncodingException e) {
099               throw new RuntimeException(e); // Should never happen
100            }
101        }
102    
103        /**
104         * Convert an input byte array to a String using the ASCII character set.
105         * 
106         * @param inputBytes
107         * @return the bytes, interpreted as an Ascii string
108         */
109        public static String toAsciiString(final byte[] inputBytes){
110            try {
111                return new String(inputBytes, "ASCII");
112            } catch (UnsupportedEncodingException e) {
113                throw new RuntimeException(e); // Should never happen
114            }
115        }
116    
117        /**
118         * Compare byte buffers, optionally ignoring trailing nulls
119         * 
120         * @param buffer1
121         * @param offset1
122         * @param length1
123         * @param buffer2
124         * @param offset2
125         * @param length2
126         * @param ignoreTrailingNulls
127         * @return <code>true</code> if buffer1 and buffer2 have same contents, having regard to trailing nulls
128         */
129        public static boolean isEqual(
130                final byte[] buffer1, final int offset1, final int length1,
131                final byte[] buffer2, final int offset2, final int length2,
132                boolean ignoreTrailingNulls){
133            int minLen=length1 < length2 ? length1 : length2;
134            for (int i=0; i < minLen; i++){
135                if (buffer1[offset1+i] != buffer2[offset2+i]){
136                    return false;
137                }
138            }
139            if (length1 == length2){
140                return true;
141            }
142            if (ignoreTrailingNulls){
143                if (length1 > length2){
144                    for(int i = length2; i < length1; i++){
145                        if (buffer1[offset1+i] != 0){
146                            return false;
147                        }
148                    }
149                } else {
150                    for(int i = length1; i < length2; i++){
151                        if (buffer2[offset2+i] != 0){
152                            return false;
153                        }
154                    }                
155                }
156                return true;
157            }
158            return false;
159        }
160        
161        /**
162         * Compare byte buffers
163         * 
164         * @param buffer1
165         * @param offset1
166         * @param length1
167         * @param buffer2
168         * @param offset2
169         * @param length2
170         * @return <code>true</code> if buffer1 and buffer2 have same contents
171         */
172        public static boolean isEqual(
173                final byte[] buffer1, final int offset1, final int length1,
174                final byte[] buffer2, final int offset2, final int length2){
175            return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, false);
176        }
177        
178        /**
179         * Compare byte buffers
180         * 
181         * @param buffer1
182         * @param buffer2
183         * @return <code>true</code> if buffer1 and buffer2 have same contents
184         */
185        public static boolean isEqual(final byte[] buffer1, final byte[] buffer2 ){
186            return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, false);
187        }
188        
189        /**
190         * Compare byte buffers, optionally ignoring trailing nulls
191         * 
192         * @param buffer1
193         * @param buffer2
194         * @param ignoreTrailingNulls
195         * @return <code>true</code> if buffer1 and buffer2 have same contents
196         */
197        public static boolean isEqual(final byte[] buffer1, final byte[] buffer2, boolean ignoreTrailingNulls){
198            return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, ignoreTrailingNulls);
199        }
200        
201        /**
202         * Compare byte buffers, ignoring trailing nulls
203         * 
204         * @param buffer1
205         * @param offset1
206         * @param length1
207         * @param buffer2
208         * @param offset2
209         * @param length2
210         * @return <code>true</code> if buffer1 and buffer2 have same contents, having regard to trailing nulls
211         */
212        public static boolean isEqualWithNull(
213                final byte[] buffer1, final int offset1, final int length1,
214                final byte[] buffer2, final int offset2, final int length2){
215            return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, true);
216        }
217        
218    }