/*
*
* FileFilterExtensions.java, a FileFilter implementation that
* filters files by their extension.
* Copyright (C) 2004 - 2011 Achim Westermann, created on 01.07.2004, 12:18:29
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* If you modify or optimize the code in a useful way please let me know.
* Achim.Westermann@gmx.de
*
*/
package info.monitorenter.gui.chart.io;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringTokenizer;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileSystemView;
/**
* <p>
* Configureable implementation of {@link javax.swing.filechooser.FileFilter}
* that filters files by their extension (e.g.: ".txt").
* </p>
* <p>
* The extension Strings are provided to the constructor (no configuration of
* initialized instance provided yet) and have to be the sole extension without
* the dot.
* </p>
* <p>
* This class is most often used to configure {@link javax.swing.JFileChooser}
* dialogs. Therefore it accepts all directories to allow browsing.
* </p>
* <h3>Example usage:</h3>
* <p>
*
* <code>
*
* ...
* JFileChooser fileChooser = new JFileChooser();
* FileFilter soundFileFilter = new FileFilterExtensions(new String[]{"wav","mp3"});
* fileChooser.setFileFilter(soundFileFilter);
* ...
*
* </code>
*
* </p>
*
* @author <a href="mailto:Achim.Westermann@gmx.de>Achim Westermann </a>
*/
public final class FileFilterExtensions
extends FileFilter implements INameFilter {
/** Filename extensions to filter for. */
private String[] m_extensions;
/** Flag for windows OS. */
private boolean m_isWindows = false;
/**
* Creates an instance that will accept files with the given extensions.
* <p>
*
* @param extensionsWithoutDot
* A String[] containing extension strings without the dot like:
* <nobr><code>new String[]{"bat","txt","dict"}</code> </nobr>.
* @throws IllegalArgumentException
* if the given extensions are inivalid.
*/
public FileFilterExtensions(final String[] extensionsWithoutDot) throws IllegalArgumentException {
this.verify(extensionsWithoutDot);
this.m_extensions = new String[extensionsWithoutDot.length];
System.arraycopy(extensionsWithoutDot, 0, this.m_extensions, 0, extensionsWithoutDot.length);
this.m_isWindows = this.isWindows();
}
/**
* @see javax.swing.filechooser.FileFilter#accept(java.io.File)
*/
@Override
public boolean accept(final File pathname) {
boolean result;
if (pathname.isDirectory()) {
result = true;
} else {
result = this.acceptNoDirectory(pathname.getAbsolutePath());
}
return result;
}
/**
* @see INameFilter#accept(String)
*/
public boolean accept(final String urlstring) {
boolean result;
if (this.isDirectory(urlstring)) {
result = true;
} else {
result = this.acceptNoDirectory(urlstring);
}
return result;
}
/**
* Accept method used for files.
* <p>
*
* @param noDirFileNoURL
* the path to the file.
* @return true if the file denoted by the given path is accepted.
*/
private boolean acceptNoDirectory(final String noDirFileNoURL) {
boolean ret = false;
// search for extension without dot.
StringTokenizer tokenizer = new StringTokenizer(noDirFileNoURL, ".");
// a dot, because verify will not allow these
String extension = "no.txt";
// tokens: won't accept, if no extension in
// pathname.
while (tokenizer.hasMoreElements()) {
extension = tokenizer.nextToken();
}
for (int i = this.m_extensions.length - 1; i >= 0; i--) {
if (this.m_extensions[i].equals(extension)) {
ret = true;
break;
}
}
return ret;
}
/**
* @see javax.swing.filechooser.FileFilter#getDescription()
*/
@Override
public String getDescription() {
StringBuffer ret = new StringBuffer();
int len = this.m_extensions.length;
for (int i = 0; i < len; i++) {
ret.append("*.").append(this.m_extensions[i]);
if (i < (len - 1)) {
ret.append(",");
}
}
return ret.toString();
}
/**
* Returns true if the given String denotes a directory.
* <p>
*
* @param urlstring
* the url format String pointing to a file.
* @return true if the given String denotes a directory.
*/
private boolean isDirectory(final String urlstring) {
boolean ret = false;
boolean isURL = false;
try {
// try, if URL (expensive):
new URL(urlstring);
isURL = true;
} catch (MalformedURLException e) {
// nop.
}
int lastDot = urlstring.lastIndexOf('.');
int lastSeparator;
// Could be minimized but is more talking this way.
if (isURL) {
lastSeparator = urlstring.lastIndexOf('/');
} else {
if (this.m_isWindows) {
lastSeparator = urlstring.lastIndexOf('\\');
} else {
lastSeparator = urlstring.lastIndexOf('/');
}
}
if (lastSeparator == -1) {
if (lastDot == -1) {
// top host without a path.
ret = true;
} else {
ret = false;
}
} else {
if (lastDot == -1) {
ret = true;
} else if (lastDot > (lastSeparator + 1)) {
ret = false;
} else {
ret = true;
}
}
return ret;
}
/**
* Needed for {@link #isDirectory(String)}: We cannot use
* {@link System#getProperty(java.lang.String)} to determine file separators
* in applet context. That would possibly throw an SecurityAccessException.
* <p>
*
* @return true if current OS is windows.
*/
private boolean isWindows() {
boolean ret = false;
File[] roots = FileSystemView.getFileSystemView().getRoots();
for (int i = 0; i < roots.length; i++) {
if (roots[i].getAbsolutePath().indexOf(':') != -1) {
ret = true;
break;
}
}
return ret;
}
/**
* Verifies the given extensions for valid format.
* <p>
*
* @param extensions
* The array with the Strings of extensions.
* @throws IllegalArgumentException
* If a String of the array is null or contains a dot ('.').
*/
private void verify(final String[] extensions) throws IllegalArgumentException {
String current;
StringBuffer msg = new StringBuffer();
for (int i = extensions.length - 1; i >= 0; i--) {
current = extensions[i];
if (current == null) {
msg.append("Extension at index " + i + " is null!\n");
} else if (current.indexOf('.') != -1) {
msg.append("Extension \"" + current + "\" contains a dot!\n");
}
}
if (msg.length() > 0) {
throw new IllegalArgumentException(msg.toString());
}
}
}