提交 2cc2b4c2 编写于 作者: J jbachorik

8014085: Better serialization support in JMX classes

Reviewed-by: alanb, dfuchs, skoivu
上级 db5bee27
......@@ -25,6 +25,9 @@
package javax.management;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.util.Arrays;
/**
......@@ -67,7 +70,7 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable
/**
* @serial The different types of the notification.
*/
private final String[] types;
private String[] types;
/** @see MBeanInfo#arrayGettersSafe */
private final transient boolean arrayGettersSafe;
......@@ -114,9 +117,8 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable
notifType, though it doesn't explicitly allow it
either. */
if (notifTypes == null)
notifTypes = NO_TYPES;
this.types = notifTypes;
this.types = (notifTypes != null && notifTypes.length > 0) ?
notifTypes.clone() : NO_TYPES;
this.arrayGettersSafe =
MBeanInfo.arrayGettersSafe(this.getClass(),
MBeanNotificationInfo.class);
......@@ -203,4 +205,16 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable
hash ^= types[i].hashCode();
return hash;
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
String[] t = (String[])gf.get("types", null);
if (t == null) {
throw new InvalidObjectException("Trying to deserialize an invalid " +
"instance of " + MBeanNotificationInfo.class +
"[types=null]");
}
types = t.length == 0 ? t : t.clone();
}
}
......@@ -26,6 +26,9 @@
package javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.security.Principal;
......@@ -64,9 +67,7 @@ public class JMXPrincipal implements Principal, Serializable {
* <code>null</code>.
*/
public JMXPrincipal(String name) {
if (name == null)
throw new NullPointerException("illegal null input");
validate(name);
this.name = name;
}
......@@ -130,4 +131,20 @@ public class JMXPrincipal implements Principal, Serializable {
public int hashCode() {
return name.hashCode();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
String principalName = (String)gf.get("name", null);
try {
validate(principalName);
this.name = principalName;
} catch (NullPointerException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private static void validate(String name) throws NullPointerException {
if (name == null)
throw new NullPointerException("illegal null input");
}
}
......@@ -29,6 +29,9 @@ package javax.management.remote;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.net.InetAddress;
......@@ -297,7 +300,7 @@ public class JMXServiceURL implements Serializable {
If we're given an explicit host name that is illegal we
have to reject it. (Bug 5057532.) */
try {
validateHost(host);
validateHost(host, port);
} catch (MalformedURLException e) {
if (logger.fineOn()) {
logger.fine("JMXServiceURL",
......@@ -336,36 +339,82 @@ public class JMXServiceURL implements Serializable {
validate();
}
private void validate() throws MalformedURLException {
private static final String INVALID_INSTANCE_MSG =
"Trying to deserialize an invalid instance of JMXServiceURL";
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = inputStream.readFields();
String h = (String)gf.get("host", null);
int p = (int)gf.get("port", -1);
String proto = (String)gf.get("protocol", null);
String url = (String)gf.get("urlPath", null);
if (proto == null || url == null || h == null) {
StringBuilder sb = new StringBuilder(INVALID_INSTANCE_MSG).append('[');
boolean empty = true;
if (proto == null) {
sb.append("protocol=null");
empty = false;
}
if (h == null) {
sb.append(empty ? "" : ",").append("host=null");
empty = false;
}
if (url == null) {
sb.append(empty ? "" : ",").append("urlPath=null");
}
sb.append(']');
throw new InvalidObjectException(sb.toString());
}
// Check protocol
if (h.contains("[") || h.contains("]")) {
throw new InvalidObjectException("Invalid host name: " + h);
}
try {
validate(proto, h, p, url);
this.protocol = proto;
this.host = h;
this.port = p;
this.urlPath = url;
} catch (MalformedURLException e) {
throw new InvalidObjectException(INVALID_INSTANCE_MSG + ": " +
e.getMessage());
}
final int protoEnd = indexOfFirstNotInSet(protocol, protocolBitSet, 0);
if (protoEnd == 0 || protoEnd < protocol.length()
|| !alphaBitSet.get(protocol.charAt(0))) {
}
private void validate(String proto, String h, int p, String url)
throws MalformedURLException {
// Check protocol
final int protoEnd = indexOfFirstNotInSet(proto, protocolBitSet, 0);
if (protoEnd == 0 || protoEnd < proto.length()
|| !alphaBitSet.get(proto.charAt(0))) {
throw new MalformedURLException("Missing or invalid protocol " +
"name: \"" + protocol + "\"");
"name: \"" + proto + "\"");
}
// Check host
validateHost();
validateHost(h, p);
// Check port
if (port < 0)
throw new MalformedURLException("Bad port: " + port);
if (p < 0)
throw new MalformedURLException("Bad port: " + p);
// Check URL path
if (urlPath.length() > 0) {
if (!urlPath.startsWith("/") && !urlPath.startsWith(";"))
throw new MalformedURLException("Bad URL path: " + urlPath);
if (url.length() > 0) {
if (!url.startsWith("/") && !url.startsWith(";"))
throw new MalformedURLException("Bad URL path: " + url);
}
}
private void validateHost() throws MalformedURLException {
if (host.length() == 0) {
private void validate() throws MalformedURLException {
validate(this.protocol, this.host, this.port, this.urlPath);
}
private static void validateHost(String h, int port)
throws MalformedURLException {
if (h.length() == 0) {
if (port != 0) {
throw new MalformedURLException("Cannot give port number " +
"without host name");
......@@ -373,12 +422,6 @@ public class JMXServiceURL implements Serializable {
return;
}
validateHost(host);
}
private static void validateHost(String h)
throws MalformedURLException {
if (isNumericIPv6Address(h)) {
/* We assume J2SE >= 1.4 here. Otherwise you can't
use the address anyway. We can't call
......@@ -663,22 +706,22 @@ public class JMXServiceURL implements Serializable {
/**
* The value returned by {@link #getProtocol()}.
*/
private final String protocol;
private String protocol;
/**
* The value returned by {@link #getHost()}.
*/
private final String host;
private String host;
/**
* The value returned by {@link #getPort()}.
*/
private final int port;
private int port;
/**
* The value returned by {@link #getURLPath()}.
*/
private final String urlPath;
private String urlPath;
/**
* Cached result of {@link #toString()}.
......
......@@ -25,6 +25,9 @@
package javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
/**
......@@ -76,17 +79,7 @@ public class NotificationResult implements Serializable {
public NotificationResult(long earliestSequenceNumber,
long nextSequenceNumber,
TargetedNotification[] targetedNotifications) {
if (targetedNotifications == null) {
final String msg = "Notifications null";
throw new IllegalArgumentException(msg);
}
if (earliestSequenceNumber < 0 || nextSequenceNumber < 0)
throw new IllegalArgumentException("Bad sequence numbers");
/* We used to check nextSequenceNumber >= earliestSequenceNumber
here. But in fact the opposite can legitimately be true if
notifications have been lost. */
validate(targetedNotifications, earliestSequenceNumber, nextSequenceNumber);
this.earliestSequenceNumber = earliestSequenceNumber;
this.nextSequenceNumber = nextSequenceNumber;
this.targetedNotifications = (targetedNotifications.length == 0 ? targetedNotifications : targetedNotifications.clone());
......@@ -138,7 +131,39 @@ public class NotificationResult implements Serializable {
getTargetedNotifications().length;
}
private final long earliestSequenceNumber;
private final long nextSequenceNumber;
private final TargetedNotification[] targetedNotifications;
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
TargetedNotification[] tNotifs = (TargetedNotification[])gf.get("targetedNotifications", null);
long snStart = gf.get("earliestSequenceNumber", -1L);
long snNext = gf.get("nextSequenceNumber", -1L);
try {
validate(tNotifs, snStart, snNext);
this.targetedNotifications = tNotifs.length == 0 ? tNotifs : tNotifs.clone();
this.earliestSequenceNumber = snStart;
this.nextSequenceNumber = snNext;
} catch (IllegalArgumentException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private long earliestSequenceNumber;
private long nextSequenceNumber;
private TargetedNotification[] targetedNotifications;
private static void validate(TargetedNotification[] targetedNotifications,
long earliestSequenceNumber,
long nextSequenceNumber)
throws IllegalArgumentException {
if (targetedNotifications == null) {
final String msg = "Notifications null";
throw new IllegalArgumentException(msg);
}
if (earliestSequenceNumber < 0 || nextSequenceNumber < 0)
throw new IllegalArgumentException("Bad sequence numbers");
/* We used to check nextSequenceNumber >= earliestSequenceNumber
here. But in fact the opposite can legitimately be true if
notifications have been lost. */
}
}
......@@ -26,6 +26,9 @@
package javax.management.remote;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import javax.management.Notification;
......@@ -73,12 +76,9 @@ public class TargetedNotification implements Serializable {
*/
public TargetedNotification(Notification notification,
Integer listenerID) {
validate(notification, listenerID);
// If we replace integer with int...
// this(notification,intValue(listenerID));
if (notification == null) throw new
IllegalArgumentException("Invalid notification: null");
if (listenerID == null) throw new
IllegalArgumentException("Invalid listener ID: null");
this.notif = notification;
this.id = listenerID;
}
......@@ -115,13 +115,13 @@ public class TargetedNotification implements Serializable {
* @serial A notification to transmit to the other side.
* @see #getNotification()
**/
private final Notification notif;
private Notification notif;
/**
* @serial The ID of the listener to which the notification is
* targeted.
* @see #getListenerID()
**/
private final Integer id;
private Integer id;
//private final int id;
// Needed if we use int instead of Integer...
......@@ -130,4 +130,26 @@ public class TargetedNotification implements Serializable {
// IllegalArgumentException("Invalid listener ID: null");
// return id.intValue();
// }
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Notification notification = (Notification)gf.get("notif", null);
Integer listenerId = (Integer)gf.get("id", null);
try {
validate(notification, listenerId);
this.notif = notification;
this.id = listenerId;
} catch (IllegalArgumentException e) {
throw new InvalidObjectException(e.getMessage());
}
}
private static void validate(Notification notif, Integer id) throws IllegalArgumentException {
if (notif == null) {
throw new IllegalArgumentException("Invalid notification: null");
}
if (id == null) {
throw new IllegalArgumentException("Invalid listener ID: null");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册