diff options
author | Roman Kennke <roman@kennke.org> | 2006-10-30 13:19:49 +0000 |
---|---|---|
committer | Roman Kennke <roman@kennke.org> | 2006-10-30 13:19:49 +0000 |
commit | d562f9f0a899608bb155799a61300675cb0fd85f (patch) | |
tree | cae7433abb03fcadda7431a8588496eeb2c89ec8 | |
parent | dcc21101715f16a696c6d9715308d40ce6934693 (diff) | |
download | classpath-d562f9f0a899608bb155799a61300675cb0fd85f.tar.gz |
2006-10-30 Roman Kennke <kennke@aicas.com>
* java/awt/datatransfer/DataFlavor.java
(javaFileListFlavor): Don't explicitly specify class.
(plainTextFlavor): Don't explicitly specify class.
(mimeType): Changed to type MimeType. Remove final.
(representationClass): Remove final.
(DataFlavor): Don't do anything here.
(DataFlavor(Class,String,String)): Removed.
(DataFlavor(Class,String)): Initialize here.
(DataFlavor(String,String,ClassLoader)): Initialize in init().
(DataFlavor(String,String)): Initialize in init().
(DataFlavor(String)): Initialize in init().
(init): New initialization method.
(getMimeType): Delegate to MimeType.toString().
(getParameter(String,String)): Removed. Is now done in MimeType.
(getParameter(String)): Delegate to MimeType.
(getPrimaryType): Delegate to MimeType.
(getRepresentationClassFromMime): Removed.
(getRepresentationClassFromMimeThrows): Removed.
(getSubType): Delegate to MimeType.
(hashCode): Take MimeType.toString() for the hashCode.
(isFlavorRemoveObjectType): Return true only when representation
class is remove and serializable and the mime type is remote.
(isFlavorSerializedObjectType): Return true only when representation
class is serializable and the mime type is serialized.
(isMimeTypeEqual): Rewritten to delegate to MimeType.matches().
(isMimeTypeSerializedObject): Delegate to isMimeTypeEqual().
(readExternal): Implemented stub method.
(writeExternal): Implemented stub method.
* java/awt/datatransfer/MimeType.java: New helper class.
-rw-r--r-- | ChangeLog | 32 | ||||
-rw-r--r-- | java/awt/datatransfer/DataFlavor.java | 276 | ||||
-rw-r--r-- | java/awt/datatransfer/MimeType.java | 281 |
3 files changed, 457 insertions, 132 deletions
@@ -1,3 +1,35 @@ +2006-10-30 Roman Kennke <kennke@aicas.com> + + * java/awt/datatransfer/DataFlavor.java + (javaFileListFlavor): Don't explicitly specify class. + (plainTextFlavor): Don't explicitly specify class. + (mimeType): Changed to type MimeType. Remove final. + (representationClass): Remove final. + (DataFlavor): Don't do anything here. + (DataFlavor(Class,String,String)): Removed. + (DataFlavor(Class,String)): Initialize here. + (DataFlavor(String,String,ClassLoader)): Initialize in init(). + (DataFlavor(String,String)): Initialize in init(). + (DataFlavor(String)): Initialize in init(). + (init): New initialization method. + (getMimeType): Delegate to MimeType.toString(). + (getParameter(String,String)): Removed. Is now done in MimeType. + (getParameter(String)): Delegate to MimeType. + (getPrimaryType): Delegate to MimeType. + (getRepresentationClassFromMime): Removed. + (getRepresentationClassFromMimeThrows): Removed. + (getSubType): Delegate to MimeType. + (hashCode): Take MimeType.toString() for the hashCode. + (isFlavorRemoveObjectType): Return true only when representation + class is remove and serializable and the mime type is remote. + (isFlavorSerializedObjectType): Return true only when representation + class is serializable and the mime type is serialized. + (isMimeTypeEqual): Rewritten to delegate to MimeType.matches(). + (isMimeTypeSerializedObject): Delegate to isMimeTypeEqual(). + (readExternal): Implemented stub method. + (writeExternal): Implemented stub method. + * java/awt/datatransfer/MimeType.java: New helper class. + 2006-10-28 Roman Kennke <kennke@aicas.com> * javax/swing/TransferHandler.java diff --git a/java/awt/datatransfer/DataFlavor.java b/java/awt/datatransfer/DataFlavor.java index 9178c925a..58ff49f2d 100644 --- a/java/awt/datatransfer/DataFlavor.java +++ b/java/awt/datatransfer/DataFlavor.java @@ -46,6 +46,7 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInput; import java.io.ObjectOutput; +import java.io.OptionalDataException; import java.io.Reader; import java.io.Serializable; import java.io.StringReader; @@ -76,8 +77,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable * deals with bytes not chars. Use <code>getRederForText()</code>. */ public static final DataFlavor plainTextFlavor = - new DataFlavor(java.io.InputStream.class, - "text/plain; charset=unicode", + new DataFlavor("text/plain; charset=unicode; class=java.io.InputStream", "plain unicode text"); /** @@ -94,8 +94,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable * element of the list being a <code>java.io.File</code>. */ public static final DataFlavor javaFileListFlavor = - new DataFlavor(java.util.List.class, - "application/x-java-file-list; class=java.util.List", + new DataFlavor("application/x-java-file-list; class=java.util.List", "Java File List"); /** @@ -132,10 +131,10 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ // The MIME type for this flavor - private final String mimeType; + private MimeType mimeType; // The representation class for this flavor - private final Class representationClass; + private Class representationClass; // The human readable name of this flavor private String humanPresentableName; @@ -198,62 +197,6 @@ public class DataFlavor implements java.io.Externalizable, Cloneable throw new ClassNotFoundException(className); } - private static Class getRepresentationClassFromMimeThrows(String mimeString, - ClassLoader classLoader) - throws ClassNotFoundException - { - String classname = getParameter("class", mimeString); - if (classname != null) - return tryToLoadClass(classname, classLoader); - else - return java.io.InputStream.class; - } - - // Same as above, but wraps any ClassNotFoundExceptions - private static Class getRepresentationClassFromMime(String mimeString, - ClassLoader classLoader) - { - try - { - return getRepresentationClassFromMimeThrows(mimeString, classLoader); - } - catch(ClassNotFoundException cnfe) - { - IllegalArgumentException iae; - iae = new IllegalArgumentException("mimeString: " - + mimeString - + " classLoader: " - + classLoader); - iae.initCause(cnfe); - throw iae; - } - } - - /** - * Returns the value of the named MIME type parameter, or <code>null</code> - * if the parameter does not exist. Given the parameter name and the mime - * string. - * - * @param paramName The name of the parameter. - * @param mimeString The mime string from where the name should be found. - * - * @return The value of the parameter or null. - */ - private static String getParameter(String paramName, String mimeString) - { - int idx = mimeString.indexOf(paramName + "="); - if (idx == -1) - return(null); - - String value = mimeString.substring(idx + paramName.length() + 1); - - idx = value.indexOf(";"); - if (idx == -1) - return(value); - else - return(value.substring(0, idx)); - } - /** * XXX - Currently returns <code>plainTextFlavor</code>. */ @@ -321,31 +264,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public DataFlavor() { - mimeType = null; - representationClass = null; - humanPresentableName = null; - } - - /** - * Private constructor. - */ - private DataFlavor(Class representationClass, - String mimeType, - String humanPresentableName) - { - this.representationClass = representationClass; - this.mimeType = mimeType; - - // Do some simple validity checks - String type = getPrimaryType() + "/" + getSubType(); - if (type.indexOf('=') != -1 - || type.indexOf(';') != -1) - throw new IllegalArgumentException(mimeType); - - if (humanPresentableName != null) - this.humanPresentableName = humanPresentableName; - else - this.humanPresentableName = mimeType; + // Used for deserialization only, nothing to do here. } /** @@ -360,11 +279,21 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public DataFlavor(Class representationClass, String humanPresentableName) { - this(representationClass, - "application/x-java-serialized-object" - + "; class=" - + representationClass.getName(), - humanPresentableName); + if (representationClass == null) + throw new NullPointerException("representationClass must not be null"); + try + { + mimeType = new MimeType(javaSerializedObjectMimeType); + } + catch (MimeTypeParseException ex) + { + // Must not happen as we use a constant string. + assert false; + } + if (humanPresentableName == null) + humanPresentableName = javaSerializedObjectMimeType; + this.humanPresentableName = humanPresentableName; + this.representationClass = representationClass; } /** @@ -389,8 +318,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable ClassLoader classLoader) throws ClassNotFoundException { - this(getRepresentationClassFromMimeThrows(mimeType, classLoader), - mimeType, humanPresentableName); + init(mimeType, humanPresentableName, classLoader); } /** @@ -411,8 +339,17 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public DataFlavor(String mimeType, String humanPresentableName) { - this(getRepresentationClassFromMime (mimeType, null), - mimeType, humanPresentableName); + try + { + init(mimeType, humanPresentableName, getClass().getClassLoader()); + } + catch (ClassNotFoundException ex) + { + IllegalArgumentException iae = + new IllegalArgumentException("Class not found: " + ex.getMessage()); + iae.initCause(ex); + throw iae; + } } /** @@ -431,8 +368,54 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public DataFlavor(String mimeType) throws ClassNotFoundException { - this(getRepresentationClassFromMimeThrows(mimeType, null), - mimeType, null); + init(mimeType, null, getClass().getClassLoader()); + } + + /** + * Called by various constructors to initialize this object. + * + * @param mime the mime string + * @param humanPresentableName the human presentable name + * @param loader the class loader to use for loading the representation + * class + */ + private void init(String mime, String humanPresentableName, + ClassLoader loader) + throws ClassNotFoundException + { + if (mime == null) + throw new NullPointerException("The mime type must not be null"); + try + { + mimeType = new MimeType(mime); + } + catch (MimeTypeParseException ex) + { + IllegalArgumentException iae = + new IllegalArgumentException("Invalid mime type"); + iae.initCause(ex); + throw iae; + } + String className = mimeType.getParameter("class"); + if (className == null) + { + if (mimeType.getBaseType().equals(javaSerializedObjectMimeType)) + throw new IllegalArgumentException("Serialized object type must have" + + " a representation class parameter"); + else + representationClass = java.io.InputStream.class; + } + else + representationClass = tryToLoadClass(className, loader); + mimeType.addParameter("class", representationClass.getName()); + + if (humanPresentableName == null) + { + humanPresentableName = mimeType.getParameter("humanPresentableName"); + if (humanPresentableName == null) + humanPresentableName = mimeType.getBaseType(); + } + this.humanPresentableName = humanPresentableName; } /** @@ -442,7 +425,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public String getMimeType() { - return(mimeType); + return(mimeType.toString()); } /** @@ -472,11 +455,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public String getPrimaryType() { - int idx = mimeType.indexOf("/"); - if (idx == -1) - return(mimeType); - - return(mimeType.substring(0, idx)); + return(mimeType.getPrimaryType()); } /** @@ -486,15 +465,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public String getSubType() { - int start = mimeType.indexOf("/"); - if (start == -1) - return ""; - - int end = mimeType.indexOf(";", start + 1); - if (end == -1) - return mimeType.substring(start + 1); - else - return mimeType.substring(start + 1, end); + return mimeType.getSubType(); } /** @@ -510,7 +481,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable if ("humanPresentableName".equals(paramName)) return getHumanPresentableName(); - return getParameter(paramName, mimeType); + return mimeType.getParameter(paramName); } /** @@ -536,16 +507,22 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public boolean isMimeTypeEqual(String mimeType) { - String mime = getMimeType(); - int i = mime.indexOf(";"); - if (i != -1) - mime = mime.substring(0, i); - - i = mimeType.indexOf(";"); - if (i != -1) - mimeType = mimeType.substring(0, i); - - return mime.equals(mimeType); + if (mimeType == null) + throw new NullPointerException("mimeType must not be null"); + boolean equal = false; + try + { + if (this.mimeType != null) + { + MimeType other = new MimeType(mimeType); + equal = this.mimeType.matches(other); + } + } + catch (MimeTypeParseException ex) + { + // Return false in this case. + } + return equal; } /** @@ -570,7 +547,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public boolean isMimeTypeSerializedObject() { - return mimeType.startsWith(javaSerializedObjectMimeType); + return isMimeTypeEqual(javaSerializedObjectMimeType); } /** @@ -616,8 +593,8 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public boolean isFlavorSerializedObjectType() { - // FIXME: What is the diff between this and isMimeTypeSerializedObject? - return(mimeType.startsWith(javaSerializedObjectMimeType)); + return isRepresentationClassSerializable() + && isMimeTypeEqual(javaSerializedObjectMimeType); } /** @@ -628,7 +605,9 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public boolean isFlavorRemoteObjectType() { - return(mimeType.startsWith(javaRemoteObjectMimeType)); + return isRepresentationClassRemote() + && isRepresentationClassSerializable() + && isMimeTypeEqual(javaRemoteObjectMimeType); } /** @@ -769,7 +748,7 @@ public class DataFlavor implements java.io.Externalizable, Cloneable */ public int hashCode() { - return mimeType.toLowerCase().hashCode() ^ representationClass.hashCode(); + return mimeType.toString().hashCode() ^ representationClass.hashCode(); } /** @@ -823,7 +802,15 @@ public class DataFlavor implements java.io.Externalizable, Cloneable public void writeExternal(ObjectOutput stream) throws IOException, NotImplementedException { - // FIXME: Implement me + if (mimeType != null) + { + mimeType.addParameter("humanPresentableName", humanPresentableName); + stream.writeObject(mimeType); + mimeType.removeParameter("humanPresentableName"); + } + else + stream.writeObject(null); + stream.writeObject(representationClass); } @@ -837,9 +824,34 @@ public class DataFlavor implements java.io.Externalizable, Cloneable * cannot be found. */ public void readExternal(ObjectInput stream) - throws IOException, ClassNotFoundException, NotImplementedException + throws IOException, ClassNotFoundException { - // FIXME: Implement me + mimeType = (MimeType) stream.readObject(); + String className = null; + if (mimeType != null) + { + humanPresentableName = + mimeType.getParameter("humanPresentableName"); + mimeType.removeParameter("humanPresentableName"); + className = mimeType.getParameter("class"); + if (className == null) + throw new IOException("No class in mime type"); + } + try + { + representationClass = (Class) stream.readObject(); + } + catch (OptionalDataException ex) + { + if (ex.eof && ex.length == 0) + { + if (className != null) + representationClass = tryToLoadClass(className, + getClass().getClassLoader()); + } + else + throw ex; + } } /** diff --git a/java/awt/datatransfer/MimeType.java b/java/awt/datatransfer/MimeType.java new file mode 100644 index 000000000..438d78e9e --- /dev/null +++ b/java/awt/datatransfer/MimeType.java @@ -0,0 +1,281 @@ +/* MimeType.java -- A helper class for mime handling in DataFlavor + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath 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 2, or (at your option) +any later version. + +GNU Classpath 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 GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt.datatransfer; + +import java.io.Externalizable; +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.StringTokenizer; + +/** + * A helper class for mime handling in DataFlavor. + * + * A Mauve test for DataFlavor.writeExternal() shows that a non-public + * class java.awt.datatransfer.MimeType gets serialized. This class + * is mainly here for serialization compatibility. Of course, + * now that we have it here, we can just as well implement some + * mime handling facility here. + */ +class MimeType + implements Externalizable +{ + + /** + * The primary type. + */ + private String primaryType; + + /** + * The subtype. + */ + private String subType; + + /** + * Additional parameters to be appended to the mime string. + */ + private HashMap parameters; + + /** + * This is only here for deserialization. + */ + public MimeType() + { + parameters = new HashMap(); + } + + /** + * Creates a new MimeType object. + * + * @param mime the mime type + */ + MimeType(String mime) + throws MimeTypeParseException + { + this(); + parse(mime); + } + + /** + * Adds a mime parameter. + * + * @param param the parameter key + * @param value the parameter value + */ + void addParameter(String param, String value) + { + parameters.put(param, value); + } + + /** + * Removes the parameter with the specified key. + * + * @param param the parameter to remove + */ + void removeParameter(String param) + { + parameters.remove(param); + } + + /** + * Returns the parameter for the <code>key</code>. + * + * @param key the parameter key + * + * @return the parameter for the <code>key</code> + */ + String getParameter(String key) + { + return (String) parameters.get(key); + } + + /** + * Returns the primary type. + * + * @return the primary type + */ + String getPrimaryType() + { + return primaryType; + } + + String getSubType() + { + return subType; + } + + /** + * Returns the base type of this mime type. This is the primary + * type plus the subtype, separated by '/'. + * + * @return the base type of this mime type + */ + String getBaseType() + { + return primaryType + '/' + subType; + } + + /** + * Returns <code>true</code> if this mime type and another mime type + * match. This will be true when their primary types are equal, and their + * subtypes are equal (or when either subtype is * ). + * + * @param other the other mime type + * + * @return <code>true</code> if the mime types match, <code>false</code> + * otherwise + */ + boolean matches(MimeType other) + { + boolean match = false; + if (other != null) + { + match = primaryType.equals(other.primaryType) + && (subType.equals("*") || other.subType.equals("*") + || subType.equals(other.subType)); + } + return match; + } + + /** + * Serializes the mime type. + * + * @param in the input stream to read from + * + * @throws ClassNotFoundException not thrown here + * @throws IOException when something goes wrong on the input stream, + * or when the mime type can't be parsed + */ + public void readExternal(ObjectInput in) + throws ClassNotFoundException, IOException + { + String mime = in.readUTF(); + parameters.clear(); + try + { + parse(mime); + } + catch (MimeTypeParseException ex) + { + IOException ioEx = new IOException(); + ioEx.initCause(ex); + throw ioEx; + } + } + + /** + * Serializes this mime type. + * + * @param out the output stream + * + * @throws IOException when something goes wrong on the output stream + */ + public void writeExternal(ObjectOutput out) + throws IOException + { + out.writeUTF(toString()); + } + + /** + * Creates a string representation of this mime type. + * + * @return a string representation of this mime type + */ + public String toString() + { + StringBuilder s = new StringBuilder(); + s.append(primaryType); + s.append('/'); + s.append(subType); + if (parameters.size() > 0) + { + Set entries = parameters.entrySet(); + for (Iterator i = entries.iterator(); i.hasNext();) + { + s.append("; "); + Map.Entry entry = (Map.Entry) i.next(); + s.append(entry.getKey()); + s.append('='); + s.append(entry.getValue()); + } + } + return s.toString(); + } + + /** + * Parses the specified mime type string and initializes the fields + * of this object. + * + * @param mime the mime type string + */ + private void parse(String mime) + throws MimeTypeParseException + { + // FIXME: Maybe implement more sophisticated mime string parsing according + // to RFC 2045 and 2046. + StringTokenizer tokenizer = new StringTokenizer(mime); + try + { + primaryType = tokenizer.nextToken("/"); + subType = tokenizer.nextToken("/;"); + } + catch (NoSuchElementException ex) + { + throw new MimeTypeParseException("Expected / separator"); + } + + // Add any parameters. + while (tokenizer.hasMoreTokens()) + { + String keyValuePair = tokenizer.nextToken(";"); + int i = keyValuePair.indexOf('='); + if (i == -1) + throw new MimeTypeParseException("Expected = as parameter separator"); + String key = keyValuePair.substring(0, i).trim(); + String value = keyValuePair.substring(i + 1).trim(); + parameters.put(key, value); + } + } + +} |