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         * Convert an input byte array to a String using the ASCII character set.
119         * 
120         * @param inputBytes input byte array
121         * @param offset offset within array
122         * @param length length of array
123         * @return the bytes, interpreted as an Ascii string
124         */
125        public static String toAsciiString(final byte[] inputBytes, int offset, int length){
126            try {
127                return new String(inputBytes, offset, length, "ASCII");
128            } catch (UnsupportedEncodingException e) {
129                throw new RuntimeException(e); // Should never happen
130            }
131        }
132    
133        /**
134         * Compare byte buffers, optionally ignoring trailing nulls
135         * 
136         * @param buffer1
137         * @param offset1
138         * @param length1
139         * @param buffer2
140         * @param offset2
141         * @param length2
142         * @param ignoreTrailingNulls
143         * @return <code>true</code> if buffer1 and buffer2 have same contents, having regard to trailing nulls
144         */
145        public static boolean isEqual(
146                final byte[] buffer1, final int offset1, final int length1,
147                final byte[] buffer2, final int offset2, final int length2,
148                boolean ignoreTrailingNulls){
149            int minLen=length1 < length2 ? length1 : length2;
150            for (int i=0; i < minLen; i++){
151                if (buffer1[offset1+i] != buffer2[offset2+i]){
152                    return false;
153                }
154            }
155            if (length1 == length2){
156                return true;
157            }
158            if (ignoreTrailingNulls){
159                if (length1 > length2){
160                    for(int i = length2; i < length1; i++){
161                        if (buffer1[offset1+i] != 0){
162                            return false;
163                        }
164                    }
165                } else {
166                    for(int i = length1; i < length2; i++){
167                        if (buffer2[offset2+i] != 0){
168                            return false;
169                        }
170                    }                
171                }
172                return true;
173            }
174            return false;
175        }
176        
177        /**
178         * Compare byte buffers
179         * 
180         * @param buffer1
181         * @param offset1
182         * @param length1
183         * @param buffer2
184         * @param offset2
185         * @param length2
186         * @return <code>true</code> if buffer1 and buffer2 have same contents
187         */
188        public static boolean isEqual(
189                final byte[] buffer1, final int offset1, final int length1,
190                final byte[] buffer2, final int offset2, final int length2){
191            return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, false);
192        }
193        
194        /**
195         * Compare byte buffers
196         * 
197         * @param buffer1
198         * @param buffer2
199         * @return <code>true</code> if buffer1 and buffer2 have same contents
200         */
201        public static boolean isEqual(final byte[] buffer1, final byte[] buffer2 ){
202            return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, false);
203        }
204        
205        /**
206         * Compare byte buffers, optionally ignoring trailing nulls
207         * 
208         * @param buffer1
209         * @param buffer2
210         * @param ignoreTrailingNulls
211         * @return <code>true</code> if buffer1 and buffer2 have same contents
212         */
213        public static boolean isEqual(final byte[] buffer1, final byte[] buffer2, boolean ignoreTrailingNulls){
214            return isEqual(buffer1, 0, buffer1.length, buffer2, 0, buffer2.length, ignoreTrailingNulls);
215        }
216        
217        /**
218         * Compare byte buffers, ignoring trailing nulls
219         * 
220         * @param buffer1
221         * @param offset1
222         * @param length1
223         * @param buffer2
224         * @param offset2
225         * @param length2
226         * @return <code>true</code> if buffer1 and buffer2 have same contents, having regard to trailing nulls
227         */
228        public static boolean isEqualWithNull(
229                final byte[] buffer1, final int offset1, final int length1,
230                final byte[] buffer2, final int offset2, final int length2){
231            return isEqual(buffer1, offset1, length1, buffer2, offset2, length2, true);
232        }
233        
234    }