JBossWeb SVN: r667 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-12 10:20:09 -0400 (Thu, 12 Jun 2008)
New Revision: 667
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
trunk/java/org/jboss/web/cluster/LocalStrings.properties
trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml
Log:
- Add fields to configure the advertise listener.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-12 14:11:25 UTC (rev 666)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-12 14:20:09 UTC (rev 667)
@@ -31,6 +31,7 @@
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -170,6 +171,30 @@
/**
+ * Advertise group.
+ */
+ protected String advertiseGroupAddress = null;
+ public String getAdvertiseGroupAddress() { return advertiseGroupAddress; }
+ public void setAdvertiseGroupAddress(String advertiseGroupAddress) { this.advertiseGroupAddress = advertiseGroupAddress; }
+
+
+ /**
+ * Advertise port.
+ */
+ protected int advertisePort = -1;
+ public int getAdvertisePort() { return advertisePort; }
+ public void setAdvertisePort(int advertisePort) { this.advertisePort = advertisePort; }
+
+
+ /**
+ * Advertise security key.
+ */
+ protected String advertiseSecurityKey = null;
+ public String getAdvertiseSecurityKey() { return advertiseSecurityKey; }
+ public void setAdvertiseSecurityKey(String advertiseSecurityKey) { this.advertiseSecurityKey = advertiseSecurityKey; }
+
+
+ /**
* Proxy list, format "address:port,address:port".
*/
protected String proxyList = null;
@@ -710,10 +735,22 @@
*/
protected void startListener() {
listener = new AdvertiseListener(this);
+ if (advertiseGroupAddress != null) {
+ listener.setGroupAddress(advertiseGroupAddress);
+ }
+ if (advertisePort > 0) {
+ listener.setAdvertisePort(advertisePort);
+ }
try {
+ if (advertiseSecurityKey != null) {
+ listener.setSecurityKey(advertiseSecurityKey);
+ }
listener.start();
} catch (IOException e) {
- log.info(sm.getString("clusterListener.error.startListener"), e);
+ log.error(sm.getString("clusterListener.error.startListener"), e);
+ } catch (NoSuchAlgorithmException e) {
+ // Should never happen
+ log.error(sm.getString("clusterListener.error.startListener"), e);
}
}
@@ -726,7 +763,7 @@
try {
listener.destroy();
} catch (IOException e) {
- log.info(sm.getString("clusterListener.error.stopListener"), e);
+ log.error(sm.getString("clusterListener.error.stopListener"), e);
}
listener = null;
}
Modified: trunk/java/org/jboss/web/cluster/LocalStrings.properties
===================================================================
--- trunk/java/org/jboss/web/cluster/LocalStrings.properties 2008-06-12 14:11:25 UTC (rev 666)
+++ trunk/java/org/jboss/web/cluster/LocalStrings.properties 2008-06-12 14:20:09 UTC (rev 667)
@@ -19,4 +19,6 @@
clusterListener.error.nullAttribute=Value for attribute {0} cannot be null
clusterListener.error.other=Error [{2}: {3}] sending command {0} to proxy {1}, configuration will be reset
clusterListener.error.parse=Error parsing response header for command {0}
+clusterListener.error.startListener=Error starting advertise listener
+clusterListener.error.stopListener=Error stopping advertise listener
clusterListener.error.syntax=Unrecoverable syntax error [{2}: {3}] sending command {0} to proxy {1}
Modified: trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml
===================================================================
--- trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml 2008-06-12 14:11:25 UTC (rev 666)
+++ trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml 2008-06-12 14:20:09 UTC (rev 667)
@@ -29,6 +29,22 @@
description="Connection timeout for communication with the proxy"
type="int"/>
+ <attribute name="advertise"
+ description="Enable autodiscovery of httpd servers"
+ type="boolean"/>
+
+ <attribute name="advertiseGroupAddress"
+ description="Multicast address for discovery"
+ type="java.lang.String"/>
+
+ <attribute name="advertisePort"
+ description="Multicast port for discovery"
+ type="int"/>
+
+ <attribute name="advertiseSecurityKey"
+ description="Security key for discovery"
+ type="java.lang.String"/>
+
<attribute name="domain"
description="Domain parameter, which allows tying a jvmRoute to a particular domain"
type="java.lang.String"/>
17 years, 3 months
JBossWeb SVN: r666 - trunk/java/org/apache/juli.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-12 10:11:25 -0400 (Thu, 12 Jun 2008)
New Revision: 666
Modified:
trunk/java/org/apache/juli/FileHandler.java
Log:
- Patch port.
- Fix possible logging NPE on shutdown.
Modified: trunk/java/org/apache/juli/FileHandler.java
===================================================================
--- trunk/java/org/apache/juli/FileHandler.java 2008-06-12 14:10:53 UTC (rev 665)
+++ trunk/java/org/apache/juli/FileHandler.java 2008-06-12 14:11:25 UTC (rev 666)
@@ -133,8 +133,12 @@
}
try {
- writer.write(result);
- writer.flush();
+ if (writer != null) {
+ writer.write(result);
+ writer.flush();
+ } else {
+ reportError("FileHandler is closed or not yet initialized, unable to log ["+result+"]", null, ErrorManager.WRITE_FAILURE);
+ }
} catch (Exception e) {
reportError(null, e, ErrorManager.WRITE_FAILURE);
return;
17 years, 3 months
JBossWeb SVN: r665 - trunk/java/org/apache/el/parser.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-12 10:10:53 -0400 (Thu, 12 Jun 2008)
New Revision: 665
Modified:
trunk/java/org/apache/el/parser/AstValue.java
Log:
- Patch port.
- Make forced coercion of null and "" to zero optional.
Modified: trunk/java/org/apache/el/parser/AstValue.java
===================================================================
--- trunk/java/org/apache/el/parser/AstValue.java 2008-06-12 00:03:37 UTC (rev 664)
+++ trunk/java/org/apache/el/parser/AstValue.java 2008-06-12 14:10:53 UTC (rev 665)
@@ -38,6 +38,10 @@
*/
public final class AstValue extends SimpleNode {
+ protected static final boolean COERCE_TO_ZERO =
+ Boolean.valueOf(System.getProperty(
+ "org.apache.el.parser.COERCE_TO_ZERO", "true")).booleanValue();
+
protected static class Target {
protected Object base;
@@ -129,12 +133,26 @@
Target t = getTarget(ctx);
ctx.setPropertyResolved(false);
ELResolver resolver = ctx.getELResolver();
- resolver.setValue(ctx, t.base, t.property,
- // coerce to the expected type
- ELSupport.coerceToType(value,
- resolver.getType(ctx, t.base, t.property)));
+ // coerce to the expected type
+ Class<?> targetClass = resolver.getType(ctx, t.base, t.property);
+ if (COERCE_TO_ZERO
+ || !isAssignable(value, targetClass)) {
+ value = ELSupport.coerceToType(value, targetClass);
+ }
+ resolver.setValue(ctx, t.base, t.property, value);
}
+ private boolean isAssignable(Object value, Class<?> targetClass) {
+ if (targetClass == null) {
+ return false;
+ } else if (value != null && targetClass.isPrimitive()) {
+ return false;
+ } else if (value != null && !targetClass.isInstance(value)) {
+ return false;
+ }
+ return true;
+ }
+
public MethodInfo getMethodInfo(EvaluationContext ctx, Class[] paramTypes)
throws ELException {
Target t = getTarget(ctx);
17 years, 3 months
JBossWeb SVN: r664 - in trunk/java/org/jboss/web/cluster: advertise and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-11 20:03:37 -0400 (Wed, 11 Jun 2008)
New Revision: 664
Added:
trunk/java/org/jboss/web/cluster/advertise/
trunk/java/org/jboss/web/cluster/advertise/AdvertiseEventType.java
trunk/java/org/jboss/web/cluster/advertise/AdvertiseListener.java
trunk/java/org/jboss/web/cluster/advertise/AdvertisedServer.java
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
Log:
- Add discovery of the httpd servers. Not done yet.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-10 11:14:12 UTC (rev 663)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-12 00:03:37 UTC (rev 664)
@@ -61,6 +61,7 @@
import org.apache.tomcat.util.buf.UEncoder;
import org.apache.tomcat.util.modeler.Registry;
import org.jboss.logging.Logger;
+import org.jboss.web.cluster.advertise.AdvertiseListener;
@@ -147,13 +148,28 @@
/**
* Remove proxy list.
*/
- protected ArrayList<Proxy> removeProxies = new ArrayList<Proxy>();
+ protected ArrayList<Proxy> removeProxies = new ArrayList<Proxy>();
+ /**
+ * Advertise listener.
+ */
+ protected AdvertiseListener listener = null;
+
+
// ------------------------------------------------------------- Properties
/**
+ * Receive advertisements from httpd proxies (default is to use advertisements
+ * if the proxyList is not set).
+ */
+ protected int advertise = -1;
+ public boolean getAdvertise() { return (advertise == 0) ? false : true; }
+ public void setAdvertise(boolean advertise) { this.advertise = advertise ? 1 : 0; }
+
+
+ /**
* Proxy list, format "address:port,address:port".
*/
protected String proxyList = null;
@@ -468,13 +484,14 @@
if (source instanceof Server) {
if (this.proxyList == null) {
- // if (advertise) {
- // FIXME: enable simple advertise service in this case, most likely
- // using a flag
- // } else {
- // Default to a httpd on localhost on the default port
- proxies = new Proxy[1];
- proxies[0] = new Proxy();
+ if (advertise != 0) {
+ proxies = new Proxy[0];
+ startListener();
+ } else {
+ // Default to a httpd on localhost on the default port
+ proxies = new Proxy[1];
+ proxies[0] = new Proxy();
+ }
} else {
ArrayList<Proxy> proxyList = new ArrayList<Proxy>();
StringTokenizer tok = new StringTokenizer(this.proxyList, ",");
@@ -511,6 +528,11 @@
sslInit();
startServer((Server) source, -1);
+
+ if (advertise == 1) {
+ startListener();
+ }
+
init = true;
} else {
return;
@@ -520,6 +542,7 @@
// Stop a webapp
stopContext((Context) source, -1);
} else if (source instanceof Server) {
+ stopListener();
stopServer((Server) source, -1);
for (int i = 0; i < connections.length; i++) {
closeConnection(i);
@@ -540,6 +563,26 @@
/**
* Add proxy.
*/
+ public void addProxy(String address) {
+ int pos = address.indexOf(':');
+ String host = null;
+ int port = 0;
+ if (pos < 0) {
+ host = address;
+ } else if (pos == 0) {
+ host = null;
+ port = Integer.parseInt(address.substring(1));
+ } else {
+ host = address.substring(0, pos);
+ port = Integer.parseInt(address.substring(pos + 1));
+ }
+ addProxy(host, port);
+ }
+
+
+ /**
+ * Add proxy.
+ */
public synchronized void addProxy(String host, int port) {
Proxy proxy = new Proxy();
try {
@@ -547,7 +590,9 @@
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
- proxy.port = port;
+ if (port > 0) {
+ proxy.port = port;
+ }
proxy.state = State.ERROR;
addProxies.add(proxy);
}
@@ -563,7 +608,9 @@
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
- proxy.port = port;
+ if (port > 0) {
+ proxy.port = port;
+ }
removeProxies.add(proxy);
}
@@ -659,6 +706,34 @@
/**
+ * Start the advertise listener.
+ */
+ protected void startListener() {
+ listener = new AdvertiseListener(this);
+ try {
+ listener.start();
+ } catch (IOException e) {
+ log.info(sm.getString("clusterListener.error.startListener"), e);
+ }
+ }
+
+
+ /**
+ * Stop the advertise listener.
+ */
+ protected void stopListener() {
+ if (listener != null) {
+ try {
+ listener.destroy();
+ } catch (IOException e) {
+ log.info(sm.getString("clusterListener.error.stopListener"), e);
+ }
+ listener = null;
+ }
+ }
+
+
+ /**
* Send commands to the front end server assocaited with the startup of the
* node.
*/
Added: trunk/java/org/jboss/web/cluster/advertise/AdvertiseEventType.java
===================================================================
--- trunk/java/org/jboss/web/cluster/advertise/AdvertiseEventType.java (rev 0)
+++ trunk/java/org/jboss/web/cluster/advertise/AdvertiseEventType.java 2008-06-12 00:03:37 UTC (rev 664)
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+/**
+ * Set what type of event the AdvertiseEvent signals.
+ * @param type The type of event. One of:
+ * <PRE>
+ * ON_NEW_SERVER -- New AdvertisedServer detected
+ * ON_STATUS_CHANGE -- AdvertisedServer server changed status
+ * </PRE>
+ */
+public enum AdvertiseEventType
+{
+ /** New AdvertisedServer detected */
+ ON_NEW_SERVER( 0),
+ /** AdvertisedServer server changed status */
+ ON_STATUS_CHANGE( 1);
+
+ private int value;
+ private AdvertiseEventType(int v)
+ {
+ value = v;
+ }
+
+ public int valueOf()
+ {
+ return value;
+ }
+
+ public static AdvertiseEventType valueOf(int value)
+ {
+ for (AdvertiseEventType e : values()) {
+ if (e.value == value)
+ return e;
+ }
+ throw new IllegalArgumentException("Invalid initializer: " + value);
+ }
+
+}
Added: trunk/java/org/jboss/web/cluster/advertise/AdvertiseListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/advertise/AdvertiseListener.java (rev 0)
+++ trunk/java/org/jboss/web/cluster/advertise/AdvertiseListener.java 2008-06-12 00:03:37 UTC (rev 664)
@@ -0,0 +1,454 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+import java.io.IOException;
+
+import java.net.InetAddress;
+import java.net.SocketAddress;
+import java.net.DatagramPacket;
+import java.net.MulticastSocket;
+import java.net.NetworkInterface;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.HashMap;
+import java.util.Collection;
+
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.security.NoSuchAlgorithmException;
+
+import org.jboss.web.cluster.ClusterListener;
+
+
+/** AdvertiseListener
+ * Listens for Advertise messages from mod_cluster
+ *
+ * @author Mladen Turk
+ *
+ */
+public class AdvertiseListener
+{
+ /** Default port for listening Advertise messages.
+ */
+ public static int DEFAULT_PORT = 23364;
+ /** Default Multicast group address for listening Advertise messages.
+ */
+ public static String DEFAULT_GROUP = "224.0.1.105";
+
+ private static String RFC_822_FMT = "EEE, d MMM yyyy HH:mm:ss Z";
+ private int advertisePort = DEFAULT_PORT;
+ private String groupAddress = DEFAULT_GROUP;
+ private MulticastSocket ms;
+ private SimpleDateFormat df;
+ private boolean listening = true;
+ private boolean initialized = false;
+ private boolean running = false;
+ private boolean paused = false;
+ private boolean daemon = true;
+ private byte [] secure = new byte[16];
+ private String securityKey = null;
+ private MessageDigest md = null;
+
+ private HashMap<String, AdvertisedServer> servers;
+
+ private ClusterListener listener;
+ private Thread workerThread;
+
+
+ private static void digestString(MessageDigest md, String s)
+ {
+ int len = s.length();
+ byte [] b = new byte[len];
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (c < 127)
+ b[i] = (byte)c;
+ else
+ b[i] = '?';
+ }
+ md.update(b);
+ }
+
+ /** Create AdvertiseListener instance
+ * @param eventHandler The event handler that will be used for
+ * status and new server notifications.
+ */
+ public AdvertiseListener(ClusterListener listener)
+ {
+ df = new SimpleDateFormat(RFC_822_FMT, Locale.US);
+ servers = new HashMap<String, AdvertisedServer>();
+ this.listener = listener;
+ }
+
+ /**
+ * The default is true - the control thread will be
+ * in daemon mode. If set to false, the control thread
+ * will not be daemon - and will keep the process alive.
+ */
+ public void setDaemon(boolean b)
+ {
+ daemon = b;
+ }
+
+ public boolean getDaemon()
+ {
+ return daemon;
+ }
+
+ /** Set Advertise security key
+ * @param key The key to use.<br/>
+ * Security key must match the AdvertiseKey
+ * on the advertised server.
+ */
+ public void setSecurityKey(String key)
+ throws NoSuchAlgorithmException
+ {
+ securityKey = key;
+ if (md == null)
+ md = MessageDigest.getInstance("MD5");
+ }
+
+ /** Set Advertise port
+ * @param port The UDP port to use.
+ */
+ public void setAdvertisePort(int port)
+ {
+ advertisePort = port;
+ }
+
+ public int getAdvertisePort()
+ {
+ return advertisePort;
+ }
+
+ /** Set Advertise Multicaset group address
+ * @param address The IP or host address to use.
+ */
+ public void setGroupAddress(String address)
+ {
+ groupAddress = address;
+ }
+
+ /** Get Advertise Multicaset group address
+ */
+ public String getGroupAddress()
+ {
+ return groupAddress;
+ }
+
+ /** Get Collection of all AdvertisedServer instances.
+ */
+ public Collection<AdvertisedServer> getServers()
+ {
+ return servers.values();
+ }
+
+ /** Get AdvertiseServer server.
+ * @param name Server name to get.
+ */
+ public AdvertisedServer getServer(String name)
+ {
+ return servers.get(name);
+ }
+
+ /** Remove the AdvertisedServer from the collection.
+ * @param server Server to remove.
+ */
+ public void removeServer(AdvertisedServer server)
+ {
+ servers.remove(server);
+ }
+
+ private void init()
+ throws IOException
+ {
+ ms = new MulticastSocket(advertisePort);
+ ms.setTimeToLive(16);
+ ms.joinGroup(InetAddress.getByName(groupAddress));
+ initialized = true;
+ }
+
+ private void interruptDatagramReader()
+ {
+ if (!initialized)
+ return;
+ try {
+ // Restrict to localhost.
+ ms.setTimeToLive(0);
+ DatagramPacket dp = new DatagramPacket(secure, secure.length,
+ InetAddress.getByName(groupAddress),
+ advertisePort);
+ ms.send(dp);
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+
+ /** Start the Listener, creating listener thread.
+ */
+ public void start()
+ throws IOException
+ {
+ if (!initialized) {
+ init();
+ }
+ if (!running) {
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(secure);
+ secure[0] = 0;
+ running = true;
+ paused = false;
+ listening = true;
+ AdvertiseListenerWorker aw = new AdvertiseListenerWorker();
+ workerThread = new Thread(aw);
+ workerThread.setDaemon(daemon);
+ workerThread.start();
+ }
+ }
+
+ /**
+ * Pause the listener, which will make it stop accepting new advertise
+ * messages.
+ */
+ public void pause()
+ {
+ if (running && !paused) {
+ paused = true;
+ interruptDatagramReader();
+ }
+ }
+
+
+ /**
+ * Resume the listener, which will make it start accepting new advertise
+ * messages again.
+ */
+ public void resume()
+ {
+ if (running && paused) {
+ // Genererate new private secure
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(secure);
+ secure[0] = 0;
+ paused = false;
+ }
+ }
+
+
+ /**
+ * Stop the endpoint. This will cause all processing threads to stop.
+ */
+ public void stop()
+ {
+ if (running) {
+ running = false;
+ interruptDatagramReader();
+ workerThread = null;
+ }
+ }
+
+
+ /**
+ * Deallocate listener and close sockets.
+ */
+ public void destroy()
+ throws IOException
+ {
+ if (running) {
+ stop();
+ }
+ if (initialized) {
+ ms.leaveGroup(InetAddress.getByName(groupAddress));
+ ms.close();
+ initialized = false;
+ ms = null;
+ }
+ }
+
+ private boolean verifyDigest(String digest, String server, String date)
+ {
+ if (md == null)
+ return true;
+ md.reset();
+ digestString(md, securityKey);
+ digestString(md, date);
+ digestString(md, server);
+ byte [] our = md.digest();
+ byte [] dst = new byte[digest.length() * 2];
+ for (int i = 0, j = 0; i < digest.length(); i++) {
+ char ch = digest.charAt(i);
+ dst[j++] = (byte)((ch >= 'A') ? ((ch & 0xdf) - 'A') + 10 : (ch - '0'));
+ }
+ return true;
+ }
+
+ /**
+ * True if listener is accepting the advetise messages.<br/>
+ * If false it means that listener is experiencing some
+ * network problems if running.
+ */
+ public boolean isListening()
+ {
+ return listening;
+ }
+
+
+ // ------------------------------------ AdvertiseListenerWorker Inner Class
+ private class AdvertiseListenerWorker implements Runnable
+ {
+
+ protected AdvertiseListenerWorker()
+ {
+ // Nothing
+ }
+ /**
+ * The background thread that listens for incoming Advertise packets
+ * and hands them off to an appropriate AdvertiseEvent handler.
+ */
+ public void run() {
+ byte[] buffer = new byte[512];
+ // Loop until we receive a shutdown command
+ while (running) {
+ // Loop if endpoint is paused
+ while (paused) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ }
+ try {
+ DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
+ ms.receive(dp);
+ if (!running)
+ break;
+ byte [] data = dp.getData();
+ boolean intr = false;
+ if (dp.getLength() == secure.length) {
+ int i;
+ for (i = 0; i < secure.length; i++) {
+ if (data[i] != secure[i])
+ break;
+ }
+ if (i == secure.length)
+ intr = true;
+ }
+ if (intr)
+ continue;
+ String s = new String(data, 0, dp.getLength(), "8859_1");
+ if (!s.startsWith("HTTP/1."))
+ continue;
+
+ String [] headers = s.split("\r\n");
+ String date_str = null;
+ Date date = null;
+ int status = 0;
+ String status_desc = null;
+ String digest = null;
+ String server_name = null;
+ AdvertisedServer server = null;
+ boolean added = false;
+ for (int i = 0; i < headers.length; i++) {
+ if (i == 0) {
+ String [] sline = headers[i].split(" ", 3);
+ if (sline == null || sline.length != 3)
+ break;
+ status = Integer.parseInt(sline[1]);
+ if (status < 100)
+ break;
+ status_desc = sline[2];
+ }
+ else {
+ String [] hdrv = headers[i].split(": ", 2);
+ if (hdrv == null || hdrv.length != 2)
+ break;
+ if (hdrv[0].equals("Date")) {
+ date_str = hdrv[1];
+ try {
+ date = df.parse(date_str);
+ } catch (ParseException e) {
+ date = new Date();
+ }
+ }
+ else if (hdrv[0].equals("Digest")) {
+ digest = hdrv[1];
+ }
+ else if (hdrv[0].equals("Server")) {
+ server_name = hdrv[1];
+ server = servers.get(server_name);
+ if (server == null) {
+ server = new AdvertisedServer(server_name);
+ added = true;
+ }
+ }
+ else if (server != null) {
+ server.setParameter(hdrv[0], hdrv[1]);
+ }
+ }
+ }
+ if (server != null && status > 0) {
+ if (md != null) {
+ /* We need a digest to match */
+ if (!verifyDigest(digest, server_name, date_str)) {
+ System.out.println("Digest mismatch");
+ continue;
+ }
+ }
+ server.setDate(date);
+ boolean rc = server.setStatus(status, status_desc);
+ if (added) {
+ servers.put(server_name, server);
+ // Call the new server callback
+ //eventHandler.onEvent(AdvertiseEventType.ON_NEW_SERVER, server);
+ String proxy = server.getParameter(AdvertisedServer.MANAGER_ADDRESS);
+ if (proxy != null) {
+ listener.addProxy(proxy);
+ }
+ }
+ else if (rc) {
+ // Call the status change callback
+ //eventHandler.onEvent(AdvertiseEventType.ON_STATUS_CHANGE, server);
+ }
+ }
+ listening = true;
+ } catch (IOException e) {
+ // Do not blow the CPU in case of communication error
+ listening = false;
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException x) {
+ // Ignore
+ }
+ }
+ }
+ }
+ }
+
+}
Added: trunk/java/org/jboss/web/cluster/advertise/AdvertisedServer.java
===================================================================
--- trunk/java/org/jboss/web/cluster/advertise/AdvertisedServer.java (rev 0)
+++ trunk/java/org/jboss/web/cluster/advertise/AdvertisedServer.java 2008-06-12 00:03:37 UTC (rev 664)
@@ -0,0 +1,128 @@
+/*
+ *
+ * Copyright(c) 2008 Red Hat Middleware, LLC,
+ * and individual contributors as indicated by the @authors tag.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ */
+
+package org.jboss.web.cluster.advertise;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Collection;
+
+/**
+ * Advertised server instance
+ *
+ * @author Mladen Turk
+ *
+ */
+public class AdvertisedServer
+{
+ private String server;
+ private Date date;
+ private int status;
+ private String status_desc;
+ private HashMap<String, String> headers;
+
+ /** Manager-Address header */
+ public static String MANAGER_ADDRESS = "X-Manager-Address";
+ /** Manager-Url header */
+ public static String MANAGER_URL = "X-Manager-Url";
+ /** Manager-Protocol header */
+ public static String MANAGER_PROTOCOL = "X-Manager-Protocol";
+ /** Manager-Version header */
+ public static String MANAGER_VERSION = "X-Manager-Version";
+ /** Manager-Host header */
+ public static String MANAGER_HOST = "X-Manager-Host";
+
+ private AdvertisedServer()
+ {
+ // Disable creation.
+ }
+
+ protected AdvertisedServer(String server)
+ {
+ this.server = server;
+ headers = new HashMap<String, String>();
+ }
+
+ protected boolean setStatus(int status, String desc)
+ {
+ boolean rv = false;
+ status_desc = desc;
+ if (this.status == 0 ) {
+ // First time
+ this.status = status;
+ }
+ else if (this.status != status) {
+ this.status = status;
+ rv = true;
+ }
+ return rv;
+ }
+
+ /** Set the Date of the last Advertise message
+ */
+ protected void setDate(Date date)
+ {
+ this.date = date;
+ }
+
+ /** Set the Header
+ */
+ protected void setParameter(String name, String value)
+ {
+ headers.put(name, value);
+ }
+
+ /** Get Date of the last Advertise message
+ */
+ public Date getDate()
+ {
+ return date;
+ }
+
+ /** Get Status code of the last Advertise message
+ */
+ public int getStatusCode()
+ {
+ return status;
+ }
+
+ /** Get Status description of the last Advertise message
+ */
+ public String getStatusDescription()
+ {
+ return status_desc;
+ }
+
+ /** Get Advertise parameter
+ */
+ public String getParameter(String name)
+ {
+ return headers.get(name);
+ }
+
+ public String toString()
+ {
+ return server;
+ }
+}
17 years, 3 months
JBossWeb SVN: r663 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-10 07:14:12 -0400 (Tue, 10 Jun 2008)
New Revision: 663
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml
Log:
- Add addProxy and removeProxy.
- Found NPE location (it is a harmless info logging, why is it always reported as a major issue ?).
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-10 09:39:24 UTC (rev 662)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-10 11:14:12 UTC (rev 663)
@@ -138,6 +138,18 @@
protected boolean init = false;
+ /**
+ * Add proxy list.
+ */
+ protected ArrayList<Proxy> addProxies = new ArrayList<Proxy>();
+
+
+ /**
+ * Remove proxy list.
+ */
+ protected ArrayList<Proxy> removeProxies = new ArrayList<Proxy>();
+
+
// ------------------------------------------------------------- Properties
@@ -456,6 +468,11 @@
if (source instanceof Server) {
if (this.proxyList == null) {
+ // if (advertise) {
+ // FIXME: enable simple advertise service in this case, most likely
+ // using a flag
+ // } else {
+ // Default to a httpd on localhost on the default port
proxies = new Proxy[1];
proxies[0] = new Proxy();
} else {
@@ -521,6 +538,37 @@
/**
+ * Add proxy.
+ */
+ public synchronized void addProxy(String host, int port) {
+ Proxy proxy = new Proxy();
+ try {
+ proxy.address = InetAddress.getByName(host);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ proxy.port = port;
+ proxy.state = State.ERROR;
+ addProxies.add(proxy);
+ }
+
+
+ /**
+ * Remove proxy.
+ */
+ public synchronized void removeProxy(String host, int port) {
+ Proxy proxy = new Proxy();
+ try {
+ proxy.address = InetAddress.getByName(host);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ proxy.port = port;
+ removeProxies.add(proxy);
+ }
+
+
+ /**
* Retrieves the full proxy configuration. To be used through JMX or similar.
*
* response: HTTP/1.1 200 OK
@@ -611,39 +659,6 @@
/**
- * Parse proxy list.
- */
- protected void parseProxyList(String list) {
- if (list == null) {
- proxies = new Proxy[1];
- proxies[0] = new Proxy();
- } else {
- ArrayList<Proxy> proxyList = new ArrayList<Proxy>();
- StringTokenizer tok = new StringTokenizer(list, ",");
- while (tok.hasMoreTokens()) {
- String token = tok.nextToken().trim();
- Proxy proxy = new Proxy();
- int pos = token.indexOf(':');
- String address = null;
- if (pos > 0) {
- address = token.substring(0, pos);
- proxy.port = Integer.parseInt(token.substring(pos + 1));
- } else {
- address = token;
- }
- try {
- proxy.address = InetAddress.getByName(address);
- } catch (Exception e) {
- throw new IllegalArgumentException(e);
- }
- proxyList.add(proxy);
- }
- proxies = proxyList.toArray(new Proxy[0]);
- }
- }
-
-
- /**
* Send commands to the front end server assocaited with the startup of the
* node.
*/
@@ -882,6 +897,39 @@
* @param engine
*/
protected void status(Engine engine) {
+
+ // Check to add or remove proxies, and rebuild a new list if needed
+ synchronized (this) {
+ if (!addProxies.isEmpty() || !removeProxies.isEmpty()) {
+ ArrayList<Proxy> currentProxies = new ArrayList<Proxy>();
+ for (int i = 0; i < proxies.length; i++) {
+ currentProxies.add(proxies[i]);
+ }
+ for (int i = 0; i < addProxies.size(); i++) {
+ if (!currentProxies.contains(addProxies.get(i))) {
+ currentProxies.add(addProxies.get(i));
+ }
+ }
+ for (int i = 0; i < removeProxies.size(); i++) {
+ if (currentProxies.contains(removeProxies.get(i))) {
+ currentProxies.remove(removeProxies.get(i));
+ }
+ }
+ addProxies.clear();
+ removeProxies.clear();
+ proxies = currentProxies.toArray(new Proxy[0]);
+ // Reset all connections
+ if (connections != null) {
+ for (int i = 0; i < connections.length; i++) {
+ closeConnection(i);
+ }
+ }
+ connections = new Socket[proxies.length];
+ connectionReaders = new BufferedReader[proxies.length];
+ connectionWriters = new BufferedWriter[proxies.length];
+ }
+ }
+
Proxy[] local = proxies;
for (int i = 0; i < local.length; i++) {
if (local[i].state == State.ERROR) {
@@ -1179,27 +1227,29 @@
String message = null;
String errorType = null;
int contentLength = 0;
- try {
- responseStatus = responseStatus.substring(responseStatus.indexOf(' ') + 1, responseStatus.indexOf(' ', responseStatus.indexOf(' ') + 1));
- status = Integer.parseInt(responseStatus);
- String header = reader.readLine();
- while (!"".equals(header)) {
- int colon = header.indexOf(':');
- String headerName = header.substring(0, colon).trim();
- String headerValue = header.substring(colon + 1).trim();
- if ("version".equalsIgnoreCase(headerName)) {
- version = headerValue;
- } else if ("type".equalsIgnoreCase(headerName)) {
- errorType = headerValue;
- } else if ("mess".equalsIgnoreCase(headerName)) {
- message = headerValue;
- } else if ("content-length".equalsIgnoreCase(headerName)) {
- contentLength = Integer.parseInt(headerValue);
+ if (responseStatus != null) {
+ try {
+ responseStatus = responseStatus.substring(responseStatus.indexOf(' ') + 1, responseStatus.indexOf(' ', responseStatus.indexOf(' ') + 1));
+ status = Integer.parseInt(responseStatus);
+ String header = reader.readLine();
+ while (!"".equals(header)) {
+ int colon = header.indexOf(':');
+ String headerName = header.substring(0, colon).trim();
+ String headerValue = header.substring(colon + 1).trim();
+ if ("version".equalsIgnoreCase(headerName)) {
+ version = headerValue;
+ } else if ("type".equalsIgnoreCase(headerName)) {
+ errorType = headerValue;
+ } else if ("mess".equalsIgnoreCase(headerName)) {
+ message = headerValue;
+ } else if ("content-length".equalsIgnoreCase(headerName)) {
+ contentLength = Integer.parseInt(headerValue);
+ }
+ header = reader.readLine();
}
- header = reader.readLine();
+ } catch (Exception e) {
+ log.info(sm.getString("clusterListener.error.parse", command), e);
}
- } catch (Exception e) {
- log.info(sm.getString("clusterListener.error.parse", command), e);
}
// Mark as error if the front end server did not return 200; the configuration will
@@ -1355,6 +1405,23 @@
}
}
+ public boolean equals(Object o) {
+ if (o instanceof Proxy) {
+ Proxy compare = (Proxy) o;
+ if (port != compare.port) {
+ return false;
+ }
+ if (compare.address == null) {
+ if (address == null) {
+ return true;
+ }
+ } else if ((compare.address.equals(address)) && port == compare.port) {
+ return true;
+ }
+ }
+ return false;
+ }
+
}
Modified: trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml
===================================================================
--- trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml 2008-06-10 09:39:24 UTC (rev 662)
+++ trunk/java/org/jboss/web/cluster/mbeans-descriptors.xml 2008-06-10 11:14:12 UTC (rev 663)
@@ -93,6 +93,30 @@
impact="ACTION"
returnType="boolean"/>
+ <operation name="addProxy"
+ description="Add a proxy"
+ impact="ACTION"
+ returnType="void">
+ <parameter name="host"
+ description="Proxy address"
+ type="java.lang.String"/>
+ <parameter name="port"
+ description="Proxy port"
+ type="int"/>
+ </operation>
+
+ <operation name="removeProxy"
+ description="Remove a proxy"
+ impact="ACTION"
+ returnType="void">
+ <parameter name="host"
+ description="Proxy address"
+ type="java.lang.String"/>
+ <parameter name="port"
+ description="Proxy port"
+ type="int"/>
+ </operation>
+
</mbean>
</mbeans-descriptors>
17 years, 3 months
JBossWeb SVN: r662 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: jfrederic.clere(a)jboss.com
Date: 2008-06-10 05:39:24 -0400 (Tue, 10 Jun 2008)
New Revision: 662
Modified:
trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
Log:
Allow empty password in the truststore file.
Modified: trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
===================================================================
--- trunk/java/org/jboss/web/cluster/JSSESocketFactory.java 2008-06-09 10:00:54 UTC (rev 661)
+++ trunk/java/org/jboss/web/cluster/JSSESocketFactory.java 2008-06-10 09:39:24 UTC (rev 662)
@@ -206,6 +206,8 @@
String truststorePassword = listener.getSslTrustStorePassword();
if( truststorePassword == null ) {
truststorePassword = listener.getSslKeyStorePass();
+ } else if (truststorePassword.equals("")) {
+ truststorePassword = null;
}
String truststoreType = listener.getSslTrustStoreType();
if(truststoreType == null) {
@@ -216,7 +218,7 @@
truststoreProvider = keystoreProvider;
}
- if (listener.getSslTrustStore() != null && truststorePassword != null){
+ if (listener.getSslTrustStore() != null){
trustStore = getStore(truststoreType, truststoreProvider,
listener.getSslTrustStore(), truststorePassword);
}
@@ -247,7 +249,10 @@
istream = new FileInputStream(keyStoreFile);
}
- ks.load(istream, pass.toCharArray());
+ if (pass == null)
+ ks.load(istream, null);
+ else
+ ks.load(istream, pass.toCharArray());
} catch (FileNotFoundException fnfe) {
log.error(sm.getString("jsse.keystore_load_failed", type, path,
fnfe.getMessage()), fnfe);
17 years, 3 months
JBossWeb SVN: r661 - in trunk: java/org/apache/jasper/security and 2 other directories.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-09 06:00:54 -0400 (Mon, 09 Jun 2008)
New Revision: 661
Added:
trunk/java/org/apache/catalina/valves/WebdavFixValve.java
Modified:
trunk/java/org/apache/jasper/security/SecurityUtil.java
trunk/java/org/apache/jasper/servlet/JspServlet.java
trunk/webapps/docs/changelog.xml
Log:
- Two Tomcat patches.
- Add a WebDAV valve for a broken MS client.
- Improve JSP error when including.
Added: trunk/java/org/apache/catalina/valves/WebdavFixValve.java
===================================================================
--- trunk/java/org/apache/catalina/valves/WebdavFixValve.java (rev 0)
+++ trunk/java/org/apache/catalina/valves/WebdavFixValve.java 2008-06-09 10:00:54 UTC (rev 661)
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.valves;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+
+import org.apache.catalina.valves.ValveBase;
+import org.apache.catalina.connector.Request;
+import org.apache.catalina.connector.Response;
+
+/**
+ * Valve that attempts to force MS WebDAV clients connecting on port 80 to use
+ * a WebDAV client that actually works. Other workarounds that might help
+ * include:
+ * <ul>
+ * <li>Specifing the port, even if it is port 80, when trying to connect.</li>
+ * <li>Canceling the first authentication dialog box and then trying to
+ * reconnect.</li>
+ * </ul>
+ * To use this valve add the following <code><Valve
+ * className="org.apache.catalina.valves.MicrosoftWebdavFixValve" /></code>
+ * to your <code>Engine</code>, <code>Host</code> or <code>Context</code> as
+ * required. Normally, this valve would be used at the <code>Context</code>
+ * level.
+ *
+ * @version $Revision: 420067 $, $Date: 2006-07-08 09:16:58 +0200 (sub, 08 srp 2006) $
+ */
+
+public class WebdavFixValve
+ extends ValveBase {
+
+ /**
+ * Check for the broken MS WebDAV client and if detected issue a re-direct
+ * that hopefully will cause the non-broken client to be used.
+ */
+ public void invoke(Request request, Response response)
+ throws IOException, ServletException {
+
+ String ua = request.getHeader("User-Agent");
+ if (ua != null && ua.contains("MiniRedir")) {
+ response.sendRedirect(buildRedirect(request));
+ } else {
+ getNext().invoke(request, response);
+ }
+ }
+
+ private String buildRedirect(Request request) {
+ StringBuffer location =
+ new StringBuffer(request.getRequestURL().length());
+ location.append(request.getScheme());
+ location.append("://");
+ location.append(request.getHost().getName());
+ location.append(':');
+ // If we include the port, even if it is 80, then MS clients will use
+ // a WebDAV client that works rather than the MiniRedir that has
+ // problems with BASIC authentication
+ location.append(request.getServerPort());
+ location.append(request.getRequestURI());
+ return location.toString();
+ }
+}
Modified: trunk/java/org/apache/jasper/security/SecurityUtil.java
===================================================================
--- trunk/java/org/apache/jasper/security/SecurityUtil.java 2008-06-06 14:37:41 UTC (rev 660)
+++ trunk/java/org/apache/jasper/security/SecurityUtil.java 2008-06-09 10:00:54 UTC (rev 661)
@@ -39,6 +39,43 @@
}
return false;
}
+
+ /**
+ * Filter the specified message string for characters that are sensitive
+ * in HTML. This avoids potential attacks caused by including JavaScript
+ * codes in the request URL that is often reported in error messages.
+ *
+ * @param message The message string to be filtered
+ */
+ public static String filter(String message) {
+
+ if (message == null)
+ return (null);
+
+ char content[] = new char[message.length()];
+ message.getChars(0, message.length(), content, 0);
+ StringBuffer result = new StringBuffer(content.length + 50);
+ for (int i = 0; i < content.length; i++) {
+ switch (content[i]) {
+ case '<':
+ result.append("<");
+ break;
+ case '>':
+ result.append(">");
+ break;
+ case '&':
+ result.append("&");
+ break;
+ case '"':
+ result.append(""");
+ break;
+ default:
+ result.append(content[i]);
+ }
+ }
+ return (result.toString());
+
+ }
}
Modified: trunk/java/org/apache/jasper/servlet/JspServlet.java
===================================================================
--- trunk/java/org/apache/jasper/servlet/JspServlet.java 2008-06-06 14:37:41 UTC (rev 660)
+++ trunk/java/org/apache/jasper/servlet/JspServlet.java 2008-06-09 10:00:54 UTC (rev 661)
@@ -29,14 +29,13 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.PeriodicEventListener;
-
import org.apache.jasper.Constants;
import org.apache.jasper.EmbeddedServletOptions;
import org.apache.jasper.Options;
import org.apache.jasper.compiler.JspRuntimeContext;
import org.apache.jasper.compiler.Localizer;
+import org.apache.jasper.security.SecurityUtil;
import org.jboss.logging.Logger;
-import org.jboss.logging.Logger;
/**
* The JSP engine (a.k.a Jasper).
@@ -311,8 +310,10 @@
if (includeRequestUri != null) {
// This file was included. Throw an exception as
// a response.sendError() will be ignored
- throw new ServletException(Localizer.getMessage(
- "jsp.error.file.not.found",jspUri));
+ String msg = Localizer.getMessage("jsp.error.file.not.found", jspUri);
+ // Strictly, filtering this is an application
+ // responsibility but just in case...
+ throw new ServletException(SecurityUtil.filter(msg));
} else {
try {
response.sendError(
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-06-06 14:37:41 UTC (rev 660)
+++ trunk/webapps/docs/changelog.xml 2008-06-09 10:00:54 UTC (rev 661)
@@ -60,6 +60,12 @@
<update>
Add HTTP/1.0 keep-alive to ClusterListener. (remm)
</update>
+ <add>
+ Add a new valve that works-around the broken MS WedDAV client. (markt)
+ </add>
+ <fix>
+ Fix XSS in the host manager. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
@@ -86,6 +92,10 @@
<fix>
<bug>44994</bug>: Correct BNF grammar so ${0 lt a ? 1 lt a ? "many": "one": "none"} works. (markt)
</fix>
+ <fix>
+ Add an additional layer of protection in case app fails to protect against an XSS.
+ Copied filter code to jasper module so no new dependency is created. (markt)
+ </fix>
</changelog>
</subsection>
</section>
17 years, 3 months
JBossWeb SVN: r660 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-06 10:37:41 -0400 (Fri, 06 Jun 2008)
New Revision: 660
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
Log:
- Clarify as URL prefix.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-05 18:53:08 UTC (rev 659)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-06 14:37:41 UTC (rev 660)
@@ -150,9 +150,9 @@
/**
- * Most likely only useful for testing.
+ * URL prefix.
*/
- protected String proxyURL = "/";
+ protected String proxyURL = null;
public String getProxyURL() { return proxyURL; }
public void setProxyURL(String proxyURL) { this.proxyURL = proxyURL; }
@@ -1148,7 +1148,17 @@
}
// Generate and write request
- String requestLine = command + " " + ((wildcard) ? "*" : proxyURL) + " HTTP/1.0";
+ String url = proxyURL;
+ if (url == null) {
+ url = (wildcard) ? "/*" : "/";
+ } else {
+ if (url.endsWith("/") && wildcard) {
+ url = url + "*";
+ } else if (wildcard) {
+ url = url + "/*";
+ }
+ }
+ String requestLine = command + " " + url + " HTTP/1.0";
writer.write(requestLine);
writer.write("\r\n");
writer.write("Content-Length: " + body.getLength() + "\r\n");
17 years, 3 months
JBossWeb SVN: r659 - in trunk: webapps/docs and 1 other directory.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-05 14:53:08 -0400 (Thu, 05 Jun 2008)
New Revision: 659
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
trunk/webapps/docs/changelog.xml
Log:
- Try adding HTTP/1.0 keepalive.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-05 00:47:39 UTC (rev 658)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-05 18:53:08 UTC (rev 659)
@@ -38,9 +38,6 @@
import javax.management.ObjectName;
import javax.net.ssl.KeyManagerFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import org.apache.catalina.Container;
@@ -117,6 +114,30 @@
protected JSSESocketFactory sslSocketFactory = null;
+ /**
+ * Active connections.
+ */
+ protected Socket[] connections = null;
+
+
+ /**
+ * Connection readers.
+ */
+ protected BufferedReader[] connectionReaders = null;
+
+
+ /**
+ * Connection writers.
+ */
+ protected BufferedWriter[] connectionWriters = null;
+
+
+ /**
+ * Initialization flag.
+ */
+ protected boolean init = false;
+
+
// ------------------------------------------------------------- Properties
@@ -139,7 +160,7 @@
/**
* Connection timeout for communication with the proxy.
*/
- protected int socketTimeout = 5000;
+ protected int socketTimeout = 20000;
public int getSocketTimeout() { return socketTimeout; }
public void setSocketTimeout(int socketTimeout) { this.socketTimeout = socketTimeout; }
@@ -467,8 +488,13 @@
proxies = proxyList.toArray(new Proxy[0]);
}
+ connections = new Socket[proxies.length];
+ connectionReaders = new BufferedReader[proxies.length];
+ connectionWriters = new BufferedWriter[proxies.length];
+
sslInit();
startServer((Server) source, -1);
+ init = true;
} else {
return;
}
@@ -478,11 +504,15 @@
stopContext((Context) source, -1);
} else if (source instanceof Server) {
stopServer((Server) source, -1);
+ for (int i = 0; i < connections.length; i++) {
+ closeConnection(i);
+ }
+ init = false;
} else {
return;
}
} else if (Lifecycle.PERIODIC_EVENT.equals(event.getType())) {
- if (source instanceof Engine) {
+ if (init && source instanceof Engine) {
status((Engine) source);
}
}
@@ -638,7 +668,7 @@
Connector connector = findProxyConnector(engine.getService().findConnectors());
InetAddress localAddress =
(InetAddress) IntrospectionUtils.getProperty(connector.getProtocolHandler(), "address");
- if (engine.getJvmRoute() == null || localAddress == null) {
+ if ((engine.getJvmRoute() == null || localAddress == null) && proxies.length > 0) {
// Automagical JVM route (address + port + engineName)
try {
if (localAddress == null) {
@@ -650,7 +680,6 @@
// Should not happen
IntrospectionUtils.setProperty(connector.getProtocolHandler(), "address", "127.0.0.1");
}
- connection.close();
log.info(sm.getString("clusterListener.address", localAddress.getHostAddress()));
}
if (engine.getJvmRoute() == null) {
@@ -1055,7 +1084,6 @@
BufferedReader reader = null;
BufferedWriter writer = null;
CharChunk body = null;
- Socket connection = null;
// First, encode the POST body
try {
@@ -1105,23 +1133,34 @@
try {
// Then, connect to the proxy
- connection = getConnection(i);
- connection.setSoTimeout(socketTimeout);
+ getConnection(i);
+ writer = getConnectionWriter(i);
+ // Check connection to see if it is still alive (not really allowed,
+ // but httpd deals with the extra CRLF)
+ try {
+ writer.write("\r\n");
+ writer.flush();
+ } catch (IOException e) {
+ // Get a new connection; if it fails this second time, it is an error
+ closeConnection(i);
+ getConnection(i);
+ writer = getConnectionWriter(i);
+ }
+ // Generate and write request
String requestLine = command + " " + ((wildcard) ? "*" : proxyURL) + " HTTP/1.0";
- int contentLength = body.getLength();
- writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
writer.write(requestLine);
writer.write("\r\n");
- writer.write("Content-Length: " + contentLength + "\r\n");
+ writer.write("Content-Length: " + body.getLength() + "\r\n");
writer.write("User-Agent: ClusterListener/1.0\r\n");
+ writer.write("Connection: Keep-Alive\r\n");
writer.write("\r\n");
writer.write(body.getBuffer(), body.getStart(), body.getLength());
writer.write("\r\n");
writer.flush();
// Read the response to a string
- reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
+ reader = getConnectionReader(i);
// Read the first response line and skip the rest of the HTTP header
String responseStatus = reader.readLine();
// Parse the line, which is formed like HTTP/1.x YYY Message
@@ -1129,6 +1168,7 @@
String version = "0";
String message = null;
String errorType = null;
+ int contentLength = 0;
try {
responseStatus = responseStatus.substring(responseStatus.indexOf(' ') + 1, responseStatus.indexOf(' ', responseStatus.indexOf(' ') + 1));
status = Integer.parseInt(responseStatus);
@@ -1143,6 +1183,8 @@
errorType = headerValue;
} else if ("mess".equalsIgnoreCase(headerName)) {
message = headerValue;
+ } else if ("content-length".equalsIgnoreCase(headerName)) {
+ contentLength = Integer.parseInt(headerValue);
}
header = reader.readLine();
}
@@ -1155,13 +1197,18 @@
if (status == 200) {
// Read the request body
StringBuffer result = new StringBuffer();
- char[] buf = new char[512];
- while (true) {
- int n = reader.read(buf);
- if (n <= 0) {
- break;
- } else {
- result.append(buf, 0, n);
+ if (contentLength > 0) {
+ int thisTime = contentLength;
+ char[] buf = new char[512];
+ while (contentLength > 0) {
+ thisTime = (contentLength > buf.length) ? buf.length : contentLength;
+ int n = reader.read(buf, 0, thisTime);
+ if (n <= 0) {
+ break;
+ } else {
+ result.append(buf, 0, n);
+ contentLength -= n;
+ }
}
}
if (pos != -1) {
@@ -1183,27 +1230,10 @@
proxies[i].state = State.ERROR;
log.info(sm.getString("clusterListener.error.io", command, proxies[i]), e);
} finally {
- if (writer != null) {
- try {
- writer.close();
- } catch (IOException e) {
- // Ignore
- }
+ // If there's an error of any sort, or if the proxy did not return 200, it is an error
+ if (proxies[i].state != State.OK) {
+ closeConnection(i);
}
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- // Ignore
- }
- }
- if (connection != null) {
- try {
- connection.close();
- } catch (IOException e) {
- // Ignore
- }
- }
}
}
@@ -1224,20 +1254,78 @@
/**
- * Return a connection to the proxy.
+ * Return a reader to the proxy.
*/
protected Socket getConnection(int i)
throws IOException {
- InetAddress address =
- (proxies[i].address == null) ? InetAddress.getLocalHost() : proxies[i].address;
- if (ssl) {
- return sslSocketFactory.createSocket(address, proxies[i].port);
- } else {
- return new Socket(address, proxies[i].port);
+ if (connections[i] == null) {
+ InetAddress address = (proxies[i].address == null) ? InetAddress.getLocalHost() : proxies[i].address;
+ if (ssl) {
+ connections[i] = sslSocketFactory.createSocket(address, proxies[i].port);
+ } else {
+ connections[i] = new Socket(address, proxies[i].port);
+ }
+ connections[i].setSoTimeout(socketTimeout);
}
+ return connections[i];
}
+
+ /**
+ * Return a reader to the proxy.
+ */
+ protected BufferedReader getConnectionReader(int i)
+ throws IOException {
+ if (connectionReaders[i] == null) {
+ connectionReaders[i] = new BufferedReader(new InputStreamReader(connections[i].getInputStream()));
+ }
+ return connectionReaders[i];
+ }
+
+ /**
+ * Return a writer to the proxy.
+ */
+ protected BufferedWriter getConnectionWriter(int i)
+ throws IOException {
+ if (connectionWriters[i] == null) {
+ connectionWriters[i] = new BufferedWriter(new OutputStreamWriter(connections[i].getOutputStream()));
+ }
+ return connectionWriters[i];
+ }
+
+
+ /**
+ * Close connection.
+ */
+ protected void closeConnection(int i) {
+ try {
+ if (connectionReaders[i] != null) {
+ connectionReaders[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connectionReaders[i] = null;
+ try {
+ if (connectionWriters[i] != null) {
+ connectionWriters[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connectionWriters[i] = null;
+ try {
+ if (connections[i] != null) {
+ connections[i].close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ connections[i] = null;
+ }
+
+
// ------------------------------------------------------ Proxy Inner Class
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-06-05 00:47:39 UTC (rev 658)
+++ trunk/webapps/docs/changelog.xml 2008-06-05 18:53:08 UTC (rev 659)
@@ -55,8 +55,11 @@
Avoid overriding existing system properties. (remm)
</fix>
<update>
- Add security to ClusterListener using SSL client certificate. (remm)
+ Add security to ClusterListener using SSL and possible client certificate usage. (remm)
</update>
+ <update>
+ Add HTTP/1.0 keep-alive to ClusterListener. (remm)
+ </update>
</changelog>
</subsection>
<subsection name="Coyote">
17 years, 3 months
JBossWeb SVN: r658 - trunk/java/org/jboss/web/cluster.
by jbossweb-commits@lists.jboss.org
Author: remy.maucherat(a)jboss.com
Date: 2008-06-04 20:47:39 -0400 (Wed, 04 Jun 2008)
New Revision: 658
Modified:
trunk/java/org/jboss/web/cluster/ClusterListener.java
trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
Log:
- Use the socket factory.
Modified: trunk/java/org/jboss/web/cluster/ClusterListener.java
===================================================================
--- trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-04 19:57:54 UTC (rev 657)
+++ trunk/java/org/jboss/web/cluster/ClusterListener.java 2008-06-05 00:47:39 UTC (rev 658)
@@ -114,9 +114,9 @@
/**
* Socket factory.
*/
+ protected JSSESocketFactory sslSocketFactory = null;
-
// ------------------------------------------------------------- Properties
@@ -1217,6 +1217,9 @@
* SSL init.
*/
protected void sslInit() {
+ if (ssl) {
+ sslSocketFactory = new JSSESocketFactory(this);
+ }
}
@@ -1225,25 +1228,22 @@
*/
protected Socket getConnection(int i)
throws IOException {
- // FIXME: Add SSL (using a client cert)
- if (!ssl) {
- if (proxies[i].address == null) {
- return new Socket(InetAddress.getLocalHost(), proxies[i].port);
- } else {
- return new Socket(proxies[i].address, proxies[i].port);
- }
+ InetAddress address =
+ (proxies[i].address == null) ? InetAddress.getLocalHost() : proxies[i].address;
+ if (ssl) {
+ return sslSocketFactory.createSocket(address, proxies[i].port);
} else {
- if (proxies[i].address == null) {
- return SSLSocketFactory.getDefault()
- .createSocket(InetAddress.getLocalHost(), proxies[i].port);
- } else {
- return SSLSocketFactory.getDefault()
- .createSocket(proxies[i].address, proxies[i].port);
- }
+ return new Socket(address, proxies[i].port);
}
}
+ // ------------------------------------------------------ Proxy Inner Class
+
+
+ /**
+ * This class represents a front-end httpd server.
+ */
protected static class Proxy {
public InetAddress address = null;
public int port = 8000;
Modified: trunk/java/org/jboss/web/cluster/JSSESocketFactory.java
===================================================================
--- trunk/java/org/jboss/web/cluster/JSSESocketFactory.java 2008-06-04 19:57:54 UTC (rev 657)
+++ trunk/java/org/jboss/web/cluster/JSSESocketFactory.java 2008-06-05 00:47:39 UTC (rev 658)
@@ -23,9 +23,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
-import java.net.ServerSocket;
import java.net.Socket;
-import java.net.SocketException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CRL;
@@ -39,7 +37,6 @@
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CertSelector;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Vector;
import javax.net.ssl.CertPathTrustManagerParameters;
@@ -47,7 +44,6 @@
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
17 years, 3 months