KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > util > CmsFileUtil


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/util/CmsFileUtil.java,v $
3  * Date : $Date: 2006/10/27 10:49:46 $
4  * Version: $Revision: 1.27 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.util;
33
34 import org.opencms.configuration.CmsConfigurationManager;
35 import org.opencms.file.CmsObject;
36 import org.opencms.file.CmsRequestContext;
37 import org.opencms.file.CmsResource;
38 import org.opencms.flex.CmsFlexCache;
39 import org.opencms.i18n.CmsEncoder;
40 import org.opencms.main.CmsException;
41 import org.opencms.main.CmsIllegalArgumentException;
42 import org.opencms.main.CmsLog;
43 import org.opencms.main.CmsSystemInfo;
44 import org.opencms.staticexport.CmsLinkManager;
45
46 import java.io.ByteArrayInputStream JavaDoc;
47 import java.io.ByteArrayOutputStream JavaDoc;
48 import java.io.File JavaDoc;
49 import java.io.FileFilter JavaDoc;
50 import java.io.FileInputStream JavaDoc;
51 import java.io.FileNotFoundException JavaDoc;
52 import java.io.FileOutputStream JavaDoc;
53 import java.io.IOException JavaDoc;
54 import java.io.InputStream JavaDoc;
55 import java.io.OutputStreamWriter JavaDoc;
56 import java.net.URL JavaDoc;
57 import java.net.URLClassLoader JavaDoc;
58 import java.util.ArrayList JavaDoc;
59 import java.util.Arrays JavaDoc;
60 import java.util.Collections JavaDoc;
61 import java.util.Iterator JavaDoc;
62 import java.util.List JavaDoc;
63 import java.util.ListIterator JavaDoc;
64 import java.util.Locale JavaDoc;
65
66 import org.apache.commons.logging.Log;
67
68 /**
69  * Provides File utility functions.<p>
70  *
71  * @author Alexander Kandzior
72  *
73  * @version $Revision: 1.27 $
74  *
75  * @since 6.0.0
76  */

77 public final class CmsFileUtil {
78
79     /** The log object for this class. */
80     private static final Log LOG = CmsLog.getLog(CmsFileUtil.class);
81
82     /**
83      * Hides the public constructor.<p>
84      */

85     private CmsFileUtil() {
86
87         // noop
88
}
89
90     /**
91      * Checks if all resources are present.<p>
92      *
93      * @param cms an initialized OpenCms user context which must have read access to all resources
94      * @param resources a list of vfs resource names to check
95      *
96      * @throws CmsIllegalArgumentException in case not all resources exist or can be read with the given OpenCms user context
97      */

98     public static void checkResources(CmsObject cms, List JavaDoc resources) throws CmsIllegalArgumentException {
99
100         StringBuffer JavaDoc result = new StringBuffer JavaDoc(128);
101         ListIterator JavaDoc it = resources.listIterator();
102         while (it.hasNext()) {
103             String JavaDoc resourcePath = (String JavaDoc)it.next();
104             try {
105                 CmsResource resource = cms.readResource(resourcePath);
106                 // append folder separator, if resource is a folder and does not and with a slash
107
if (resource.isFolder() && !resourcePath.endsWith("/")) {
108                     it.set(resourcePath + "/");
109                 }
110             } catch (CmsException e) {
111                 result.append(resourcePath);
112                 result.append('\n');
113             }
114         }
115         if (result.length() > 0) {
116             throw new CmsIllegalArgumentException(Messages.get().container(
117                 Messages.ERR_MISSING_RESOURCES_1,
118                 result.toString()));
119         }
120     }
121
122     /**
123      * Simply version of a 1:1 binary file copy.<p>
124      *
125      * @param fromFile the name of the file to copy
126      * @param toFile the name of the target file
127      * @throws IOException if any IO error occurs during the copy operation
128      */

129     public static void copy(String JavaDoc fromFile, String JavaDoc toFile) throws IOException JavaDoc {
130
131         File JavaDoc inputFile = new File JavaDoc(fromFile);
132         File JavaDoc outputFile = new File JavaDoc(toFile);
133
134         FileInputStream JavaDoc in = new FileInputStream JavaDoc(inputFile);
135         FileOutputStream JavaDoc out = new FileOutputStream JavaDoc(outputFile);
136
137         // transfer bytes from in to out
138
byte[] buf = new byte[1024];
139         int len;
140         while ((len = in.read(buf)) > 0) {
141             out.write(buf, 0, len);
142         }
143         in.close();
144         out.close();
145     }
146
147     /**
148      * Returns the formatted filesize to Bytes, KB, MB or GB depending on the given value.<p>
149      *
150      * @param filesize in bytes
151      * @param locale the locale of the current OpenCms user or the System's default locale if the first choice
152      * is not at hand.
153      *
154      * @return the formatted filesize to Bytes, KB, MB or GB depending on the given value
155      **/

156     public static String JavaDoc formatFilesize(long filesize, Locale JavaDoc locale) {
157
158         String JavaDoc result;
159         filesize = Math.abs(filesize);
160
161         if (Math.abs(filesize) < 1024) {
162             result = Messages.get().getBundle(locale).key(Messages.GUI_FILEUTIL_FILESIZE_BYTES_1, new Long JavaDoc(filesize));
163         } else if (Math.abs(filesize) < 1048576) {
164             // 1048576 = 1024.0 * 1024.0
165
result = Messages.get().getBundle(locale).key(
166                 Messages.GUI_FILEUTIL_FILESIZE_KBYTES_1,
167                 new Double JavaDoc(filesize / 1024.0));
168         } else if (Math.abs(filesize) < 1073741824) {
169             // 1024.0^3 = 1073741824
170
result = Messages.get().getBundle(locale).key(
171                 Messages.GUI_FILEUTIL_FILESIZE_MBYTES_1,
172                 new Double JavaDoc(filesize / 1048576.0));
173         } else {
174             result = Messages.get().getBundle(locale).key(
175                 Messages.GUI_FILEUTIL_FILESIZE_GBYTES_1,
176                 new Double JavaDoc(filesize / 1073741824.0));
177         }
178         return result;
179     }
180
181     /**
182      * Returns a comma separated list of resource paths names, with the site root
183      * from the given OpenCms user context removed.<p>
184      *
185      * @param context the current users OpenCms context (optional, may be <code>null</code>)
186      * @param resources a List of <code>{@link CmsResource}</code> instances to get the names from
187      *
188      * @return a comma separated list of resource paths names
189      */

190     public static String JavaDoc formatResourceNames(CmsRequestContext context, List JavaDoc resources) {
191
192         if (resources == null) {
193             return null;
194         }
195         StringBuffer JavaDoc result = new StringBuffer JavaDoc(128);
196         Iterator JavaDoc i = resources.iterator();
197         while (i.hasNext()) {
198             CmsResource res = (CmsResource)i.next();
199             String JavaDoc path = res.getRootPath();
200             if (context != null) {
201                 path = context.removeSiteRoot(path);
202             }
203             result.append(path);
204             if (i.hasNext()) {
205                 result.append(", ");
206             }
207         }
208         return result.toString();
209     }
210
211     /**
212      * Returns the extension of the given file name, that is the part behind the last '.' char,
213      * converted to lower case letters.<p>
214      *
215      * The result does contain the '.' char. For example, if the input is <code>"opencms.html"</code>,
216      * then the result will be <code>".html"</code>.<p>
217      *
218      * If the given file name does not contain a '.' char, the empty String <code>""</code> is returned.<p>
219      *
220      * Please note: No check is performed to ensure the given file name is not <code>null</code>.<p>
221      *
222      * @param filename the file name to get the extension for
223      * @return the extension of the given file name
224      */

225     public static String JavaDoc getFileExtension(String JavaDoc filename) {
226
227         int pos = filename.lastIndexOf('.');
228         return (pos >= 0) ? filename.substring(pos).toLowerCase() : "";
229     }
230
231     /**
232      * Returns a list of all filtered files in the RFS.<p>
233      *
234      * If the <code>name</code> is not a folder the folder that contains the
235      * given file will be used instead.<p>
236      *
237      * Despite the filter may not accept folders, every subfolder is traversed
238      * if the <code>includeSubtree</code> parameter is set.<p>
239      *
240      * @param name a folder or file name
241      * @param filter a filter
242      * @param includeSubtree if to include subfolders
243      *
244      * @return a list of filtered <code>{@link File}</code> objects
245      */

246     public static List JavaDoc getFiles(String JavaDoc name, FileFilter JavaDoc filter, boolean includeSubtree) {
247
248         List JavaDoc ret = new ArrayList JavaDoc();
249
250         File JavaDoc file = new File JavaDoc(name);
251         if (!file.isDirectory()) {
252             file = new File JavaDoc(file.getParent());
253             if (!file.isDirectory()) {
254                 return ret;
255             }
256         }
257         File JavaDoc[] dirContent = file.listFiles();
258         for (int i = 0; i < dirContent.length; i++) {
259             File JavaDoc f = dirContent[i];
260             if (filter.accept(f)) {
261                 ret.add(f);
262             }
263             if (includeSubtree && f.isDirectory()) {
264                 ret.addAll(getFiles(f.getAbsolutePath(), filter, true));
265             }
266         }
267
268         return ret;
269     }
270
271     /**
272      * Returns the file name for a given VFS name that has to be written to a repository in the "real" file system,
273      * by appending the VFS root path to the given base repository path, also adding an
274      * folder for the "online" or "offline" project.<p>
275      *
276      * @param repository the base repository path
277      * @param vfspath the VFS root path to write to use
278      * @param online flag indicates if the result should be used for the online project (<code>true</code>) or not
279      *
280      * @return The full uri to the JSP
281      */

282     public static String JavaDoc getRepositoryName(String JavaDoc repository, String JavaDoc vfspath, boolean online) {
283
284         StringBuffer JavaDoc result = new StringBuffer JavaDoc(64);
285         result.append(repository);
286         result.append(online ? CmsFlexCache.REPOSITORY_ONLINE : CmsFlexCache.REPOSITORY_OFFLINE);
287         result.append(vfspath);
288         return result.toString();
289     }
290
291     /**
292      * Returns the absolute path name for the given relative
293      * path name if it was found by the context Classloader of the
294      * current Thread.<p>
295      *
296      * The argument has to denote a resource within the Classloaders
297      * scope. A <code>{@link java.net.URLClassLoader}</code> implementation for example would
298      * try to match a given path name to some resource under it's URL
299      * entries.<p>
300      *
301      * As the result is internally obtained as an URL it is reduced to
302      * a file path by the call to <code>{@link java.net.URL#getFile()}</code>. Therefore
303      * the returned String will start with a '/' (no problem for java.io).<p>
304      *
305      * @param fileName the filename to return the path from the Classloader for
306      *
307      * @return the absolute path name for the given relative
308      * path name if it was found by the context Classloader of the
309      * current Thread or an empty String if it was not found
310      *
311      * @see Thread#getContextClassLoader()
312      */

313     public static String JavaDoc getResourcePathFromClassloader(String JavaDoc fileName) {
314
315         boolean isFolder = CmsResource.isFolder(fileName);
316         String JavaDoc result = "";
317         URL JavaDoc inputUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
318         if (inputUrl != null) {
319             // decode name here to avoid url encodings in path name
320
result = normalizePath(inputUrl);
321             if (isFolder && !CmsResource.isFolder(result)) {
322                 result = result + '/';
323             }
324         } else {
325             if (LOG.isErrorEnabled()) {
326                 try {
327                     URLClassLoader JavaDoc cl = (URLClassLoader JavaDoc)Thread.currentThread().getContextClassLoader();
328                     URL JavaDoc[] paths = cl.getURLs();
329                     LOG.error(Messages.get().getBundle().key(
330                         Messages.ERR_MISSING_CLASSLOADER_RESOURCE_2,
331                         fileName,
332                         Arrays.asList(paths)));
333                 } catch (Throwable JavaDoc t) {
334                     LOG.error(Messages.get().getBundle().key(Messages.ERR_MISSING_CLASSLOADER_RESOURCE_1, fileName));
335                 }
336             }
337         }
338         return result;
339     }
340
341     /**
342      * Creates unique, valid RFS name for the given filename that contains
343      * a coded version of the given parameters, with the given file extension appended.<p>
344      *
345      * This is used to create file names for the static export,
346      * or in a vfs disk cache.<p>
347      *
348      * @param filename the base file name
349      * @param extension the extension to use
350      * @param parameters the parameters to code in the result file name
351      *
352      * @return a unique, valid RFS name for the given parameters
353      *
354      * @see org.opencms.staticexport.CmsStaticExportManager
355      */

356     public static String JavaDoc getRfsPath(String JavaDoc filename, String JavaDoc extension, String JavaDoc parameters) {
357
358         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(128);
359         buf.append(filename);
360         buf.append('_');
361         int h = parameters.hashCode();
362         // ensure we do have a positive id value
363
buf.append(h > 0 ? h : -h);
364         buf.append(extension);
365         return buf.toString();
366     }
367
368     /**
369      * Normalizes a file path that might contain <code>'../'</code> or <code>'./'</code> or <code>'//'</code>
370      * elements to a normal absolute path, the path separator char used is {@link File#separatorChar}.<p>
371      *
372      * @param path the path to normalize
373      *
374      * @return the normalized path
375      *
376      * @see #normalizePath(String, char)
377      */

378     public static String JavaDoc normalizePath(String JavaDoc path) {
379
380         return normalizePath(path, File.separatorChar);
381     }
382
383     /**
384      * Normalizes a file path that might contain <code>'../'</code> or <code>'./'</code> or <code>'//'</code>
385      * elements to a normal absolute path.<p>
386      *
387      * Can also handle Windows like path information containing a drive letter,
388      * like <code>C:\path\..\</code>.<p>
389      *
390      * @param path the path to normalize
391      * @param separatorChar the file separator char to use, for example {@link File#separatorChar}
392      *
393      * @return the normalized path
394      */

395     public static String JavaDoc normalizePath(String JavaDoc path, char separatorChar) {
396
397         if (CmsStringUtil.isNotEmpty(path)) {
398             // ensure all File separators are '/'
399
path = path.replace('\\', '/');
400             String JavaDoc drive = null;
401             if ((path.length() > 1) && (path.charAt(1) == ':')) {
402                 // windows path like C:\home\
403
drive = path.substring(0, 2);
404                 path = path.substring(2);
405             } else if ((path.length() > 1) && (path.charAt(0) == '/') && (path.charAt(1) == '/')) {
406                 // windows path like \\home\ (network mapped drives)
407
drive = path.substring(0, 2);
408                 path = path.substring(2);
409             }
410             if (path.charAt(0) == '/') {
411                 // trick to resolve all ../ inside a path
412
path = '.' + path;
413             }
414             // resolve all '../' or './' elements in the path
415
path = CmsLinkManager.getAbsoluteUri(path, "/");
416             // still some '//' elements might persist
417
path = CmsStringUtil.substitute(path, "//", "/");
418             // re-append drive if required
419
if (drive != null) {
420                 path = drive.concat(path);
421             }
422             // switch '/' back to OS dependend File separator if required
423
if (separatorChar != '/') {
424                 path = path.replace('/', separatorChar);
425             }
426         }
427         return path;
428     }
429
430     /**
431      * Returns the normalized file path created from the given URL.<p>
432      *
433      * The path part {@link URL#getPath()} is used, unescaped and
434      * normalized using {@link #normalizePath(String, char)} using {@link File#separatorChar}.<p>
435      *
436      * @param url the URL to extract the path information from
437      *
438      * @return the normalized file path created from the given URL using {@link File#separatorChar}
439      *
440      * @see #normalizePath(URL, char)
441      */

442     public static String JavaDoc normalizePath(URL JavaDoc url) {
443
444         return normalizePath(url, File.separatorChar);
445     }
446
447     /**
448      * Returns the normalized file path created from the given URL.<p>
449      *
450      * The path part {@link URL#getPath()} is used, unescaped and
451      * normalized using {@link #normalizePath(String, char)}.<p>
452      *
453      * @param url the URL to extract the path information from
454      * @param separatorChar the file separator char to use, for example {@link File#separatorChar}
455      *
456      * @return the normalized file path created from the given URL
457      */

458     public static String JavaDoc normalizePath(URL JavaDoc url, char separatorChar) {
459
460         // get the path part from the URL
461
String JavaDoc path = new File JavaDoc(url.getPath()).getAbsolutePath();
462         // trick to get the OS default encoding, taken from the official Java i18n FAQ
463
String JavaDoc systemEncoding = (new OutputStreamWriter JavaDoc(new ByteArrayOutputStream JavaDoc())).getEncoding();
464         // decode url in order to remove spaces and escaped chars from path
465
return CmsFileUtil.normalizePath(CmsEncoder.decode(path, systemEncoding), separatorChar);
466     }
467
468     /**
469      * Deletes a directory in the file system and all subfolders of that directory.<p>
470      *
471      * @param directory the directory to delete
472      */

473     public static void purgeDirectory(File JavaDoc directory) {
474
475         if (directory.canRead() && directory.isDirectory()) {
476             File JavaDoc[] files = directory.listFiles();
477             for (int i = 0; i < files.length; i++) {
478                 File JavaDoc f = files[i];
479                 if (f.isDirectory()) {
480                     purgeDirectory(f);
481                 }
482                 if (f.canWrite()) {
483                     f.delete();
484                 }
485             }
486             directory.delete();
487         }
488     }
489
490     /**
491      * Reads a file from the RFS and returns the file content.<p>
492      *
493      * @param file the file to read
494      * @return the read file content
495      *
496      * @throws IOException in case of file access errors
497      */

498     public static byte[] readFile(File JavaDoc file) throws IOException JavaDoc {
499
500         // create input and output stream
501
FileInputStream JavaDoc in = new FileInputStream JavaDoc(file);
502
503         // read the content
504
return readFully(in, (int)file.length());
505     }
506
507     /**
508      * Reads a file with the given name from the class loader and returns the file content.<p>
509      *
510      * @param filename the file to read
511      * @return the read file content
512      *
513      * @throws IOException in case of file access errors
514      */

515     public static byte[] readFile(String JavaDoc filename) throws IOException JavaDoc {
516
517         // create input and output stream
518
InputStream JavaDoc in = CmsFileUtil.class.getClassLoader().getResourceAsStream(filename);
519         if (in == null) {
520             throw new FileNotFoundException JavaDoc(filename);
521         }
522
523         return readFully(in);
524     }
525
526     /**
527      * Reads a file from the class loader and converts it to a String with the specified encoding.<p>
528      *
529      * @param filename the file to read
530      * @param encoding the encoding to use when converting the file content to a String
531      * @return the read file convered to a String
532      * @throws IOException in case of file access errors
533      */

534     public static String JavaDoc readFile(String JavaDoc filename, String JavaDoc encoding) throws IOException JavaDoc {
535
536         return new String JavaDoc(readFile(filename), encoding);
537     }
538
539     /**
540      * Reads all bytes from the given input stream, closes it
541      * and returns the result in an array.<p>
542      *
543      * @param in the input stream to read the bytes from
544      * @return the byte content of the input stream
545      *
546      * @throws IOException in case of errors in the underlying java.io methods used
547      */

548     public static byte[] readFully(InputStream JavaDoc in) throws IOException JavaDoc {
549
550       return readFully(in, true);
551     }
552     
553     /**
554      * Reads all bytes from the given input stream, conditionally closes the given input stream
555      * and returns the result in an array.<p>
556      *
557      * @param in the input stream to read the bytes from
558      * @return the byte content of the input stream
559      * @param closeInputStream if true the given stream will be closed afterwards
560      *
561      * @throws IOException in case of errors in the underlying java.io methods used
562      */

563     public static byte[] readFully(InputStream JavaDoc in, boolean closeInputStream) throws IOException JavaDoc {
564
565         if (in instanceof ByteArrayInputStream JavaDoc) {
566             // content can be read in one pass
567
return readFully(in, in.available(), closeInputStream);
568         }
569
570         // copy buffer
571
byte[] xfer = new byte[2048];
572         // output buffer
573
ByteArrayOutputStream JavaDoc out = new ByteArrayOutputStream JavaDoc(xfer.length);
574
575         // transfer data from input to output in xfer-sized chunks.
576
for (int bytesRead = in.read(xfer, 0, xfer.length); bytesRead >= 0; bytesRead = in.read(xfer, 0, xfer.length)) {
577             if (bytesRead > 0) {
578                 out.write(xfer, 0, bytesRead);
579             }
580         }
581         if (closeInputStream) {
582             in.close();
583         }
584         out.close();
585         return out.toByteArray();
586     }
587
588     /**
589      * Reads the specified number of bytes from the given input stream,
590      * closes it and returns the result in an array.<p>
591      *
592      * @param in the input stream to read the bytes from
593      * @param size the number of bytes to read
594      *
595      * @return the byte content read from the input stream
596      *
597      * @throws IOException in case of errors in the underlying java.io methods used
598      */

599     public static byte[] readFully(InputStream JavaDoc in, int size) throws IOException JavaDoc {
600
601         return readFully(in, size, true);
602     }
603     
604     /**
605      * Reads the specified number of bytes from the given input stream, conditionally closes the stream
606      * and returns the result in an array.<p>
607      *
608      * @param in the input stream to read the bytes from
609      * @param size the number of bytes to read
610      * @param closeStream if true the given stream will be closed
611      *
612      * @return the byte content read from the input stream
613      *
614      * @throws IOException in case of errors in the underlying java.io methods used
615      */

616     public static byte[] readFully(InputStream JavaDoc in, int size, boolean closeStream) throws IOException JavaDoc {
617
618         // create the byte array to hold the data
619
byte[] bytes = new byte[size];
620
621         // read in the bytes
622
int offset = 0;
623         int numRead = 0;
624         while (offset < size) {
625             numRead = in.read(bytes, offset, size - offset);
626             if (numRead >= 0) {
627                 offset += numRead;
628             } else {
629                 break;
630             }
631         }
632
633         // close the input stream and return bytes
634
if (closeStream) {
635             in.close();
636         }
637
638         // ensure all the bytes have been read in
639
if (offset < bytes.length) {
640             throw new IOException JavaDoc("Could not read requested " + size + " bytes from input stream");
641         }
642         
643         return bytes;
644     }
645
646     
647     /**
648      * Removes all resource names in the given List that are "redundant" because the parent folder name
649      * is also contained in the List.<p>
650      *
651      * The content of the input list is not modified.<p>
652      *
653      * @param resourcenames a list of VFS pathnames to check for redundencies (Strings)
654      *
655      * @return a the given list with all redundancies removed
656      *
657      * @see #removeRedundantResources(List)
658      */

659     public static List JavaDoc removeRedundancies(List JavaDoc resourcenames) {
660
661         if ((resourcenames == null) || (resourcenames.isEmpty())) {
662             return new ArrayList JavaDoc();
663         }
664         if (resourcenames.size() == 1) {
665             // if there is only one resource name in the list, there can be no redundancies
666
return new ArrayList JavaDoc(resourcenames);
667         }
668         // check all resources names and see if a parent folder name is contained
669
List JavaDoc result = new ArrayList JavaDoc(resourcenames.size());
670         List JavaDoc base = new ArrayList JavaDoc(resourcenames);
671         Collections.sort(base);
672         Iterator JavaDoc i = base.iterator();
673         while (i.hasNext()) {
674             // check all resource names in the list
675
String JavaDoc resourcename = (String JavaDoc)i.next();
676             if (CmsStringUtil.isEmptyOrWhitespaceOnly(resourcename)) {
677                 // skip empty strings
678
continue;
679             }
680             boolean valid = true;
681             for (int j = (result.size() - 1); j >= 0; j--) {
682                 // check if this resource name is indirectly contained because a parent folder name is contained
683
String JavaDoc check = (String JavaDoc)result.get(j);
684                 if (resourcename.startsWith(check)) {
685                     valid = false;
686                     break;
687                 }
688             }
689             if (valid) {
690                 // a parent folder name is not already contained in the result
691
result.add(resourcename);
692             }
693         }
694         return result;
695     }
696
697     /**
698      * Removes all resources in the given List that are "redundant" because the parent folder
699      * is also contained in the List.<p>
700      *
701      * The content of the input list is not modified.<p>
702      *
703      * @param resources a list of <code>{@link CmsResource}</code> objects to check for redundencies
704      *
705      * @return a the given list with all redundancies removed
706      *
707      * @see #removeRedundancies(List)
708      */

709     public static List JavaDoc removeRedundantResources(List JavaDoc resources) {
710
711         if ((resources == null) || (resources.isEmpty())) {
712             return new ArrayList JavaDoc();
713         }
714         if (resources.size() == 1) {
715             // if there is only one resource in the list, there can be no redundancies
716
return new ArrayList JavaDoc(resources);
717         }
718         // check all resources and see if a parent folder name is contained
719
List JavaDoc result = new ArrayList JavaDoc(resources.size());
720         List JavaDoc base = new ArrayList JavaDoc(resources);
721         Collections.sort(base);
722         Iterator JavaDoc i = base.iterator();
723         while (i.hasNext()) {
724             // check all folders in the list
725
CmsResource resource = (CmsResource)i.next();
726             boolean valid = true;
727             for (int j = (result.size() - 1); j >= 0; j--) {
728                 // check if this resource is indirectly contained because a parent folder is contained
729
String JavaDoc check = ((CmsResource)result.get(j)).getRootPath();
730                 if (resource.getRootPath().startsWith(check)) {
731                     valid = false;
732                     break;
733                 }
734             }
735             if (valid) {
736                 // the parent folder is not already contained in the result
737
result.add(resource);
738             }
739         }
740         return result;
741     }
742
743     /**
744      * Searches for the OpenCms web application 'WEB-INF' folder during system startup, code or
745      * <code>null</code> if the 'WEB-INF' folder can not be found.<p>
746      *
747      * @param startFolder the folder where to start searching
748      *
749      * @return String the path of the 'WEB-INF' folder in the 'real' file system, or <code>null</code>
750      */

751     public static String JavaDoc searchWebInfFolder(String JavaDoc startFolder) {
752
753         if (CmsStringUtil.isEmpty(startFolder)) {
754             return null;
755         }
756
757         File JavaDoc f = new File JavaDoc(startFolder);
758         if (!f.exists() || !f.isDirectory()) {
759             return null;
760         }
761
762         File JavaDoc configFile = new File JavaDoc(f, CmsSystemInfo.FOLDER_CONFIG + CmsConfigurationManager.DEFAULT_XML_FILE_NAME);
763         if (configFile.exists() && configFile.isFile()) {
764             return f.getAbsolutePath();
765         }
766
767         String JavaDoc webInfFolder = null;
768         File JavaDoc[] subFiles = f.listFiles();
769         for (int i = 0; i < subFiles.length; i++) {
770             if (subFiles[i].isDirectory()) {
771                 webInfFolder = searchWebInfFolder(subFiles[i].getAbsolutePath());
772                 if (webInfFolder != null) {
773                     break;
774                 }
775             }
776         }
777
778         return webInfFolder;
779     }
780 }
Popular Tags