Applications often need to work out the type of a file, to see if it is a text file, an HTML document, an executable, etc. This can be done in two ways:
file command use the
second method, and have a complex description file (such
as /etc/magic or /usr/share/magic)
to aid in this. Many other applications such as Web browsers,
mail readers (and even some operating systems!) use the first
method and work out a file's type based on its name.
A common file classification is into MIME types such as
text/plain and image/gif. There 
are tables of ``official'' MIME types (unofficial ones can
be added on an 
application/postscript          ai eps ps
application/rtf                 rtf
application/zip                 zip
image/gif                       gif
image/jpeg                      jpeg jpg jpe
text/html                       html htm
text/plain                      txt
and are stored in files for applications to access.
This storage of tables separate from the applications that would use them is rated as bad from the O/O point of view, since each application would need to have code to interpret the tables. The multiplicity of these tables and the ability of users to modify them makes this a maintenance problem. It would be better to encapsulate at least the filename to MIME type mapping table in an object. We define a MIME class
/**
 * MIMEType.java
 *
 *
 * Created: Mon Mar 15 22:09:13 1999
 *
 * @author Jan Newmarch
 * @version
 */
public class MIMEType  {
    /**
     * A MIME type is made up of 2 parts
     * contentType/subtype
     */    
    protected String contentType;
    protected String subtype;
    public MIMEType(String type) {
	int slash = type.indexOf('/');
	contentType = type.substring(0, slash-1);
	subtype = type.substring(slash+1, type.length());
    }
    
    public MIMEType(String contentType, String subtype) {
	this.contentType = contentType;
	this.subtype = subtype;
    }
    public String toString() {
	return contentType + "/" + subtype;
    }
} // MIMEType
and a mapping class
import MIMEType;
/**
 * FileClassifier.java
 *
 *
 * Created: Mon Mar 15 22:18:59 1999
 *
 * @author Jan Newmarch
 * @version
 */
public class FileClassifier  {
    
    static MIMEType getMIMEType(String fileName) {
	if (fileName.endsWith(".gif")) {
            return new MIMEType("image", "gif");
        } else if (fileName.endsWith(".jpeg")) {
            return new MIMEType("image", "jpeg");
        } else if (fileName.endsWith(".mpg")) {
            return new MIMEType("video", "mpeg");
        } else if (fileName.endsWith(".txt")) {
            return new MIMEType("text", "plain");
        } else if (fileName.endsWith(".html")) {
            return new MIMEType("text", "html");
        } else
	    // fill in lots of other types,
	    // but eventually give up and
            return null;
    }
} // FileClassifier
This mapping class has no constructors, as it justs acts as a
lookup table via its static method getMIMEType().
Applications may make use these classes as they stand, by simply
compiling with them and having the class files available at
runtime. This will still result in duplication throughout JVMs,
possible multiple copies of the class files, and potentially 
severe maintenance problems if applications need to be compiled.
it may be better to have the FileClassifier as a
network service. What will be involved in this?
If we wish to make a version of FileClassifier available
across the network, there are a number of options
In the form given above, the FileClassifier is basically
just a lookup table, with one static method. There is no need to
create instances of this type, and this could have been eliminated
as a possibility by declaring the constructor as private:
    private FileClassifier() {
    }
If we want to make this into a service that will be exported, we have
to make a couple of changes to this. Firstly, we will need to separate
out an interface class FileClassifier and at least one
implementation class which we shall here give as
FileClassifierImpl. Now interfaces cannot have 
static methods, so we shall have to turn the method into
a public instance method. In addition, a class object for this
interface, and later instances implementing this will need to be
shipped around by RMI, so it should extend Serializable
package option1;
import java.io.Serializable;
/**
 * FileClassifier.java
 *
 *
 * Created: Wed Mar 17 14:14:36 1999
 *
 * @author Jan Newmarch
 * @version
 */
public interface FileClassifier extends Serializable {
    
    public MIMEType getMIMEType(String fileName);
    
} // FileClasssifier
The implementation of this is straightforward
package option1;
/**
 * FileClassifierImpl.java
 *
 *
 * Created: Wed Mar 17 14:22:13 1999
 *
 * @author Jan Newmarch
 * @version
 */
public class FileClassifierImpl implements FileClassifier {
    public MIMEType getMIMEType(String fileName) {
        if (fileName.endsWith(".gif")) {
            return new MIMEType("image", "gif");
        } else if (fileName.endsWith(".jpeg")) {
            return new MIMEType("image", "jpeg");
        } else if (fileName.endsWith(".mpg")) {
            return new MIMEType("video", "mpeg");
        } else if (fileName.endsWith(".txt")) {
            return new MIMEType("text", "plain");
        } else if (fileName.endsWith(".html")) {
            return new MIMEType("text", "html");
        } else
            // fill in lots of other types,
            // but eventually give up and
            return null;
    }
    public FileClassifierImpl() {
	// empty
    }
    
} // FileClassifierImpl
The class MIMEType does not need to be moved around, so
its definition remains unaltered
package option1;
/**
 * MIMEType.java
 *
 *
 * Created: Wed Mar 17 14:17:32 1999
 *
 * @author Jan Newmarch
 * @version
 */
public class MIMEType  {
    /**
     * A MIME type is made up of 2 parts
     * contentType/subtype
     */    
    protected String contentType;
    protected String subtype;
    public MIMEType(String type) {
        int slash = type.indexOf('/');
        contentType = type.substring(0, slash-1);
        subtype = type.substring(slash+1, type.length());
    }
    
    public MIMEType(String contentType, String subtype) {
        this.contentType = contentType;
        this.subtype = subtype;
    }
    public String toString() {
        return contentType + "/" + subtype;
    }
    
} // MIMEType
The server for this just needs to create an instance of the exportable
service and register this. Note that this server only sticks around
for 10 seconds (10,000 milliseconds) but it requests that the exported
service should last forever (Lease.FOREVER. 
If the lease request is granted, then there is no need for the server 
to hang around longer than needed to upload the exported service.