/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: LibDirs.java
*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.io.input;
import javax.swing.filechooser.FileSystemView;
import javax.swing.filechooser.FileView;
import javax.swing.*;
import java.io.File;
import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.util.*;
/**
* Class for reading a text file that specifies
* additional library directories from which to
* read in library (elib) files.
*
* <p>
* LibDirs files have the following syntax:
* <p>
* * <comment text>
* <p>
* include <lib_dirs_file>
* <p>
* <library_directory>
*
* <p>
*/
public class LibDirs {
/** Default LibDirs file name */ private static String libDirsFile = "LIBDIRS";
/** List of library directories from LibDirs file*/ private static ArrayList<String> dirs = new ArrayList<String>();
/** List of libDirsFiles read (prevent recursion) */ private static ArrayList<String> libDirsFiles = new ArrayList<String>();
/** Creates a new instance of LibDirs */
LibDirs() {
}
/** return list of Lib Dirs
* @return ArrayList of lib dirs
*/
public static synchronized Iterator<String> getLibDirs() {
ArrayList<String> list = new ArrayList<String>(dirs);
return list.iterator();
}
/**
* Read in LibDirs file.
* @param dir the directory that may contain a LIBDIRS file
* @return true on error, or no LIBDIRS file found.
*/
public static synchronized boolean readLibDirs(String dir)
{
if (dir == null) return true;
String libDirFile = dir + File.separator + libDirsFile;
// read current working dir first, if set to do so
boolean error = false;
dirs.clear();
libDirsFiles.clear();
if (parseFile(libDirFile)) error = true;
return error;
}
/**
* parse a LIF file and read in libraries specified.
* @return true on error.
*/
private static boolean parseFile(String fileName)
{
if (fileName == null) return true;
BufferedReader in = null;
File file = new File(fileName);
try {
FileReader fr = new FileReader(file);
in = new BufferedReader(fr);
} catch (FileNotFoundException e) {
//System.out.println("Could not find file: " + fileName);
return true;
}
libDirsFiles.add(file.getAbsolutePath());
// parse file
boolean error = false;
int lineNumber = 0;
try {
String line;
while ( (line = in.readLine()) != null) {
if (parseLine(line, file)) {
System.out.println("Parse error: "+fileName+":"+lineNumber);
error = true;
lineNumber++;
}
}
in.close();
} catch (IOException e) {
error = true;
// System.out.println("IOError "+e.getMessage());
}
return error;
}
/**
* Parse one line of LIF file.
* @return true on error.
*/
private static boolean parseLine(String line, File libdirFile)
{
line = line.trim(); // remove leading/trailing whitespace
String[] words = line.split("\\s+"); // split by whitespace
if (words.length <= 0) return false; // nothing on line
if (words[0].equals("*")) return false; // comment
if (words[0].equals("include")) { // include statement
if (words.length != 2) return true;
// prevent recursive includes
File f = new File(words[1]);
if (libDirsFiles.contains(f.getAbsolutePath())) return true;
// read included LibDir file
return parseFile(words[1]);
}
// add dir to list, prepend current dir if relative path
String dir = words[0];
if (dir.startsWith(".")) {
dir = libdirFile.getParentFile().getAbsolutePath() + File.separator + dir;
}
dirs.add(dir);
return false;
}
// --------------------------------------------------------------
/**
* Allow JFileChooser to see libdir references as files. This should only
* be used when trying to open JELIB/ELIB libraries through a JFileChooser.
* We can't extend UnixFileSystemView or WindowsFileSystemView because they
* are private classes, so instead we must wrap them.
*/
public static class LibDirFileSystemView extends FileSystemView {
private final FileSystemView osView; // at run time java determines an OS-specific view
private final HashMap<String,File> libFiles; // key: absolute path; value: File
public LibDirFileSystemView(FileSystemView osView) {
this.osView = osView;
libFiles = new HashMap<String,File>();
}
public File createFileObject(File dir, String filename) { return osView.createFileObject(dir, filename); }
public File createFileObject(String path) { return osView.createFileObject(path); }
protected File createFileSystemRoot(File f) {
throw new Error("Unsupported operation"); // can't access protected method of osView
}
public File createNewFolder(File containingDir) throws IOException {
return osView.createNewFolder(containingDir);
}
public File getChild(File parent, String fileName) { return osView.getChild(parent, fileName); }
public File getDefaultDirectory() { return osView.getDefaultDirectory(); }
public synchronized File [] getFiles(File dir, boolean useFileHiding) {
File [] usual = osView.getFiles(dir, useFileHiding);
libFiles.clear();
if (LibDirs.readLibDirs(dir.getPath())) {
return usual;
}
// amalgamate all of the files
ArrayList<File> alllibfiles = new ArrayList<File>();
if (usual.length != 0) alllibfiles.addAll(Arrays.asList(usual));
for (Iterator<String> it = LibDirs.getLibDirs(); it.hasNext(); ) {
String str = it.next();
File libdir = new File(str);
if (!libdir.exists()) continue;
if (!libdir.isDirectory()) continue;
File [] files = osView.getFiles(libdir, useFileHiding);
//System.out.println("Reading files from dir "+str+", found "+files.length+" files.");
if (files.length == 0) continue;
alllibfiles.addAll(Arrays.asList(files));
for (int i=0; i<files.length; i++) {
libFiles.put(files[i].getAbsolutePath(), files[i]);
}
}
File [] all = new File[alllibfiles.size()];
for (int i=0; i<alllibfiles.size(); i++) {
File f = alllibfiles.get(i);
all[i] = f;
}
return all;
}
public synchronized boolean isLibFile(File f) {
if (f == null) return false;
if (libFiles.containsKey(f.getAbsolutePath())) return true;
return false;
}
public File getHomeDirectory() { return osView.getHomeDirectory(); }
public File getParentDirectory(File dir) { return osView.getParentDirectory(dir); }
public File [] getRoots() { return osView.getRoots(); }
public String getSystemDisplayName(File f) { return osView.getSystemDisplayName(f); }
public Icon getSystemIcon(File f) { return osView.getSystemIcon(f); }
public String getSystemTypeDescription(File f) { return osView.getSystemTypeDescription(f); }
public boolean isComputerNode(File dir) { return osView.isComputerNode(dir); }
public boolean isDrive(File dir) { return osView.isDrive(dir); }
public boolean isFileSystem(File f) { return osView.isFileSystem(f); }
public boolean isFileSystemRoot(File dir) { return osView.isFileSystemRoot(dir); }
public boolean isFloppyDrive(File dir) { return osView.isFloppyDrive(dir); }
public boolean isHiddenFile(File f) { return osView.isHiddenFile(f); }
public boolean isParent(File folder, File file) {
// all lib files should look like they are in the current dir
if (isLibFile(file)) { return true; }
return osView.isParent(folder, file);
}
public boolean isRoot(File f) { return osView.isRoot(f); }
public Boolean isTraversable(File f) { return osView.isTraversable(f); }
}
public static LibDirFileSystemView newLibDirFileSystemView(FileSystemView osView) { return new LibDirFileSystemView(osView); }
/**
* Allow File Chooser to see libdir references as files.
*/
public static class LibDirFileView extends FileView {
private LibDirFileSystemView view;
public LibDirFileView(LibDirFileSystemView view) {
this.view = view;
}
public String getName(File f) {
if (f == null) return null;
if (view.isLibFile(f)) return f.getName() + " [REF]";
return null;
}
}
}