/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad.data;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.util.Enumeration;
import visad.Data;
import visad.DataImpl;
import visad.VisADException;
public class FunctionFormFamily
extends FormFamily
{
public FunctionFormFamily(String name)
{
super(name);
}
/**
* Base class which tries to perform an operation on an object
* using the first valid Form.
*/
abstract class FormFunction
{
/**
* Return 'true' if this object's name applies to the given node.
*/
abstract boolean check(FormFileInformer node);
/**
* Return an InputStream for the object.
*
* Used to read in the first block of the object.
*/
abstract InputStream getStream() throws IOException;
/**
* The operation to be performed on the object.
*/
abstract boolean function(FormNode node);
/**
* Perform an operation on an object
* using the first valid Form.
*
* If a Form successfully performs the operation, return 'true'.
*/
public boolean run()
throws IOException
{
// see if we can guess the file type based on the name
for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
FormNode node = (FormNode)en.nextElement();
if (node instanceof FormFileInformer) {
// WLH 19 Feb 2000 - switch order of try and check
// needed for HDF5
try {
if (check((FormFileInformer) node)) {
if (function(node)) {
return true;
}
}
} catch (Exception e) {
} catch (Error e) {
// WLH 19 Feb 2000 - needed for HDF5
}
}
}
// get the first block of data from the file
byte[] block = new byte[2048];
InputStream is = getStream();
if (is != null) {
is.read(block);
is.close();
// see if we can guess the file type based on first block of data
for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
FormNode node = (FormNode)en.nextElement();
if (node instanceof FormFileInformer) {
// WLH 19 Feb 2000 - switch order of try and check
// needed for HDF5
try {
if (((FormFileInformer )node).isThisType(block)) {
if (function(node)) {
return true;
}
}
} catch (Exception e) {
} catch (Error e) {
// WLH 19 Feb 2000 - needed for HDF5
}
}
}
}
// use the brute-force method of checking all the forms
for (Enumeration en = forms.elements(); en.hasMoreElements(); ) {
FormNode node = (FormNode)en.nextElement();
try {
if (function(node)) {
return true;
}
} catch (Exception e) {
} catch (UnsatisfiedLinkError ule) {
}
}
return false;
}
}
/**
* Perform an operation on a local file object
* using the first valid Form.
*/
abstract class FileFunction
extends FormFunction
{
String name;
public FileFunction()
{
name = null;
}
boolean check(FormFileInformer node)
{
return node.isThisType(name);
}
InputStream getStream()
throws IOException
{
return new FileInputStream(name);
}
}
/**
* Save a Data object to a local file
* using the first valid Form.
*/
class SaveForm
extends FileFunction
{
private Data data;
private boolean replace;
public SaveForm(String name, Data data, boolean replace)
{
this.name = name;
this.data = data;
this.replace = replace;
}
boolean function(FormNode node)
{
try {
node.save(name, data, replace);
} catch (Exception e) {
return false;
}
return true;
}
InputStream getStream()
throws IOException
{
FileInputStream stream;
try {
stream = new FileInputStream(name);
} catch (FileNotFoundException fnfe) {
stream = null;
}
return stream;
}
}
/**
* Add a Data object to an existing local file
* using the first valid Form.
*/
class AddForm
extends FileFunction
{
private Data data;
private boolean replace;
public AddForm(String name, Data data, boolean replace)
{
this.name = name;
this.data = data;
this.replace = replace;
}
boolean function(FormNode node)
{
try {
node.add(name, data, replace);
} catch (Exception e) {
return false;
}
return true;
}
}
/**
* Read a Data object from a local file
* using the first valid Form.
*/
class OpenStringForm
extends FileFunction
{
private DataImpl data;
public OpenStringForm(String name)
{
this.name = name;
data = null;
}
boolean function(FormNode node)
{
try {
data = node.open(name);
} catch (OutOfMemoryError t) { // WLH 5 Feb 99
throw t;
} catch (Throwable t) {
return false;
}
return true;
}
public DataImpl getData()
{
return data;
}
}
/**
* Perform an operation on a remote file object
* using the first valid Form.
*/
abstract class URLFunction
extends FormFunction
{
URL url;
public URLFunction()
{
url = null;
}
boolean check(FormFileInformer node)
{
// try both file part of URL and full URL
return (node.isThisType(url.getFile()) ||
node.isThisType(url.toString()));
}
InputStream getStream()
throws IOException
{
return url.openStream();
}
}
/**
* Read a Data object from a remote file
* using the first valid Form.
*/
class OpenURLForm
extends URLFunction
{
/* CTR: 13 Oct 1998
private URL url;
*/
private DataImpl data;
public OpenURLForm(URL url)
{
this.url = url;
data = null;
}
boolean function(FormNode node)
{
try {
data = node.open(url);
} catch (Throwable t) {
return false;
}
return true;
}
public DataImpl getData()
{
return data;
}
}
/**
* Save a Data object using the first appropriate Form.
*/
public synchronized void save(String id, Data data, boolean replace)
throws BadFormException, RemoteException, IOException, VisADException
{
SaveForm s = new SaveForm(id, data, replace);
if (!s.run()) {
throw new BadFormException("Data object not compatible with \"" +
getName() + "\" data family");
}
}
/**
* Add data to an existing data object using the first appropriate Form.
*/
public synchronized void add(String id, Data data, boolean replace)
throws BadFormException
{
AddForm a = new AddForm(id, data, replace);
try {
if (a.run()) {
return;
}
} catch (IOException e) {
}
throw new BadFormException("Data object not compatible with \"" +
getName() + "\" data family");
}
/**
* Open a local data object using the first appropriate Form.
*/
public synchronized DataImpl open(String id)
throws BadFormException, VisADException
{
// Garbage in, garbage out
if (id == null) {
return null;
}
// try to build a URL from the string
URL url;
try {
url = new URL(id);
} catch (MalformedURLException mue) {
url = null;
}
DataImpl data = null;
// if we got a URL, try to extract a Data object from it
if (url != null) {
OpenURLForm u = new OpenURLForm(url);
try {
if (!u.run()) {
data = null;
} else {
data = u.getData();
}
} catch (Exception e) {
data = null;
}
}
// if we didn't get a Data object, look for a filename
String file = null;
if (data == null) {
if (url == null) {
file = id;
} else if (url.getProtocol() == "file") {
file = url.getFile();
// if file looks like it starts with a Windows drive spec...
if (file.length() > 2 && file.charAt(2) == ':' &&
file.charAt(0) == '/')
{
file = file.substring(1);
}
}
}
// if we found a filename, try to open it
if (file != null) {
OpenStringForm o = new OpenStringForm(file);
try {
if (!o.run()) {
data = null;
} else {
data = o.getData();
}
} catch (IOException ioe) {
data = null;
}
}
// puke if we didn't find a data object
if (data == null) {
if (file != null && !new java.io.File(file).exists()) {
throw new BadFormException("No such data object \"" + id + "\"");
}
throw new BadFormException("Data object \"" + id +
"\" not compatible with \"" + getName() +
"\" data family");
}
return data;
}
/**
* Open a remote data object using the first appropriate Form.
*/
public synchronized DataImpl open(URL url)
throws BadFormException, IOException, VisADException
{
OpenURLForm o = new OpenURLForm(url);
if (!o.run()) {
throw new BadFormException("Data object \"" + url +
"\" not compatible with \"" + getName() +
"\" data family");
}
return o.getData();
}
}