8025152: Enhance activation set up

8028388: 9 jaxws tests failed in nightly build with java.lang.ClassCastException

Fix also reviewed by Bill Shannon, Alexander Fomin

Reviewed-by: dfuchs, hawtin, mgrebac
This commit is contained in:
Bill Shannon 2013-12-15 23:35:45 +01:00 committed by Miroslav Kos
parent 87a0f4a044
commit 43ea1b56bd
8 changed files with 158 additions and 127 deletions

View File

@ -25,6 +25,9 @@
package javax.activation;
import java.util.Map;
import java.util.WeakHashMap;
/**
* The CommandMap class provides an interface to a registry of
@ -38,6 +41,8 @@ package javax.activation;
*/
public abstract class CommandMap {
private static CommandMap defaultCommandMap = null;
private static Map<ClassLoader,CommandMap> map =
new WeakHashMap<ClassLoader,CommandMap>();
/**
* Get the default CommandMap.
@ -56,11 +61,18 @@ public abstract class CommandMap {
*
* @return the CommandMap
*/
public static CommandMap getDefaultCommandMap() {
if (defaultCommandMap == null)
defaultCommandMap = new MailcapCommandMap();
public static synchronized CommandMap getDefaultCommandMap() {
if (defaultCommandMap != null)
return defaultCommandMap;
return defaultCommandMap;
// fetch per-thread-context-class-loader default
ClassLoader tccl = SecuritySupport.getContextClassLoader();
CommandMap def = map.get(tccl);
if (def == null) {
def = new MailcapCommandMap();
map.put(tccl, def);
}
return def;
}
/**
@ -71,7 +83,7 @@ public abstract class CommandMap {
* @exception SecurityException if the caller doesn't have permission
* to change the default
*/
public static void setDefaultCommandMap(CommandMap commandMap) {
public static synchronized void setDefaultCommandMap(CommandMap commandMap) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
try {
@ -79,13 +91,16 @@ public abstract class CommandMap {
security.checkSetFactory();
} catch (SecurityException ex) {
// otherwise, we also allow it if this code and the
// factory come from the same class loader (e.g.,
// factory come from the same (non-system) class loader (e.g.,
// the JAF classes were loaded with the applet classes).
if (CommandMap.class.getClassLoader() !=
if (CommandMap.class.getClassLoader() == null ||
CommandMap.class.getClassLoader() !=
commandMap.getClass().getClassLoader())
throw ex;
}
}
// remove any per-thread-context-class-loader CommandMap
map.remove(SecuritySupport.getContextClassLoader());
defaultCommandMap = commandMap;
}

View File

@ -368,7 +368,12 @@ public class DataHandler implements Transferable {
// if it's not set, set it...
if (transferFlavors == emptyFlavors)
transferFlavors = getDataContentHandler().getTransferDataFlavors();
return transferFlavors;
if (transferFlavors == emptyFlavors)
return transferFlavors;
else
return transferFlavors.clone();
}
/**

View File

@ -26,6 +26,8 @@
package javax.activation;
import java.io.File;
import java.util.Map;
import java.util.WeakHashMap;
/**
* The FileTypeMap is an abstract class that provides a data typing
@ -48,6 +50,8 @@ import java.io.File;
public abstract class FileTypeMap {
private static FileTypeMap defaultMap = null;
private static Map<ClassLoader,FileTypeMap> map =
new WeakHashMap<ClassLoader,FileTypeMap>();
/**
* The default constructor.
@ -78,11 +82,11 @@ public abstract class FileTypeMap {
* Sets the default FileTypeMap for the system. This instance
* will be returned to callers of getDefaultFileTypeMap.
*
* @param map The FileTypeMap.
* @param fileTypeMap The FileTypeMap.
* @exception SecurityException if the caller doesn't have permission
* to change the default
*/
public static void setDefaultFileTypeMap(FileTypeMap map) {
public static synchronized void setDefaultFileTypeMap(FileTypeMap fileTypeMap) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
try {
@ -90,14 +94,17 @@ public abstract class FileTypeMap {
security.checkSetFactory();
} catch (SecurityException ex) {
// otherwise, we also allow it if this code and the
// factory come from the same class loader (e.g.,
// factory come from the same (non-system) class loader (e.g.,
// the JAF classes were loaded with the applet classes).
if (FileTypeMap.class.getClassLoader() !=
map.getClass().getClassLoader())
if (FileTypeMap.class.getClassLoader() == null ||
FileTypeMap.class.getClassLoader() !=
fileTypeMap.getClass().getClassLoader())
throw ex;
}
}
defaultMap = map;
// remove any per-thread-context-class-loader FileTypeMap
map.remove(SecuritySupport.getContextClassLoader());
defaultMap = fileTypeMap;
}
/**
@ -109,10 +116,17 @@ public abstract class FileTypeMap {
* @return The default FileTypeMap
* @see javax.activation.FileTypeMap#setDefaultFileTypeMap
*/
public static FileTypeMap getDefaultFileTypeMap() {
// XXX - probably should be synchronized
if (defaultMap == null)
defaultMap = new MimetypesFileTypeMap();
return defaultMap;
public static synchronized FileTypeMap getDefaultFileTypeMap() {
if (defaultMap != null)
return defaultMap;
// fetch per-thread-context-class-loader default
ClassLoader tccl = SecuritySupport.getContextClassLoader();
FileTypeMap def = map.get(tccl);
if (def == null) {
def = new MimetypesFileTypeMap();
map.put(tccl, def);
}
return def;
}
}

View File

@ -120,11 +120,7 @@ import com.sun.activation.registries.LogSupport;
public class MailcapCommandMap extends CommandMap {
/*
* We manage a collection of databases, searched in order.
* The default database is shared between all instances
* of this class.
* XXX - Can we safely share more databases between instances?
*/
private static MailcapFile defDB = null;
private MailcapFile[] DB;
private static final int PROG = 0; // programmatically added entries
@ -164,14 +160,10 @@ public class MailcapCommandMap extends CommandMap {
loadAllResources(dbv, "META-INF/mailcap");
LogSupport.log("MailcapCommandMap: load DEF");
synchronized (MailcapCommandMap.class) {
// see if another instance has created this yet.
if (defDB == null)
defDB = loadResource("/META-INF/mailcap.default");
}
mf = loadResource("/META-INF/mailcap.default");
if (defDB != null)
dbv.add(defDB);
if (mf != null)
dbv.add(mf);
DB = new MailcapFile[dbv.size()];
DB = (MailcapFile[])dbv.toArray(DB);

View File

@ -69,11 +69,7 @@ import com.sun.activation.registries.LogSupport;
public class MimetypesFileTypeMap extends FileTypeMap {
/*
* We manage a collection of databases, searched in order.
* The default database is shared between all instances
* of this class.
* XXX - Can we safely share more databases between instances?
*/
private static MimeTypeFile defDB = null;
private MimeTypeFile[] DB;
private static final int PROG = 0; // programmatically added entries
@ -114,14 +110,10 @@ public class MimetypesFileTypeMap extends FileTypeMap {
loadAllResources(dbv, "META-INF/mime.types");
LogSupport.log("MimetypesFileTypeMap: load DEF");
synchronized (MimetypesFileTypeMap.class) {
// see if another instance has created this yet.
if (defDB == null)
defDB = loadResource("/META-INF/mimetypes.default");
}
mf = loadResource("/META-INF/mimetypes.default");
if (defDB != null)
dbv.addElement(defDB);
if (mf != null)
dbv.addElement(mf);
DB = new MimeTypeFile[dbv.size()];
dbv.copyInto(DB);

View File

@ -62,61 +62,6 @@ public class AttachmentPartImpl extends AttachmentPart {
Logger.getLogger(LogDomainConstants.SOAP_DOMAIN,
"com.sun.xml.internal.messaging.saaj.soap.LocalStrings");
static {
try {
CommandMap map = CommandMap.getDefaultCommandMap();
if (map instanceof MailcapCommandMap) {
MailcapCommandMap mailMap = (MailcapCommandMap) map;
String hndlrStr = ";;x-java-content-handler=";
mailMap.addMailcap(
"text/xml"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler");
mailMap.addMailcap(
"application/xml"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler");
mailMap.addMailcap(
"application/fastinfoset"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.FastInfosetDataContentHandler");
/* Image DataContentHandler handles all image types
mailMap.addMailcap(
"image/jpeg"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.JpegDataContentHandler");
mailMap.addMailcap(
"image/gif"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.GifDataContentHandler"); */
/*mailMap.addMailcap(
"multipart/*"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.MultipartDataContentHandler");*/
mailMap.addMailcap(
"image/*"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.ImageDataContentHandler");
mailMap.addMailcap(
"text/plain"
+ hndlrStr
+ "com.sun.xml.internal.messaging.saaj.soap.StringDataContentHandler");
} else {
throw new SOAPExceptionImpl("Default CommandMap is not a MailcapCommandMap");
}
} catch (Throwable t) {
log.log(
Level.SEVERE,
"SAAJ0508.soap.cannot.register.handlers",
t);
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new RuntimeException(t.getLocalizedMessage());
}
}
};
private final MimeHeaders headers;
private MimeBodyPart rawContent = null;
private DataHandler dataHandler = null;
@ -126,6 +71,12 @@ public class AttachmentPartImpl extends AttachmentPart {
public AttachmentPartImpl() {
headers = new MimeHeaders();
// initialization from here should cover most of cases;
// if not, it would be necessary to call
// AttachmentPartImpl.initializeJavaActivationHandlers()
// explicitly by programmer
initializeJavaActivationHandlers();
}
public AttachmentPartImpl(MIMEPart part) {
@ -619,4 +570,43 @@ public class AttachmentPartImpl extends AttachmentPart {
return headers;
}
public static void initializeJavaActivationHandlers() {
// DataHandler.writeTo() may search for DCH. So adding some default ones.
try {
CommandMap map = CommandMap.getDefaultCommandMap();
if (map instanceof MailcapCommandMap) {
MailcapCommandMap mailMap = (MailcapCommandMap) map;
// registering our DCH since javamail's DCH doesn't handle
if (!cmdMapInitialized(mailMap)) {
mailMap.addMailcap("text/xml;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler");
mailMap.addMailcap("application/xml;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler");
mailMap.addMailcap("application/fastinfoset;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.FastInfosetDataContentHandler");
mailMap.addMailcap("multipart/*;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.MultipartDataContentHandler");
mailMap.addMailcap("image/*;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.ImageDataContentHandler");
mailMap.addMailcap("text/plain;;x-java-content-handler=com.sun.xml.internal.messaging.saaj.soap.StringDataContentHandler");
}
}
} catch (Throwable t) {
// ignore the exception.
}
}
private static boolean cmdMapInitialized(MailcapCommandMap mailMap) {
// checking fastinfoset handler, since this one is specific to SAAJ
CommandInfo[] commands = mailMap.getAllCommands("application/fastinfoset");
if (commands == null || commands.length == 0) {
return false;
}
String saajClassName = "com.sun.xml.internal.ws.binding.FastInfosetDataContentHandler";
for (CommandInfo command : commands) {
String commandClass = command.getCommandClass();
if (saajClassName.equals(commandClass)) {
return true;
}
}
return false;
}
}

View File

@ -37,6 +37,9 @@ import com.sun.xml.internal.ws.client.HandlerConfiguration;
import com.sun.xml.internal.ws.developer.MemberSubmissionAddressingFeature;
import com.sun.xml.internal.ws.developer.BindingTypeFeature;
import javax.activation.CommandInfo;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceFeature;
@ -151,12 +154,61 @@ public abstract class BindingImpl implements WSBinding {
return addressingVersion;
}
public final
@NotNull
Codec createCodec() {
public final Codec createCodec() {
// initialization from here should cover most of cases;
// if not, it would be necessary to call
// BindingImpl.initializeJavaActivationHandlers()
// explicitly by programmer
initializeJavaActivationHandlers();
return bindingId.createEncoder(this);
}
public static void initializeJavaActivationHandlers() {
// DataHandler.writeTo() may search for DCH. So adding some default ones.
try {
CommandMap map = CommandMap.getDefaultCommandMap();
if (map instanceof MailcapCommandMap) {
MailcapCommandMap mailMap = (MailcapCommandMap) map;
// registering our DCH since javamail's DCH doesn't handle
if (!cmdMapInitialized(mailMap)) {
mailMap.addMailcap("text/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler");
mailMap.addMailcap("application/xml;;x-java-content-handler=com.sun.xml.internal.ws.encoding.XmlDataContentHandler");
mailMap.addMailcap("image/*;;x-java-content-handler=com.sun.xml.internal.ws.encoding.ImageDataContentHandler");
mailMap.addMailcap("text/plain;;x-java-content-handler=com.sun.xml.internal.ws.encoding.StringDataContentHandler");
}
}
} catch (Throwable t) {
// ignore the exception.
}
}
private static boolean cmdMapInitialized(MailcapCommandMap mailMap) {
CommandInfo[] commands = mailMap.getAllCommands("text/xml");
if (commands == null || commands.length == 0) {
return false;
}
// SAAJ RI implements it's own DataHandlers which can be used for JAX-WS too;
// see com.sun.xml.internal.messaging.saaj.soap.AttachmentPartImpl#initializeJavaActivationHandlers
// so if found any of SAAJ or our own handler registered, we are ok; anyway using SAAJ directly here
// is not good idea since we don't want standalone JAX-WS to depend on specific SAAJ impl.
// This is also reason for duplication of Handler's code by JAX-WS
String saajClassName = "com.sun.xml.internal.messaging.saaj.soap.XmlDataContentHandler";
String jaxwsClassName = "com.sun.xml.internal.ws.encoding.XmlDataContentHandler";
for (CommandInfo command : commands) {
String commandClass = command.getCommandClass();
if (saajClassName.equals(commandClass) ||
jaxwsClassName.equals(commandClass)) {
return true;
}
}
return false;
}
public static BindingImpl create(@NotNull BindingID bindingId) {
if (bindingId.equals(BindingID.XML_HTTP))
return new HTTPBindingImpl();

View File

@ -34,8 +34,6 @@ import com.sun.xml.internal.ws.api.message.Packet;
import com.sun.xml.internal.ws.api.pipe.Codec;
import com.sun.xml.internal.ws.api.pipe.ContentType;
import com.sun.xml.internal.ws.developer.StreamingAttachmentFeature;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import java.io.IOException;
import java.io.InputStream;
@ -63,33 +61,6 @@ import java.util.UUID;
*/
abstract class MimeCodec implements Codec {
static {
// DataHandler.writeTo() may search for DCH. So adding some default ones.
try {
CommandMap map = CommandMap.getDefaultCommandMap();
if (map instanceof MailcapCommandMap) {
MailcapCommandMap mailMap = (MailcapCommandMap) map;
String hndlrStr = ";;x-java-content-handler=";
// registering our DCH since javamail's DCH doesn't handle
// Source
mailMap.addMailcap(
"text/xml" + hndlrStr + XmlDataContentHandler.class.getName());
mailMap.addMailcap(
"application/xml" + hndlrStr + XmlDataContentHandler.class.getName());
if (map.createDataContentHandler("image/*") == null) {
mailMap.addMailcap(
"image/*" + hndlrStr + ImageDataContentHandler.class.getName());
}
if (map.createDataContentHandler("text/plain") == null) {
mailMap.addMailcap(
"text/plain" + hndlrStr + StringDataContentHandler.class.getName());
}
}
} catch (Throwable t) {
// ignore the exception.
}
}
public static final String MULTIPART_RELATED_MIME_TYPE = "multipart/related";
protected Codec mimeRootCodec;