001/*
002$Source: f:/cvsroot2/open/projects/WebARTS/ca/bc/webarts/widgets/DirReadBean.java,v $
003$Name:  $
004
005$Revision: 567 $
006$Date: 2012-11-03 20:36:02 -0700 (Sat, 03 Nov 2012) $
007$Locker:  $
008*/
009
010/* DirReadBean -- A Widget Class to do some cool formating of Directory info.
011 *
012 * Copyright (C) 2001 WebARTS Design, North Vancouver Canada
013 * http://www..webarts.bc.ca
014 *
015 * This program is free software; you can redistribute it and/or modify
016 * it under the terms of the GNU General Public License as published by
017 * the Free Software Foundation; either version 2 of the License, or
018 * (at your option) any later version.
019 *
020 * This program is distributed in the hope that it will be useful,
021 * but WITHOUT ANY WARRANTY; without even the implied warranty of
022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
023 * GNU General Public License for more details.
024 *
025 * You should have received a copy of the GNU General Public License
026 * along with this program; if not, write to the Free Software
027 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
028 */
029
030package ca.bc.webarts.widgets;
031
032import java.io.File;
033import java.io.FileReader;
034import java.io.FileNotFoundException;
035import java.io.IOException;
036import java.io.FileWriter;
037import java.util.Hashtable;
038import java.util.HashMap;
039import java.util.Iterator;
040import java.util.TreeSet;
041import java.util.Vector;
042import java.lang.System;
043
044
045/**
046 * A Widget that does some directory reading, filtering and presents some
047 * useful HTML displayed information about the files.
048 **/
049public class DirReadBean {
050
051
052/** holds a String message of the last error that occured **/
053private static String lastErrorMsg="";
054
055
056static final private String defaultDirString = File.separator ;
057
058
059/** The directory being worked on as a <code>String</code>. **/
060private  static String dirString = defaultDirString + "testDir" ;
061
062
063/** the directory being worked on as a <code>File</code>. **/
064private        File            dirFile = null;
065
066
067/**
068 * This String holds the results of any parsing and filtering that is
069 * performed. It will hold an html presentation of the directory.
070 **/
071private        String          outText_;
072
073
074/** A list of filenames in the current dir. **/
075private         static String []         fileName = null;
076
077/** A list of filenames path from the current dir. **/
078private         static String []         fileNamePath = null;
079
080
081/** A index refernce to the current file we are dealing with. **/
082private         static short           fileIndex =0;
083
084
085/** the number of files in the current <code>dirFile</code> directory. **/
086private         static short           numFiles = 0;
087
088private  HashMap magMap = new HashMap();
089
090/** Holds the Long size info for each file in <code>fileName[]</code>.**/
091private         Hashtable fileSizeHash = new Hashtable();
092
093private static long totalFileSize= 0L;
094
095private String winampFilename = "DirectoryWinAmpList.m3u";
096
097
098/** Sets the String holding the directory this class is working on. **/
099public static void setDirString(String s){dirString = s;}
100
101
102/** Sets the String holding the current HTML output string. **/
103protected void setOutText(String s){outText_ = s;}
104
105
106/** Gets the String holding the current HTML output string. **/
107public String getOutText(){return outText_;}
108
109
110/**
111 * Directly sets the dirFile we are working on.
112 * <P>The preferred way of setting this is with the <code>initDirFile</code>
113 * method.
114 *
115 * @param f the File to set dirFile to.
116 * @see #initDirFile(String)
117 **/
118protected void setDirFile(File f){dirFile = f;}
119
120
121/** Gets the dirFile we are working on. **/
122public File getDirFile(){return dirFile;}
123
124
125/**
126 * Initisalizes the dirFile field with a new File represented by the passed in
127 * String
128 **/private boolean initDirFile(String s)
129{
130  boolean retVal = false;
131  dirFile = new File(s);
132  if(dirFile.isDirectory() && dirFile.canRead())
133    retVal = true;
134  return retVal;
135}
136
137
138public int getNumFiles(){return numFiles;}
139
140
141/**
142 * Reads the Dir and Inits all required class data.
143 *
144 * @param s is the dir to init.
145 **/
146public boolean initDir(String s)
147{
148  initFileIndex();
149  return initDir(s, false);
150}
151
152
153/**
154 * Reads the Dir and Inits all required class data.
155 *
156 * @param s is the dir to init.
157 * @param recurse specifies if it should recurse for files.
158 **/
159public boolean initDir(String s, boolean recurse)
160{
161  initFileIndex();
162  return initDir(s,"",recurse);
163}
164
165
166/**
167 * Reads the Dir and Inits all required class data.
168 *
169 * @param s is the dir to init.
170 * @param subPath is the dir path to prepend to the filenames.
171* @param recurse specifies if it should recurse for files.
172 **/
173public boolean initDir(String s, String subPath, boolean recurse)
174{
175  boolean retVal = initDirFile(s);
176  if (retVal)
177  {
178    initFileIndex();
179    File tempFile;
180    System.out.println("Initing a dir - dirString = "+dirString+".  s="+s+". ");
181    numFiles = 0;
182    initFileIndex();
183    if (!dirString.equals(s))
184    {
185      setDirString(s);
186    }
187    String[] currentDirfiles = dirFile.list();
188
189    // count how many files and init our array
190    if (numFiles == 0)
191      for (int i=0; i< currentDirfiles.length; i++)
192      {
193        tempFile = new File(dirString+File.separator+currentDirfiles[i]);
194        if(!tempFile.isDirectory())
195        {
196          //System.out.println("Counting File "+
197          //                   dirString+File.separator+currentDirfiles[i]);
198          numFiles++;
199        }
200        else if (recurse)
201          numFiles +=
202            Util.countFilesInDir(dirString+File.separator+currentDirfiles[i],
203                                 true);
204      }
205    //if (fileName == null)
206    //{
207      System.out.println("numFiles = "+numFiles);
208      fileName  = new String[numFiles]; //dirFile.list();
209      fileNamePath  = new String[numFiles];
210    //}
211
212    for (int i=0; i< currentDirfiles.length; i++)
213    {
214      if (i==0)
215        System.out.println("Start Of Processing: "+currentDirfiles.length+
216                           "/"+fileIndex+"/"+numFiles);
217      tempFile = new File(dirString+File.separator+currentDirfiles[i]);
218      if(!tempFile.isDirectory())
219      {
220        fileName[fileIndex] = currentDirfiles[i];
221        fileNamePath[fileIndex] = subPath;
222
223        fileSizeHash.put(fileName[fileIndex++] ,
224                         new Long( (long) tempFile.length()));
225        totalFileSize += (long) tempFile.length();
226      }
227      else if (recurse)
228      {
229        String recursedSubpath = currentDirfiles[i];
230        if (subPath != null && subPath.length()>0)
231          recursedSubpath = subPath+"/"+currentDirfiles[i];
232        //System.out.println("Recurse on = "+tempFile.toString());
233        initDir(tempFile.toString(), recursedSubpath,true);
234        //System.out.println(fileIndex);
235        initDirFile(s);
236        setDirString(s);
237        currentDirfiles = dirFile.list();
238        //System.out.println(fileIndex);
239      }
240    }
241    System.out.println("End   Of Processing: "+currentDirfiles.length+
242                       "/"+fileIndex+"/"+numFiles);
243
244    //initFileIndex();
245  }
246  return retVal;
247}
248
249
250public void initOutText(){outText_ = "<html><body>\n"; }
251public static void initFileName(){fileName=null;}
252public static void initFileIndex(){fileIndex=0;}
253public void appendOutText(String s) {outText_ += s;}
254public void finalizeOutText(){outText_ += "\n</body></html>";  }
255public String getDirString(){return dirString;}
256public static String getLastErrorMessage(){ return lastErrorMsg;}
257public Long getTotalFileSize(){return new Long(totalFileSize);}
258
259/**
260 * Gets the file size for the file name passed in form the passed in
261 *dirString directory.
262 *
263 * @param dirString the string representation of the directory.
264 * @param s the string representation of the filename to lookup.
265 * @return the Long representing the requested file size.
266 **/
267public Long getFileSize(String dirString, String s)
268{
269  initDir(dirString);
270  return ((Long)fileSizeHash.get(s));
271}
272
273
274/**
275 * Gets the file size for the file name passed in.<P> It looks up the values in
276 * this classes Hash of the filenames... soi the readDir method or the
277 * initDir methodMUST be called before this method to ensure that the hash is
278 * initialized with the current directory info.
279 * <P>See also the getFileSize(String, String) method that takes
280 * the dir as well so you don't have to call readDir first
281 *
282 * @param s the string representation of the filename to lookup.
283 * @return the Long representing the requested file size.
284 **/
285public Long getFileSize(String s)
286{
287  return ((Long)fileSizeHash.get(s));
288}
289
290
291/**
292 * A helper method to abstract the work to find out if a file exists.
293 *
294 * @param s the string representing the file name to look for.
295 *
296 * @return true if the file exists, false if it doesn't.  duh.
297 **/
298public boolean doesFileExist(String s)
299{
300  boolean retVal = false;
301  try
302  {
303    FileReader testFile = new FileReader(getDirString()+File.separator+s);
304    retVal = true;
305    lastErrorMsg = "doesFileExist: NoError: filename="+s;
306  }
307  catch (java.io.FileNotFoundException  nfEx)
308  {
309    retVal = false;
310    lastErrorMsg = "doesFileExist: filename=" + s +
311                   " File NOT Found Exception";
312  }
313  catch (SecurityException   secEx)
314  {
315    retVal = false;
316    lastErrorMsg = "doesFileExist: SecurityException: filename=" + s;
317  }
318  return retVal;
319}
320
321
322/**
323 * Looks up the next file in the indexed list of files being kept by this class.
324 *
325 * @return a string representin the name of the next file in the file list.
326 **/
327public String getNextFileName()
328{
329  String retVal = null;
330  if (fileIndex<numFiles)
331    retVal = fileName[fileIndex++] ;
332  return retVal;
333}
334
335
336/**
337 * Looks up the next file path in the indexed list of files being kept by this class.
338 *
339 * @return a string representin the name of the next file in the file list.
340 **/
341public String getNextFilePath()
342{
343  String retVal = null;
344  if (fileIndex<numFiles)
345    retVal = fileNamePath[fileIndex] ;
346  return retVal;
347}
348
349
350/**
351 * Looks up the next file in the indexed list of files and returns its size.
352 *
353 * @return a Long representing the filesaize of the next file in the file list.
354 **/
355public Long getNextFileSize()
356{
357  Long retVal = new Long(-1L);
358  if (fileIndex<numFiles)
359    retVal = getFileSize(fileName[fileIndex]) ;
360  return retVal;
361}
362
363
364public String getFileContents(String s){
365  String retVal = "";
366  try{
367        StringBuffer sBuf = new StringBuffer();
368       int numChars=0;
369        FileReader fileReader = new FileReader(getDirString()+File.separator+s);
370        byte tempChar = (byte) fileReader.read();
371        while (tempChar != -1) {
372              sBuf.append( (char) tempChar);
373              tempChar =(byte)  fileReader.read();
374        }
375      retVal = sBuf.toString();
376   }
377   catch (FileNotFoundException fnfEx){
378              retVal = "File" +s + " NOT Found.";
379   }
380   catch (SecurityException secEx){
381              retVal = "Unable To Read File " +s +": Security.";
382   }
383   catch (IOException ioEx){
384              retVal = "Unable To Read File " +s +": IO Error.";
385   }
386    return retVal;
387}
388
389
390/**
391 * Removes any space chars ' ' from a filename and Capitalizes the next char.
392 * <P><B>NOTE:</B> The file is expected to be in
393 * the current working directorydirectory
394 *
395 * @param dirString the directory to look in for the file name (no trailing /).
396 * @param fName a string representing the file to perform the action.
397 * @return the new filename representation
398 **/
399public String spacesToCapsInFileName(String dirString, String fName)
400{
401  setDirString(dirString);
402  return spacesToCapsInFileName(fName);
403}
404
405
406/**
407 * Removes any space chars ' ' from a filename and Capitalizes the next char.
408 * <P><B>NOTE:</B> The file is expected to be in
409 * the current working directorydirectory
410 *
411 * @param fName a string representing the file to perform the action
412 * @return the new filename representation
413 **/
414public String spacesToCapsInFileName(String fName)
415{
416  String newName = "";
417  File tempFile;
418  if (fileName != null){
419    tempFile = new File(dirString+File.separator+fName);
420    if(!tempFile.isDirectory())
421    {
422      boolean space = false;
423      for (int j=0; j< fName.length(); j++)
424      {
425        char newChar = fName.charAt(j);
426        if (newChar == ' ')
427        {
428          // set the space flag so the next char can be cap'd
429          space = true;
430        }
431        else
432        {
433          if (space) // was the last char a space???
434          {
435            newName += String.valueOf(Character.toUpperCase(newChar));
436          }
437          else
438          {
439            newName += String.valueOf(newChar);
440          }
441          space = false;
442        }
443      }
444    }
445  }
446  return newName;
447}
448
449
450/**
451 * Renames files to a more URL friendly format.
452 * <P>It goes through each file in the current working directory and renames it
453 * using the spacesToCapsInFileName method of renaming.
454 *
455 * @see #spacesToCapsInFileName(String)
456 * @see #dirFile
457 **/
458public void autoFormatFileNames()
459{
460  System.out.println("Formatting dir="+dirFile.toString());
461  if (dirFile != null &&
462      dirFile.isDirectory() &&
463      dirFile.canRead() &&
464      fileName  != null )
465  {
466    File tempFile;
467    boolean succeeded = false;
468    for (int i=0;i< fileName.length;i++)
469    {
470      tempFile = new File(dirString+File.separator+fileName[i]);
471      String newName = spacesToCapsInFileName(fileName[i]);
472      try
473      {
474        if (newName !="" && fileName[i].length() != newName.length())
475        {
476          System.out.println(i+".1) "+tempFile.toString());
477          System.out.print(i+".2) "+dirString+File.separator+newName);
478          succeeded = tempFile.renameTo(
479            new File(dirString+File.separator+newName));
480          if (succeeded)
481            System.out.print("  succeeded.");
482          else
483            System.out.println("");
484          File tempFile2 = new File(dirString+File.separator+fileName[i]);
485          if (tempFile2.exists() &&
486              tempFile.exists() &&
487              !newName.toUpperCase().equals(fileName[i].toUpperCase()))
488          {
489            tempFile2.delete();
490          }
491        }
492      }
493      catch (SecurityException ex)
494      {
495        System.err.println("SecurityException " + ex);
496      }
497      catch (NullPointerException ex)
498      {
499        System.err.println("NullPointerException " + ex);
500      }
501    } //loop
502  }
503}
504
505
506/**
507 * Formats the files in the directory specified by the passed in String.
508 * <P>This method takes a string representing the directory to use as the basis
509 * for all formatting and then performs the formatting as specified by the
510 * autoFormatFileNames() method.<P><B><U>WARNING:</U></B> This method WRITES to
511 * the directory.  It actually changes the names of the files.
512 *
513 * @param arg a string representation of thre directory to parse.
514 * @see #autoFormatFileNames()
515 **/
516public void autoFormatFileNames(String arg)
517{
518  // parse the input parms to switch the dir we want
519  if(arg!=null) dirString = arg;
520
521  initOutText();
522  initDirFile(dirString);
523  if(dirFile.isDirectory())
524  {
525    if(dirFile.canRead())
526    {
527      fileName  = dirFile.list();
528    }
529  }
530  autoFormatFileNames();
531}
532
533public  String[] getArtistsNames()
534{
535  TreeSet magSet = new TreeSet(magMap.keySet());
536  String [] retVal = new String[magMap.size()];
537  int ii = 0;
538  for (Iterator i=magSet.iterator(); i.hasNext() ;)
539  {
540    retVal[ii++] = ((String) i.next()).trim();
541  }
542  return retVal;
543}
544
545public String getWinampFilename() { return winampFilename;}
546public void setWinampFilename(String s) { winampFilename = s;}
547
548
549
550/**
551 * Parse the current directory for files with the spec'd extension and create a
552 * sorted and titled list of Authored entries (mp3 files, pdf magazines etc).
553 * <P>The filenames must be in the format "Author_Title.extension" for this
554 * method to create a decent list. It groups all files withthe same author into
555 * a titled group.
556 *
557 * @param fileExtension the file extension to use as the filter for this list
558 *                      (without the leading period...
559 *                       example: for tbg_doc.pdf pass in pdf)
560 * @param filesToIgnore the filenames (without the extension) to not process
561 * @return a string holding the html unordered list
562 **/
563public String getTitledAuthorList(String fileExtension,
564                                  String pathPrefix,
565                                  Vector filesToIgnore)
566{
567  String retVal = "<!-- - - - - - - - - - - - - - - - - - - - - - - - - -->\n";
568  retVal       += "<!-- Java Servlet Created List - - - - - - - - - - - -->\n";
569  retVal       += "<!-- - - - - - - - - - - - - - - - - - - - - - - - - -->\n";
570  String name1, name, artist, title;
571  String tempArtist="",expandedTitle,expandedArtist="";
572  int startPosition, endPosition;
573  Long fileSize, zeroL = new Long(0L);
574  Vector currentMagTitles = null;
575  String [] magTitleInfo = new String[4];
576
577  initFileIndex();
578
579  fileSize = zeroL;
580  fileSize = getNextFileSize();
581  String nextPath = getNextFilePath();
582  name = getNextFileName();
583
584  while( name != null )
585  {
586    if( name.endsWith("."+fileExtension) &&
587        (filesToIgnore == null ||
588         !filesToIgnore.contains(
589           name.substring(0,name.lastIndexOf("."+fileExtension)))))
590    {
591      expandedTitle="";
592      startPosition = name.indexOf("_");
593      if (startPosition < 0 )
594      {
595        startPosition = 0;
596        artist = "No Title";
597      }
598      else
599        artist = name.substring(0,startPosition).trim();
600
601      endPosition = name.lastIndexOf("."+fileExtension);
602      title = name.substring(startPosition+1,endPosition);
603      int len = title.length();
604      boolean capital = true;
605      boolean letter = true;
606      boolean digit = false;
607      boolean lastDigit = false;
608      char c;
609      for (int i=0;i<len;i++)
610      {
611         c = title.charAt(i);
612         letter = Character.isLetter(c);
613         capital= letter & Character.isUpperCase(c);
614         digit =  Character.isDigit(c);
615
616         if (capital || (digit && !lastDigit) || (!digit && !letter))
617           expandedTitle += " ";
618
619         expandedTitle += c;
620         lastDigit = digit;
621      }
622      if (!(tempArtist.toUpperCase().equals(artist.toUpperCase())) )
623      {
624          expandedArtist="";
625          tempArtist = artist;
626          capital = true;
627          letter = true;
628          digit = false;
629          lastDigit = false;
630          for (int i=0;i<startPosition;i++)
631          {
632            c = tempArtist.charAt(i);
633            letter = Character.isLetter(c);
634            capital= letter & Character.isUpperCase(c);
635            digit =  Character.isDigit(c);
636
637            if (capital || (digit && !lastDigit) || (!digit && !letter))
638              expandedArtist += " ";
639
640            expandedArtist += c;
641            lastDigit = digit;
642          }
643      }
644      if (magMap.containsKey(expandedArtist.trim()))
645      {
646          currentMagTitles = (Vector) magMap.get(expandedArtist.trim());
647      }
648      else
649      {
650          currentMagTitles = new Vector();
651      }
652      magTitleInfo[0] = name;
653      magTitleInfo[1] = expandedTitle;
654      magTitleInfo[2] = String.valueOf(fileSize);
655      magTitleInfo[3] = nextPath;
656      currentMagTitles.add(magTitleInfo.clone());
657      magMap.put(expandedArtist.trim(),currentMagTitles);
658    }
659
660    fileSize = getNextFileSize();
661    nextPath = getNextFilePath();
662    name = getNextFileName();
663  }
664
665  retVal +="<ul>\n";
666  // get a set of the keys (expanded artists)
667  // sorted by TreeSet
668  TreeSet magSet = new TreeSet(magMap.keySet());
669  for (Iterator i=magSet.iterator(); i.hasNext() ;)
670  {
671    expandedArtist = ((String) i.next()).trim();
672    retVal +="<br /><br /><a name=\"" + expandedArtist + "\">";
673    retVal +="<b><u>" + expandedArtist + "</u></b></a>";
674
675    // now get the titles for the mag & sort them
676    currentMagTitles = (Vector)magMap.get(expandedArtist);
677    HashMap sortedTitleMap = new HashMap();
678    for (int j=0; j<currentMagTitles.size(); j++)
679    {
680        String [] currTitles= (String[]) currentMagTitles.get(j);
681        expandedTitle = currTitles[1];
682        sortedTitleMap.put(expandedTitle, currTitles);
683    }
684    TreeSet tileSet = new TreeSet(sortedTitleMap.keySet());
685    String fileSizeStr = "";
686    String filePathStr = pathPrefix;
687    for (Iterator j=tileSet.iterator(); j.hasNext() ;)
688    {
689        String key = (String) j.next();
690        String [] currTitles= (String[]) sortedTitleMap.get(key);
691        name = currTitles[0];
692        expandedTitle = currTitles[1];
693        fileSizeStr = currTitles[2];
694        if (currTitles[3] == null || currTitles[3].equals(""))
695          filePathStr =pathPrefix;
696        else
697          filePathStr = currTitles[3];
698        if (filePathStr == null)
699          filePathStr = "";
700
701        if (filePathStr != null &&
702            filePathStr.length()>0 &&
703            !filePathStr.endsWith("/"))
704          filePathStr += "/";
705        retVal +="<li><a href="+ filePathStr+name + ">" + expandedTitle +"</a>" +
706                 "&nbsp;<font size=-1>(<i>" + fileSizeStr +
707                 "</i></font> bytes)\n";
708    }
709  }
710  retVal +="</ul>\n";
711
712  return retVal;
713}
714
715
716/**
717 * Parse the current directory for files with the spec'd extension and create a
718 * sorted and titled list of Authored entries (mp3 files, pdf magazines etc).
719 * <P>The filenames must be in the format "Author_Title.extension" for this
720 * method to create a decent list. It groups all files withthe same author into
721 * a titled group.
722 *
723 * @param fileExtension the file extension to use as the filter for this list
724 *                      (without the leading period...
725 *                       example: for tbg_doc.pdf pass in pdf)
726 * @return a string holding the html unordered list
727 **/
728public String getTitledAuthorList(String fileExtension)
729{
730  return getTitledAuthorList(fileExtension, "", null);
731}
732
733
734/**
735 * Parse the current directory for files with the spec'd extension and create a
736 * sorted and titled list of Authored entries (mp3 files, pdf magazines etc).
737 * <P>The filenames must be in the format "Author_Title.extension" for this
738 * method to create a decent list. It groups all files withthe same author into
739 * a titled group.
740 *
741 * @param fileExtension the file extension to use as the filter for this list
742 *                      (without the leading period...
743 *                       example: for tbg_doc.pdf pass in pdf)
744 * @param pathPrefix is the path to prefix each href with
745 * @return a string holding the html unordered list
746 **/
747public String getTitledAuthorList(String fileExtension, String pathPrefix)
748{
749  return getTitledAuthorList(fileExtension, pathPrefix, null);
750}
751
752
753/**
754 * Reads the passed in directory and produces HTML representing the directory.
755 * <P>It initializes all the current directory variables for this class so other
756 * helper methods that work on a current directory have valid variables. It
757 * prepares the HTML represerntation of the directory and returns it and also
758 * places it in the outText_ variable.
759 *
760 * @param arg the String representation of the directory to read.
761 * @return the HTML representation of the directory.
762 **/
763public String readDir(String arg)
764{
765  // parse the input parms to switch the dir we want
766  if(arg!=null) setDirString(arg);
767
768  initOutText();
769  initDirFile(dirString);
770  if(dirFile.isDirectory())
771  {
772    if(dirFile.canRead())
773    {
774      String[] files = dirFile.list();
775      fileName  = dirFile.list();
776      File tempFile;
777      for (int i=0;i< fileName.length;i++)
778      {
779        outText_ += "<UL>\n";
780        tempFile = new File(dirString+File.separator+files[i]);
781        if(tempFile.isDirectory())
782        outText_ += "<LI> [DIR] <A HREF=\""+files[i]+"\">" +
783                     files[i] + "</A> <FONT size=\"-1\">(<I>" + tempFile.length() +
784                     " bytes</I>)</font>";
785        else
786        {
787          outText_ += "<LI>      <A HREF=\""+files[i]+"\">" +
788                     files[i] + "</A> <FONT size=\"-1\">(<I>" + tempFile.length() +
789                     " bytes</I>)</font>";
790          fileName[fileIndex] = files[i];
791          fileSizeHash.put(fileName[fileIndex++] ,
792                           new Long( (long) tempFile.length()));
793
794        }
795        outText_+="</UL>\n";
796      }
797      numFiles = fileIndex;
798      //initFileIndex();
799    }
800    else {
801      outText_ += "\n<P><B><I>Error Encountered:</I></B>";
802      outText_ += "\n<P>Unable to read Directory ->" + dirString;
803      outText_ += "\n<HR>";
804    }
805  }
806  else {
807    outText_ += "\n<P><B><I>Error Encountered:</I></B>";
808    outText_ += "\n<P>Not A Directory ->" + dirString;
809    outText_ += "\n<HR>";
810  }
811
812  finalizeOutText();
813
814  return(outText_);
815}
816
817
818public static synchronized String[] parseAuthorAndTitleFromFilename(String filename)
819{
820  String[] retVal = new String[2];
821
822  String author = "";
823  // Get the Author Name
824  int startPosition = filename.indexOf("_");
825  if (startPosition < 0 )
826  {
827    startPosition = 0;
828    author = "Not Available";
829  }
830  else
831    author = filename.substring(0,startPosition).trim();
832
833  int endPosition = filename.lastIndexOf(".");
834
835  // get the Title
836  String title = filename.substring(startPosition+1,endPosition);
837
838
839  // now expand the tile and author
840  String tempAuthor="";
841  String expandedTitle="";
842  String expandedAuthor=author;
843  int len = title.length();
844  boolean capital = true;
845  boolean letter = true;
846  boolean digit = false;
847  boolean lastDigit = false;
848  char c;
849  for (int i=0; i<len; i++)
850  {
851     c = title.charAt(i);
852     letter = Character.isLetter(c);
853     capital= letter & Character.isUpperCase(c);
854     digit =  Character.isDigit(c);
855
856     if (capital || (digit && !lastDigit) || (!digit && !letter))
857       expandedTitle += " ";
858
859     expandedTitle += c;
860     lastDigit = digit;
861  }
862  if (!(tempAuthor.toUpperCase().equals(author.toUpperCase())) )
863  {
864      expandedAuthor="";
865      tempAuthor = author;
866      capital = true;
867      letter = true;
868      digit = false;
869      lastDigit = false;
870      for (int i=0;i<startPosition;i++)
871      {
872        c = tempAuthor.charAt(i);
873        letter = Character.isLetter(c);
874        capital= letter & Character.isUpperCase(c);
875        digit =  Character.isDigit(c);
876
877        if (capital || (digit && !lastDigit) || (!digit && !letter))
878          expandedAuthor += " ";
879
880        expandedAuthor += c;
881        lastDigit = digit;
882      }
883  }
884
885  retVal[0] = expandedAuthor;
886  retVal[1] = expandedTitle;
887
888  return retVal;
889}
890
891/**
892 * Reads the passed in directory and produces a winamp playlist for all
893 * mp3 and ogg files in the dir.  It returns a playlist string.
894 *
895 * @param urlRoot the String representation of url to prepend to all the
896                  files found. If an empty or null is sent it creates a
897                  file:// url.
898 * @param dirToRead the String representation of the directory to read.
899 * @param recurse flags if the dir should be recursed
900 * @param the name of the file to save.
901 * @return the winamp playlist filename to save,
902 *         (null to NOT save, empty string to use default)
903 **/
904public static synchronized String createWinampList(String urlRoot,
905                               String dirToRead,
906                               boolean recurse,
907                               String filename)
908{
909  String retVal = "";
910  String EOL = "\r\n";
911  String winampHeader = "#EXTM3U" + EOL;
912  int winampHeaderLen = winampHeader.length();
913  String winampFilename = "WinAmpList.m3u";
914  boolean savingTheFile = true;
915  if (urlRoot == null) urlRoot = "";
916  if (filename != null &&
917     !filename.equals(""))
918    winampFilename = filename;
919  else if (filename == null)
920    savingTheFile = false;
921  File dirFileToRead = null;
922
923  if ( dirToRead !=null &&
924      !dirToRead.equals(""))
925  {
926    dirFileToRead = new File(dirToRead);
927
928    //Check if dir is available
929    if(dirFileToRead.isDirectory() && dirFileToRead.canRead())
930    {
931      // read files
932      retVal = "";
933      String[] filesInDir = dirFileToRead.list();
934      File tempFile;
935      String[] authorTitle = new String[2];
936
937      // loop through all files
938      for (int i=0; i< filesInDir.length; i++)
939      {
940        tempFile = new File(dirToRead+File.separator+filesInDir[i]);
941        if(!tempFile.isDirectory())
942        // files get added
943        {
944          if (filesInDir[i].trim().toLowerCase().endsWith(".mp3") ||
945              filesInDir[i].trim().toLowerCase().endsWith(".ogg"))
946          {
947            authorTitle = parseAuthorAndTitleFromFilename(filesInDir[i].trim());
948            retVal += "#EXTM3U:-1," + authorTitle[0] + " - " +
949                      authorTitle[1] + EOL;
950            retVal += urlRoot + "/" + filesInDir[i] + EOL;
951          }
952          else
953          {
954            // ignore ... it's not a song file
955          }
956        }
957        else
958        // dirs get recursed
959        {
960          String recursedList = createWinampList(urlRoot+"/"+filesInDir[i],
961                                     tempFile.toString(),
962                                     recurse,
963                                     null); //never save the file on a recurse
964          if (recursedList != null && !recursedList.equals(""))
965            retVal += EOL + recursedList.substring(winampHeaderLen);
966        }
967      }
968
969      //clean up the retVal
970      retVal = retVal.trim();
971      if (retVal != null && !retVal.equals("") && !retVal.startsWith(winampHeader))
972        retVal = winampHeader + retVal;
973
974
975      // Save the file
976      if (savingTheFile)
977      {
978        try
979        {
980          if(filesInDir.length > 0 && retVal.length()>0)
981          {
982            FileWriter fileWriter = new FileWriter(dirToRead + File.separator +
983                                                   winampFilename);
984            fileWriter.write(retVal,0,retVal.length());
985            fileWriter.flush();
986            fileWriter.close();
987          }
988          else
989          {
990            // No Files return empty string
991            lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
992            lastErrorMsg += "\n<P>NO files in " + dirToRead;
993            lastErrorMsg += "\n<HR>";
994            retVal = "";
995          }
996        }
997        catch (IOException ex)
998        {
999          lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
1000          lastErrorMsg += "\n<P>Unable to create WinAmp Playlist file" +
1001                          "for Directory ->\n" + dirToRead;
1002          lastErrorMsg += "\n<HR>";
1003        }
1004      }
1005    }
1006    else
1007    {
1008      // error return empty string
1009      lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
1010      lastErrorMsg += "\n<P>NOT a dir or Unable to initialize Directory for "+
1011                      "reading->" + dirString;
1012      lastErrorMsg += "\n<HR>";
1013      retVal = "";
1014    }
1015  }
1016  else
1017  {
1018    // error return empty string
1019    lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
1020    lastErrorMsg += "\n<P>Unable to initialize Directory for reading->" +
1021                    dirString;
1022    lastErrorMsg += "\n<HR>";
1023    retVal = "";
1024  }
1025
1026  return retVal;
1027}
1028
1029
1030/**
1031 * Reads the passed in directory and produces a winamp playlist for all
1032 * mp3 files in the dir.It returns an empty string "" if the file cannot be
1033 * created and fills the lastErrorMsg field.
1034 *
1035 * @param urlRoot the String representation of url to prepend to all the
1036                  files found. If an empty or null is sent it creates a
1037                  file:// url.
1038 * @param arg the String representation of the directory to read.
1039 * @param recurse flags if the dir should be recursed
1040 * @return the name of the winamp playlist file.
1041 **/
1042public String createWinampList(String urlRoot, String arg, boolean recurse)
1043{
1044  String retVal = "#EXTM3U\n";
1045/*
1046 #EXTINF:239,Bryan Adams - Hey honey-I'm packin'you in!
1047 D:\tbg\stuff\mp3\BryanAdams_HeyHoney-ImPackinYouIn.mp3
1048*/
1049  // parse the input parms to switch the dir we want
1050
1051  if (urlRoot == null)
1052    urlRoot = "";
1053
1054  if(true )//initDir(arg, true))
1055  {
1056    //autoFormatFileNames();
1057    String[] files = dirFile.list();
1058    fileName  = dirFile.list();
1059    File tempFile;
1060    String artistName = "";
1061    String songTitle = "";
1062    System.out.println("Creating Playlist with "+fileName.length+" Songs");
1063    for (int i=0;i< fileName.length;i++)
1064    {
1065      tempFile = new File(dirString+File.separator+fileNamePath[i]+
1066                                    fileName[i]);
1067      /*if(tempFile.isDirectory() && recurse)
1068      {
1069        retVal += createWinampList(urlRoot,
1070                                   dirString+File.separator+fileName[i],
1071                                   true);
1072      }
1073      else */
1074      System.out.println("Filename="+tempFile.toString());
1075      if (fileName[i].trim().toLowerCase().endsWith(".mp3") ||
1076               fileName[i].trim().toLowerCase().endsWith(".ogg"))
1077      {
1078        retVal += "#EXTM3U:-1," + artistName + " - " + songTitle + "\n";
1079        retVal += urlRoot + fileNamePath[i] + fileName[i] + "\n";
1080      }
1081    }
1082    try
1083    {
1084      FileWriter fileWriter = new FileWriter(dirString + File.separator +
1085                                             winampFilename);
1086      fileWriter.write(retVal,0,retVal.length());
1087      fileWriter.flush();
1088      fileWriter.close();
1089    }
1090    catch (IOException ex)
1091    {
1092      lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
1093      lastErrorMsg += "\n<P>Unable to create WinAmp Playlist file for Directory ->" + dirString;
1094      lastErrorMsg += "\n<HR>";
1095     }
1096  }
1097  else
1098  {
1099    lastErrorMsg = "\n<P><B><I>Error Encountered:</I></B>";
1100    lastErrorMsg += "\n<P>Unable to initialize Directory for reading->" + dirString;
1101    lastErrorMsg += "\n<HR>";
1102  }
1103
1104
1105  return(retVal);
1106}
1107
1108
1109/** For Testing Purposes **/
1110public static void main (String [] args)
1111  {
1112    DirReadBean dirlist1 = new DirReadBean();
1113    dirlist1.initFileIndex();
1114    dirlist1.initFileName();
1115    dirlist1.setDirString("");
1116    String dir1 = "g:\\snd\\ogg\\";
1117    dirlist1.initDir(dir1, "/ogg", true); // true to recurse
1118    String aList = dirlist1.getTitledAuthorList("ogg");
1119    //System.out.println(aList);
1120
1121    String [] magNames = dirlist1.getArtistsNames();
1122    String currName = "";
1123    for (int i=0; i< magNames.length; i++)
1124    {
1125      currName = magNames[i];
1126      System.out.println(currName);
1127    }
1128
1129    //dirlist1 = new DirReadBean();
1130    //dirlist1.initFileIndex();
1131    //dirlist1.initFileName();
1132    //dirlist1.setDirString("");
1133    String playlist =
1134       createWinampList("http://warp2/ogg", dir1, true,"");
1135
1136    if (!playlist.equals(""))
1137      System.out.println("Playlist written to file.");
1138    else
1139      System.out.println(getLastErrorMessage());
1140  }
1141
1142
1143/*
1144Here is the revision log
1145------------------------
1146$Log: DirReadBean.java,v $
1147Revision 1.8  2002/05/02 22:32:45  tgutwin
1148Fixed Winamp list problems
1149Added recursive options
1150
1151Revision 1.7  2002/04/15 04:40:04  anonymous
1152
1153Added fields and methods to allow the getTitledAuthorList to ignore certain
1154files when parsing and preparing output.
1155
1156Revision 1.6  2002/03/27 20:08:18  anonymous
1157Trim the Artist Name Strings and added a A Name to each Artist Title
1158
1159Revision 1.5  2001/11/17 04:39:25  tgutwin
1160
1161Added a couple of get methods.
1162
1163Revision 1.4  2001/09/02 03:24:14  tgutwin
1164
1165Initial Rev of my custom DropDown Boxes.
1166
1167Revision 1.3  2001/08/08 23:36:21  tgutwin
1168
1169Added CVS Keywords.
1170
1171
1172*/
1173}
1174
1175
1176