Merge branch 'master' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project

This commit is contained in:
hmalphettes 2011-09-14 16:34:33 +08:00
commit 1cbf5c4672
26 changed files with 1386 additions and 496 deletions

23
.gitignore vendored
View File

@ -1,14 +1,33 @@
target/ # eclipse
.classpath .classpath
.project .project
.settings .settings
# maven
target/
*/src/main/java/META-INF/ */src/main/java/META-INF/
.pmd
# common junk
*.log *.log
*.swp *.swp
*.diff *.diff
*.patch *.patch
# intellij
*.iml *.iml
*.ipr *.ipr
*.iws *.iws
.idea/ .idea/
# Mac filesystem dust
/.DS_Store
# pmd
.pmdruleset
.pmd
# netbeans
/nbproject
# vim
.*.sw[a-p]

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all-server</artifactId> <artifactId>jetty-all-server</artifactId>
<name>Jetty :: Aggregate :: All Server</name> <name>Jetty :: Aggregate :: All Server</name>
<properties> <properties>

View File

@ -5,10 +5,8 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId> <artifactId>jetty-all</artifactId>
<name>Jetty :: Aggregate :: All core Jetty</name> <name>Jetty :: Aggregate :: All core Jetty</name>
<build> <build>
<sourceDirectory>${project.build.directory}/sources</sourceDirectory> <sourceDirectory>${project.build.directory}/sources</sourceDirectory>
<plugins> <plugins>

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-client</artifactId> <artifactId>jetty-client</artifactId>
<name>Jetty :: Aggregate :: HTTP Client</name> <name>Jetty :: Aggregate :: HTTP Client</name>

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-plus</artifactId> <artifactId>jetty-plus</artifactId>
<name>Jetty :: Aggregate :: Plus Server</name> <name>Jetty :: Aggregate :: Plus Server</name>

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-server</artifactId> <artifactId>jetty-server</artifactId>
<name>Jetty :: Aggregate :: HTTP Server</name> <name>Jetty :: Aggregate :: HTTP Server</name>

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-servlet</artifactId> <artifactId>jetty-servlet</artifactId>
<name>Jetty :: Aggregate :: Servlet Server</name> <name>Jetty :: Aggregate :: Servlet Server</name>

View File

@ -5,7 +5,6 @@
<version>7.5.2-SNAPSHOT</version> <version>7.5.2-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-webapp</artifactId> <artifactId>jetty-webapp</artifactId>
<name>Jetty :: Aggregate :: WebApp Server</name> <name>Jetty :: Aggregate :: WebApp Server</name>

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials // All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0 // are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution. // and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at // The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html // http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at // The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php // http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses. // You may elect to redistribute this code under either of these licenses.
// ======================================================================== // ========================================================================
package org.eclipse.jetty.io.nio; package org.eclipse.jetty.io.nio;
@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.ConnectedEndPoint; import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
@ -55,7 +54,7 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable
{ {
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio"); public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
// TODO Tune these by approx system speed. // TODO Tune these by approx system speed.
private static final int __JVMBUG_THRESHHOLD=Integer.getInteger("org.eclipse.jetty.io.nio.JVMBUG_THRESHHOLD",0).intValue(); private static final int __JVMBUG_THRESHHOLD=Integer.getInteger("org.eclipse.jetty.io.nio.JVMBUG_THRESHHOLD",0).intValue();
private static final int __MONITOR_PERIOD=Integer.getInteger("org.eclipse.jetty.io.nio.MONITOR_PERIOD",1000).intValue(); private static final int __MONITOR_PERIOD=Integer.getInteger("org.eclipse.jetty.io.nio.MONITOR_PERIOD",1000).intValue();
@ -63,7 +62,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
private static final int __BUSY_PAUSE=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_PAUSE",50).intValue(); private static final int __BUSY_PAUSE=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_PAUSE",50).intValue();
private static final int __BUSY_KEY=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_KEY",-1).intValue(); private static final int __BUSY_KEY=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_KEY",-1).intValue();
private static final int __IDLE_TICK=Integer.getInteger("org.eclipse.jetty.io.nio.IDLE_TICK",400).intValue(); private static final int __IDLE_TICK=Integer.getInteger("org.eclipse.jetty.io.nio.IDLE_TICK",400).intValue();
private int _maxIdleTime; private int _maxIdleTime;
private int _lowResourcesMaxIdleTime; private int _lowResourcesMaxIdleTime;
private long _lowResourcesConnections; private long _lowResourcesConnections;
@ -72,7 +71,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
private volatile int _set; private volatile int _set;
private boolean _deferringInterestedOps0=true; private boolean _deferringInterestedOps0=true;
private int _selectorPriorityDelta=0; private int _selectorPriorityDelta=0;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param maxIdleTime The maximum period in milli seconds that a connection may be idle before it is closed. * @param maxIdleTime The maximum period in milli seconds that a connection may be idle before it is closed.
@ -82,18 +81,18 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
_maxIdleTime=(int)maxIdleTime; _maxIdleTime=(int)maxIdleTime;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param selectSets number of select sets to create * @param selectSets number of select sets to create
*/ */
public void setSelectSets(int selectSets) public void setSelectSets(int selectSets)
{ {
long lrc = _lowResourcesConnections * _selectSets; long lrc = _lowResourcesConnections * _selectSets;
_selectSets=selectSets; _selectSets=selectSets;
_lowResourcesConnections=lrc/_selectSets; _lowResourcesConnections=lrc/_selectSets;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return the max idle time * @return the max idle time
@ -102,7 +101,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
return _maxIdleTime; return _maxIdleTime;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return the number of select sets in use * @return the number of select sets in use
@ -114,14 +113,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param i * @param i
* @return The select set * @return The select set
*/ */
public SelectSet getSelectSet(int i) public SelectSet getSelectSet(int i)
{ {
return _selectSet[i]; return _selectSet[i];
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Register a channel /** Register a channel
* @param channel * @param channel
@ -132,8 +131,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter. // The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will // so long as the value changes sometimes, then connections will
// be distributed over the available sets. // be distributed over the available sets.
int s=_set++; int s=_set++;
s=s%_selectSets; s=s%_selectSets;
SelectSet[] sets=_selectSet; SelectSet[] sets=_selectSet;
if (sets!=null) if (sets!=null)
@ -144,7 +143,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Register a channel /** Register a channel
* @param channel * @param channel
@ -154,8 +153,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter. // The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will // so long as the value changes sometimes, then connections will
// be distributed over the available sets. // be distributed over the available sets.
int s=_set++; int s=_set++;
s=s%_selectSets; s=s%_selectSets;
SelectSet[] sets=_selectSet; SelectSet[] sets=_selectSet;
if (sets!=null) if (sets!=null)
@ -165,14 +164,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
set.wakeup(); set.wakeup();
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Register a {@link ServerSocketChannel} /** Register a {@link ServerSocketChannel}
* @param acceptChannel * @param acceptChannel
*/ */
public void register(ServerSocketChannel acceptChannel) public void register(ServerSocketChannel acceptChannel)
{ {
int s=_set++; int s=_set++;
s=s%_selectSets; s=s%_selectSets;
SelectSet set=_selectSet[s]; SelectSet set=_selectSet[s];
set.addChange(acceptChannel); set.addChange(acceptChannel);
@ -196,8 +195,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
_selectorPriorityDelta=delta; _selectorPriorityDelta=delta;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return the lowResourcesConnections * @return the lowResourcesConnections
@ -237,7 +236,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
_lowResourcesMaxIdleTime=(int)lowResourcesMaxIdleTime; _lowResourcesMaxIdleTime=(int)lowResourcesMaxIdleTime;
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
public abstract boolean dispatch(Runnable task); public abstract boolean dispatch(Runnable task);
@ -254,7 +253,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selectSet[i]= new SelectSet(i); _selectSet[i]= new SelectSet(i);
super.doStart(); super.doStart();
// start a thread to Select // start a thread to Select
for (int i=0;i<getSelectSets();i++) for (int i=0;i<getSelectSets();i++)
{ {
@ -271,7 +270,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (sets==null) if (sets==null)
return; return;
SelectSet set=sets[id]; SelectSet set=sets[id];
Thread.currentThread().setName(name+" Selector"+id); Thread.currentThread().setName(name+" Selector"+id);
if (getSelectorPriorityDelta()!=0) if (getSelectorPriorityDelta()!=0)
Thread.currentThread().setPriority(Thread.currentThread().getPriority()+getSelectorPriorityDelta()); Thread.currentThread().setPriority(Thread.currentThread().getPriority()+getSelectorPriorityDelta());
@ -362,7 +361,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
LOG.warn(ex+","+channel+","+attachment); LOG.warn(ex+","+channel+","+attachment);
LOG.debug(ex); LOG.debug(ex);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public String dump() public String dump()
{ {
@ -375,8 +374,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
out.append(String.valueOf(this)).append("\n"); out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,TypeUtil.asList(_selectSet)); AggregateLifeCycle.dump(out,indent,TypeUtil.asList(_selectSet));
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@ -384,11 +383,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
private final int _setID; private final int _setID;
private final Timeout _timeout; private final Timeout _timeout;
private final ConcurrentLinkedQueue<Object> _changes = new ConcurrentLinkedQueue<Object>(); private final ConcurrentLinkedQueue<Object> _changes = new ConcurrentLinkedQueue<Object>();
private volatile Selector _selector; private volatile Selector _selector;
private volatile Thread _selecting; private volatile Thread _selecting;
private int _jvmBug; private int _jvmBug;
private int _selects; private int _selects;
@ -404,7 +403,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
private int _jvmFix2; private int _jvmFix2;
private volatile long _idleTick; private volatile long _idleTick;
private ConcurrentMap<SelectChannelEndPoint,Object> _endPoints = new ConcurrentHashMap<SelectChannelEndPoint, Object>(); private ConcurrentMap<SelectChannelEndPoint,Object> _endPoints = new ConcurrentHashMap<SelectChannelEndPoint, Object>();
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
SelectSet(int acceptorID) throws Exception SelectSet(int acceptorID) throws Exception
{ {
@ -420,7 +419,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_monitorNext=_monitorStart+__MONITOR_PERIOD; _monitorNext=_monitorStart+__MONITOR_PERIOD;
_log=_monitorStart+60000; _log=_monitorStart+60000;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void addChange(Object change) public void addChange(Object change)
{ {
@ -429,7 +428,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void addChange(SelectableChannel channel, Object att) public void addChange(SelectableChannel channel, Object att)
{ {
if (att==null) if (att==null)
addChange(channel); addChange(channel);
else if (att instanceof EndPoint) else if (att instanceof EndPoint)
@ -437,11 +436,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
else else
addChange(new ChannelAndAttachment(channel,att)); addChange(new ChannelAndAttachment(channel,att));
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* Select and dispatch tasks found from changes and the selector. * Select and dispatch tasks found from changes and the selector.
* *
* @throws IOException * @throws IOException
*/ */
public void doSelect() throws IOException public void doSelect() throws IOException
@ -450,6 +449,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
_selecting=Thread.currentThread(); _selecting=Thread.currentThread();
final Selector selector=_selector; final Selector selector=_selector;
// Stopped concurrently ?
if (selector == null)
return;
// Make any key changes required // Make any key changes required
Object change; Object change;
@ -458,7 +460,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
Channel ch=null; Channel ch=null;
SelectionKey key=null; SelectionKey key=null;
try try
{ {
if (change instanceof EndPoint) if (change instanceof EndPoint)
@ -475,7 +477,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
final SelectableChannel channel=asc._channel; final SelectableChannel channel=asc._channel;
ch=channel; ch=channel;
final Object att = asc._attachment; final Object att = asc._attachment;
if ((channel instanceof SocketChannel) && ((SocketChannel)channel).isConnected()) if ((channel instanceof SocketChannel) && ((SocketChannel)channel).isConnected())
{ {
key = channel.register(selector,SelectionKey.OP_READ,att); key = channel.register(selector,SelectionKey.OP_READ,att);
@ -517,7 +519,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
if (e instanceof ThreadDeath) if (e instanceof ThreadDeath)
throw (ThreadDeath)e; throw (ThreadDeath)e;
if (isRunning()) if (isRunning())
LOG.warn(e); LOG.warn(e);
else else
@ -540,7 +542,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selects++; _selects++;
long now=System.currentTimeMillis(); long now=System.currentTimeMillis();
// if no immediate things to do // if no immediate things to do
if (selected==0 && selector.selectedKeys().isEmpty()) if (selected==0 && selector.selectedKeys().isEmpty())
{ {
@ -562,7 +564,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_timeout.setNow(now); _timeout.setNow(now);
long to_next_timeout=_timeout.getTimeToNext(); long to_next_timeout=_timeout.getTimeToNext();
long wait = _changes.size()==0?__IDLE_TICK:0L; long wait = _changes.size()==0?__IDLE_TICK:0L;
if (wait > 0 && to_next_timeout >= 0 && wait > to_next_timeout) if (wait > 0 && to_next_timeout >= 0 && wait > to_next_timeout)
wait = to_next_timeout; wait = to_next_timeout;
@ -574,21 +576,21 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selects++; _selects++;
now = System.currentTimeMillis(); now = System.currentTimeMillis();
_timeout.setNow(now); _timeout.setNow(now);
if (__JVMBUG_THRESHHOLD>0) if (__JVMBUG_THRESHHOLD>0)
checkJvmBugs(before, now, wait, selected); checkJvmBugs(before, now, wait, selected);
} }
} }
// have we been destroyed while sleeping // have we been destroyed while sleeping
if (_selector==null || !selector.isOpen()) if (_selector==null || !selector.isOpen())
return; return;
// Look for things to do // Look for things to do
for (SelectionKey key: selector.selectedKeys()) for (SelectionKey key: selector.selectedKeys())
{ {
SocketChannel channel=null; SocketChannel channel=null;
try try
{ {
if (!key.isValid()) if (!key.isValid())
@ -641,7 +643,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
SelectChannelEndPoint endpoint = createEndPoint(channel,key); SelectChannelEndPoint endpoint = createEndPoint(channel,key);
key.attach(endpoint); key.attach(endpoint);
if (key.isReadable()) if (key.isReadable())
endpoint.schedule(); endpoint.schedule();
} }
key = null; key = null;
} }
@ -665,15 +667,15 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
LOG.debug(e2); LOG.debug(e2);
} }
if (key != null && !(key.channel() instanceof ServerSocketChannel) && key.isValid()) if (key != null && !(key.channel() instanceof ServerSocketChannel) && key.isValid())
key.cancel(); key.cancel();
} }
} }
// Everything always handled // Everything always handled
selector.selectedKeys().clear(); selector.selectedKeys().clear();
now=System.currentTimeMillis(); now=System.currentTimeMillis();
_timeout.setNow(now); _timeout.setNow(now);
Task task = _timeout.expired(); Task task = _timeout.expired();
@ -688,11 +690,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (now-_idleTick>__IDLE_TICK) if (now-_idleTick>__IDLE_TICK)
{ {
_idleTick=now; _idleTick=now;
final long idle_now=((_lowResourcesConnections>0 && selector.keys().size()>_lowResourcesConnections)) final long idle_now=((_lowResourcesConnections>0 && selector.keys().size()>_lowResourcesConnections))
?(now+_maxIdleTime-_lowResourcesMaxIdleTime) ?(now+_maxIdleTime-_lowResourcesMaxIdleTime)
:now; :now;
dispatch(new Runnable() dispatch(new Runnable()
{ {
public void run() public void run()
@ -721,7 +723,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selecting=null; _selecting=null;
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private void checkJvmBugs(long before, long now, long wait, int selected) private void checkJvmBugs(long before, long now, long wait, int selected)
throws IOException throws IOException
@ -729,7 +731,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
Selector selector = _selector; Selector selector = _selector;
if (selector==null) if (selector==null)
return; return;
// Look for JVM bugs over a monitor period. // Look for JVM bugs over a monitor period.
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933 // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933
// http://bugs.sun.com/view_bug.do?bug_id=6693490 // http://bugs.sun.com/view_bug.do?bug_id=6693490
@ -748,7 +750,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (now>_log) if (now>_log)
{ {
if (_paused>0) if (_paused>0)
LOG.debug(this+" Busy selector - injecting delay "+_paused+" times"); LOG.debug(this+" Busy selector - injecting delay "+_paused+" times");
if (_jvmFix2>0) if (_jvmFix2>0)
@ -842,9 +844,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_busyKey=busy; _busyKey=busy;
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private void renewSelector() private void renewSelector()
{ {
try try
{ {
@ -876,7 +878,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
throw new RuntimeException("recreating selector",e); throw new RuntimeException("recreating selector",e);
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public SelectorManager getManager() public SelectorManager getManager()
{ {
@ -891,9 +893,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @param task The task to timeout. If it implements Runnable, then * @param task The task to timeout. If it implements Runnable, then
* expired will be called from a dispatched thread. * expired will be called from a dispatched thread.
* *
* @param timeoutMs * @param timeoutMs
*/ */
public void scheduleTimeout(Timeout.Task task, long timeoutMs) public void scheduleTimeout(Timeout.Task task, long timeoutMs)
@ -902,7 +904,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
throw new IllegalArgumentException("!Runnable"); throw new IllegalArgumentException("!Runnable");
_timeout.schedule(task, timeoutMs); _timeout.schedule(task, timeoutMs);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void cancelTimeout(Timeout.Task task) public void cancelTimeout(Timeout.Task task)
{ {
@ -927,20 +929,20 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
renewSelector(); renewSelector();
} }
}); });
renewSelector(); renewSelector();
} }
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private SelectChannelEndPoint createEndPoint(SocketChannel channel, SelectionKey sKey) throws IOException private SelectChannelEndPoint createEndPoint(SocketChannel channel, SelectionKey sKey) throws IOException
{ {
SelectChannelEndPoint endp = newEndPoint(channel,this,sKey); SelectChannelEndPoint endp = newEndPoint(channel,this,sKey);
endPointOpened(endp); endPointOpened(endp);
_endPoints.put(endp,this); _endPoints.put(endp,this);
return endp; return endp;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void destroyEndPoint(SelectChannelEndPoint endp) public void destroyEndPoint(SelectChannelEndPoint endp)
{ {
@ -953,11 +955,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
return _selector; return _selector;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
void stop() throws Exception void stop() throws Exception
{ {
// Spin for a while waiting for selector to complete // Spin for a while waiting for selector to complete
// to avoid unneccessary closed channel exceptions // to avoid unneccessary closed channel exceptions
try try
{ {
@ -994,8 +996,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
} }
} }
} }
_timeout.cancelAll(); _timeout.cancelAll();
try try
{ {
@ -1006,7 +1008,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
catch (IOException e) catch (IOException e)
{ {
LOG.ignore(e); LOG.ignore(e);
} }
_selector=null; _selector=null;
} }
} }
@ -1021,9 +1023,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
public void dump(Appendable out, String indent) throws IOException public void dump(Appendable out, String indent) throws IOException
{ {
out.append(String.valueOf(this)).append(" id=").append(String.valueOf(_setID)).append("\n"); out.append(String.valueOf(this)).append(" id=").append(String.valueOf(_setID)).append("\n");
Thread selecting = _selecting; Thread selecting = _selecting;
Object where = "not selecting"; Object where = "not selecting";
StackTraceElement[] trace =selecting==null?null:selecting.getStackTrace(); StackTraceElement[] trace =selecting==null?null:selecting.getStackTrace();
if (trace!=null) if (trace!=null)
@ -1039,9 +1041,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
Selector selector=_selector; Selector selector=_selector;
final ArrayList<Object> dump = new ArrayList<Object>(selector.keys().size()*2); final ArrayList<Object> dump = new ArrayList<Object>(selector.keys().size()*2);
dump.add(where); dump.add(where);
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
addChange(new Runnable(){ addChange(new Runnable(){
public void run() public void run()
{ {
@ -1049,7 +1051,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
latch.countDown(); latch.countDown();
} }
}); });
try try
{ {
latch.await(5,TimeUnit.SECONDS); latch.await(5,TimeUnit.SECONDS);
@ -1081,7 +1083,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
final SelectableChannel _channel; final SelectableChannel _channel;
final Object _attachment; final Object _attachment;
public ChannelAndAttachment(SelectableChannel channel, Object attachment) public ChannelAndAttachment(SelectableChannel channel, Object attachment)
{ {
super(); super();
@ -1101,12 +1103,12 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
_deferringInterestedOps0 = deferringInterestedOps0; _deferringInterestedOps0 = deferringInterestedOps0;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private interface ChangeTask extends Runnable private interface ChangeTask extends Runnable
{} {}
} }

View File

@ -0,0 +1,69 @@
// ========================================================================
// Copyright (c) 2011 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.jndi;
import java.util.Iterator;
import javax.naming.Binding;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
/** BindingEnumeration
* <p>Implementation of NamingEnumeration
*
* <p><h4>Notes</h4>
* <p>Used to return results of Context.listBindings();
*
* <p><h4>Usage</h4>
*
*/
public class BindingEnumeration implements NamingEnumeration<Binding>
{
Iterator<Binding> _delegate;
public BindingEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public Binding next()
throws NamingException
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(), true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public Binding nextElement()
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(),true);
}
}

View File

@ -0,0 +1,69 @@
// ========================================================================
// Copyright (c) 2011 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.jndi;
import java.util.Iterator;
import javax.naming.Binding;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
/** NameEnumeration
* <p>Implementation of NamingEnumeration interface.
*
* <p><h4>Notes</h4>
* <p>Used for returning results of Context.list();
*
* <p><h4>Usage</h4>
*
*/
public class NameEnumeration implements NamingEnumeration<NameClassPair>
{
Iterator<Binding> _delegate;
public NameEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public NameClassPair next()
throws NamingException
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public NameClassPair nextElement()
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
}

View File

@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -31,7 +30,6 @@ import javax.naming.InitialContext;
import javax.naming.LinkRef; import javax.naming.LinkRef;
import javax.naming.Name; import javax.naming.Name;
import javax.naming.NameAlreadyBoundException; import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException; import javax.naming.NameNotFoundException;
import javax.naming.NameParser; import javax.naming.NameParser;
import javax.naming.NamingEnumeration; import javax.naming.NamingEnumeration;
@ -53,17 +51,8 @@ import org.eclipse.jetty.util.log.Logger;
* <p><h4>Notes</h4> * <p><h4>Notes</h4>
* <p>All Names are expected to be Compound, not Composite. * <p>All Names are expected to be Compound, not Composite.
* *
* <p><h4>Usage</h4> *
* <pre>
*/ */
/*
* </pre>
*
* @see
*
*
* @version 1.0
*/
public class NamingContext implements Context, Cloneable, Dumpable public class NamingContext implements Context, Cloneable, Dumpable
{ {
private final static Logger __log=NamingUtil.__log; private final static Logger __log=NamingUtil.__log;
@ -101,123 +90,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
void unbind(NamingContext ctx, Binding binding); void unbind(NamingContext ctx, Binding binding);
} }
/*------------------------------------------------*/
/** NameEnumeration
* <p>Implementation of NamingEnumeration interface.
*
* <p><h4>Notes</h4>
* <p>Used for returning results of Context.list();
*
* <p><h4>Usage</h4>
* <pre>
*/
/*
* </pre>
*
* @see
*
*/
public class NameEnumeration implements NamingEnumeration<NameClassPair>
{
Iterator<Binding> _delegate;
public NameEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public NameClassPair next()
throws NamingException
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public NameClassPair nextElement()
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
}
/*------------------------------------------------*/
/** BindingEnumeration
* <p>Implementation of NamingEnumeration
*
* <p><h4>Notes</h4>
* <p>Used to return results of Context.listBindings();
*
* <p><h4>Usage</h4>
* <pre>
*/
/*
* </pre>
*
* @see
*
*/
public class BindingEnumeration implements NamingEnumeration<Binding>
{
Iterator<Binding> _delegate;
public BindingEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public Binding next()
throws NamingException
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(), true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public Binding nextElement()
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(),true);
}
}
/*------------------------------------------------*/ /*------------------------------------------------*/
/** /**
* Constructor * Constructor
@ -240,26 +112,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
} }
/*------------------------------------------------*/
/**
* Creates a new <code>NamingContext</code> instance.
*
* @param env a <code>Hashtable</code> value
*/
public NamingContext (Hashtable<String,Object> env)
{
if (env != null)
_env.putAll(env);
}
/*------------------------------------------------*/
/**
* Constructor
*
*/
public NamingContext ()
{
}
/*------------------------------------------------*/ /*------------------------------------------------*/
@ -312,8 +164,24 @@ public class NamingContext implements Context, Cloneable, Dumpable
_parser = parser; _parser = parser;
} }
public void setEnv (Hashtable<String,Object> env)
{
_env.clear();
_env.putAll(env);
}
public Map<String,Binding> getBindings ()
{
return _bindings;
}
public void setBindings(Map<String,Binding> bindings)
{
_bindings = bindings;
}
/*------------------------------------------------*/ /*------------------------------------------------*/
/** /**
* Bind a name to an object * Bind a name to an object
@ -435,8 +303,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
ne.setRemainingName(name); ne.setRemainingName(name);
throw ne; throw ne;
} }
Name cname = toCanonicalName (name); Name cname = toCanonicalName (name);
@ -521,7 +387,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
/*------------------------------------------------*/ /*------------------------------------------------*/
/** /**
* Not supported *
* *
* @param name name of subcontext to remove * @param name name of subcontext to remove
* @exception NamingException if an error occurs * @exception NamingException if an error occurs
@ -536,7 +402,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
/*------------------------------------------------*/ /*------------------------------------------------*/
/** /**
* Not supported *
* *
* @param name name of subcontext to remove * @param name name of subcontext to remove
* @exception NamingException if an error occurs * @exception NamingException if an error occurs
@ -1128,7 +994,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
ctx = binding.getObject(); ctx = binding.getObject();
if (ctx instanceof Reference) if (ctx instanceof Reference)
{ {
//deference the object //deference the object
@ -1154,8 +1019,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
} }
else else
throw new NotContextException ("Object bound at "+firstComponent +" is not a Context"); throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
} }
} }
/*------------------------------------------------*/ /*------------------------------------------------*/
@ -1182,11 +1046,11 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param newName a <code>Name</code> value * @param newName a <code>Name</code> value
* @exception NamingException if an error occurs * @exception NamingException if an error occurs
*/ public void rename(String oldName, */ public void rename(String oldName,
String newName) String newName)
throws NamingException throws NamingException
{ {
throw new OperationNotSupportedException(); throw new OperationNotSupportedException();
} }
@ -1247,9 +1111,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
*/ */
public void close () public void close ()
throws NamingException throws NamingException
{ {
} }
@ -1362,7 +1224,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name a <code>Name</code> value * @param name a <code>Name</code> value
* @param obj an <code>Object</code> value * @param obj an <code>Object</code> value
*/ */
protected void addBinding (Name name, Object obj) throws NameAlreadyBoundException public void addBinding (Name name, Object obj) throws NameAlreadyBoundException
{ {
String key = name.toString(); String key = name.toString();
Binding binding=new Binding (key, obj); Binding binding=new Binding (key, obj);
@ -1394,7 +1256,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name a <code>Name</code> value * @param name a <code>Name</code> value
* @return a <code>Binding</code> value * @return a <code>Binding</code> value
*/ */
protected Binding getBinding (Name name) public Binding getBinding (Name name)
{ {
return (Binding) _bindings.get(name.toString()); return (Binding) _bindings.get(name.toString());
} }
@ -1407,13 +1269,13 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name as a String * @param name as a String
* @return null or the Binding * @return null or the Binding
*/ */
protected Binding getBinding (String name) public Binding getBinding (String name)
{ {
return (Binding) _bindings.get(name); return (Binding) _bindings.get(name);
} }
/*------------------------------------------------*/ /*------------------------------------------------*/
protected void removeBinding (Name name) public void removeBinding (Name name)
{ {
String key = name.toString(); String key = name.toString();
if (__log.isDebugEnabled()) if (__log.isDebugEnabled())
@ -1455,7 +1317,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
private boolean isLocked() public boolean isLocked()
{ {
if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null)) if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null))
return false; return false;

View File

@ -67,8 +67,7 @@ public class javaRootURLContext implements Context
try try
{ {
__javaNameParser = new javaNameParser(); __javaNameParser = new javaNameParser();
__nameRoot = new NamingContext(); __nameRoot = new NamingContext(null,null,null,__javaNameParser);
__nameRoot.setNameParser(__javaNameParser);
StringRefAddr parserAddr = new StringRefAddr("parser", __javaNameParser.getClass().getName()); StringRefAddr parserAddr = new StringRefAddr("parser", __javaNameParser.getClass().getName());

View File

@ -12,11 +12,19 @@
// ======================================================================== // ========================================================================
package org.eclipse.jetty.jndi.java; package org.eclipse.jetty.jndi.java;
import java.util.Hashtable;
import javax.naming.Context; import javax.naming.Context;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.naming.Name; import javax.naming.Name;
import javax.naming.NameNotFoundException; import javax.naming.NameNotFoundException;
import javax.naming.NameParser; import javax.naming.NameParser;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import org.eclipse.jetty.jndi.NamingUtil; import org.eclipse.jetty.jndi.NamingUtil;
import org.junit.After; import org.junit.After;
@ -31,13 +39,152 @@ import static org.junit.Assert.fail;
*/ */
public class TestLocalJNDI public class TestLocalJNDI
{ {
public static class FruitFactory implements ObjectFactory
{
public FruitFactory()
{
}
public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception
{
if (!env.containsKey("flavour"))
throw new Exception ("No flavour!");
if (obj instanceof Reference)
{
Reference ref = (Reference)obj;
if (ref.getClassName().equals(Fruit.class.getName()))
{
RefAddr addr = ref.get("fruit");
if (addr != null)
{
return new Fruit((String)addr.getContent());
}
}
}
return null;
}
}
public static class Fruit implements Referenceable
{
String fruit;
public Fruit(String f)
{
fruit = f;
}
public Reference getReference() throws NamingException
{
return new Reference(
Fruit.class.getName(),
new StringRefAddr("fruit", fruit),
FruitFactory.class.getName(),
null); // Factory location
}
public String toString()
{
return fruit;
}
}
@After @After
public void tearDown() throws Exception public void tearDown() throws Exception
{ {
InitialContext ic = new InitialContext(); InitialContext ic = new InitialContext();
ic.destroySubcontext("a"); ic.destroySubcontext("a");
} }
@Test
public void testLocalReferenceable() throws Exception
{
Hashtable<String,String> env1 = new Hashtable<String,String>();
env1.put("flavour", "orange");
InitialContext ic1 = new InitialContext(env1);
ic1.bind("valencia", new Fruit("orange"));
Object o = ic1.lookup("valencia");
Hashtable<String,String> env2 = new Hashtable<String,String>();
InitialContext ic2 = new InitialContext(env2);
try
{
o = ic2.lookup("valencia");
fail("Constructed object from reference without correct environment");
}
catch (Exception e)
{
assertEquals("No flavour!", e.getMessage());
}
}
@Test
public void testLocalEnvironment() throws Exception
{
Hashtable<String,String> env1 = new Hashtable<String,String>();
env1.put("make", "holden");
env1.put("model", "commodore");
Object car1 = new Object();
InitialContext ic = new InitialContext(env1);
ic.bind("car1", car1);
assertNotNull(ic.lookup("car1"));
assertEquals(car1, ic.lookup("car1"));
Context carz = ic.createSubcontext("carz");
assertNotNull(carz);
Hashtable ht = carz.getEnvironment();
assertNotNull(ht);
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
Hashtable<String,String> env2 = new Hashtable<String,String>();
env2.put("flavour", "strawberry");
InitialContext ic2 = new InitialContext(env2);
assertEquals(car1, ic2.lookup("car1"));
Context c = (Context)ic2.lookup("carz");
assertNotNull(c);
ht = c.getEnvironment();
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
Context icecreamz = ic2.createSubcontext("icecreamz");
ht = icecreamz.getEnvironment();
assertNotNull(ht);
assertEquals("strawberry", ht.get("flavour"));
Context hatchbackz = ic2.createSubcontext("carz/hatchbackz");
assertNotNull(hatchbackz);
ht = hatchbackz.getEnvironment();
assertNotNull(ht);
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
assertEquals(null, ht.get("flavour"));
c = (Context)ic.lookup("carz/hatchbackz");
assertNotNull(c);
assertEquals(hatchbackz, c);
}
@Test @Test
public void testLocal () throws Exception public void testLocal () throws Exception
{ {

View File

@ -5,9 +5,11 @@ import java.util.IllegalFormatCodePointException;
public abstract class Utf8Appendable public abstract class Utf8Appendable
{ {
private final char REPLACEMENT = '\ufffd';
protected final Appendable _appendable; protected final Appendable _appendable;
protected int _more; protected int _expectedContinuationBytes;
protected int _bits; protected int _codePoint;
protected int _minCodePoint;
public Utf8Appendable(Appendable appendable) public Utf8Appendable(Appendable appendable)
{ {
@ -63,91 +65,112 @@ public abstract class Utf8Appendable
protected void appendByte(byte b) throws IOException protected void appendByte(byte b) throws IOException
{ {
// Check for invalid bytes
if (b==(byte)0xc0 || b==(byte)0xc1 || (int)b>=0xf5)
{
_appendable.append(REPLACEMENT);
_expectedContinuationBytes=0;
_codePoint=0;
throw new NotUtf8Exception();
}
// Is it plain ASCII?
if (b>=0) if (b>=0)
{ {
if (_more>0) // Were we expecting a continuation byte?
if (_expectedContinuationBytes>0)
{ {
_appendable.append('?'); _appendable.append(REPLACEMENT);
_more=0; _expectedContinuationBytes=0;
_bits=0; _codePoint=0;
throw new NotUtf8Exception(); throw new NotUtf8Exception();
} }
else else
_appendable.append((char)(0x7f&b)); _appendable.append((char)(0x7f&b));
} }
else if (_more==0) // Else is this a start byte
else if (_expectedContinuationBytes==0)
{ {
if ((b&0xc0)!=0xc0) if ((b & 0xe0) == 0xc0)
{ {
// 10xxxxxx //110xxxxx
_appendable.append('?'); _expectedContinuationBytes=1;
_more=0; _codePoint=b&0x1f;
_bits=0; _minCodePoint=0x80;
throw new NotUtf8Exception(); }
else if ((b & 0xf0) == 0xe0)
{
//1110xxxx
_expectedContinuationBytes=2;
_codePoint=b&0x0f;
_minCodePoint=0x800;
}
else if ((b & 0xf8) == 0xf0)
{
//11110xxx
_expectedContinuationBytes=3;
_codePoint=b&0x07;
_minCodePoint=0x10000;
}
else if ((b & 0xfc) == 0xf8)
{
//111110xx
_expectedContinuationBytes=4;
_codePoint=b&0x03;
_minCodePoint=0x200000;
}
else if ((b & 0xfe) == 0xfc)
{
//1111110x
_expectedContinuationBytes=5;
_codePoint=b&0x01;
_minCodePoint=0x400000;
} }
else else
{ {
if ((b & 0xe0) == 0xc0) _appendable.append(REPLACEMENT);
{ _expectedContinuationBytes=0;
//110xxxxx _codePoint=0;
_more=1; throw new NotUtf8Exception();
_bits=b&0x1f;
}
else if ((b & 0xf0) == 0xe0)
{
//1110xxxx
_more=2;
_bits=b&0x0f;
}
else if ((b & 0xf8) == 0xf0)
{
//11110xxx
_more=3;
_bits=b&0x07;
}
else if ((b & 0xfc) == 0xf8)
{
//111110xx
_more=4;
_bits=b&0x03;
}
else if ((b & 0xfe) == 0xfc)
{
//1111110x
_more=5;
_bits=b&0x01;
}
else
{
throw new NotUtf8Exception();
}
} }
} }
// else is this a continuation character
else if ((b&0xc0)==0x80)
{
// 10xxxxxx
_codePoint=(_codePoint<<6)|(b&0x3f);
// was that the last continuation?
if (--_expectedContinuationBytes==0)
{
// If this a valid unicode point?
if (_codePoint<_minCodePoint || (_codePoint>=0xD800 && _codePoint<=0xDFFF))
{
_appendable.append(REPLACEMENT);
_expectedContinuationBytes=0;
_codePoint=0;
throw new NotUtf8Exception();
}
_minCodePoint=0;
char[] chars = Character.toChars(_codePoint);
for (char c : chars)
_appendable.append(c);
}
}
// Else this is not a continuation character
else else
{ {
if ((b&0xc0)==0xc0) // ! 10xxxxxx
{ // 11?????? _appendable.append(REPLACEMENT);
_appendable.append('?'); _expectedContinuationBytes=0;
_more=0; _codePoint=0;
_bits=0; throw new NotUtf8Exception();
throw new NotUtf8Exception();
}
else
{
// 10xxxxxx
_bits=(_bits<<6)|(b&0x3f);
if (--_more==0)
{
if (_bits>=0xD800 && _bits<=0xDFFF)
throw new NotUtf8Exception();
_appendable.append(new String(Character.toChars(_bits)));
}
}
} }
} }
public static class NotUtf8Exception extends IllegalStateException public static class NotUtf8Exception extends IllegalArgumentException
{ {
public NotUtf8Exception() public NotUtf8Exception()
{ {

View File

@ -53,13 +53,13 @@ public class Utf8StringBuffer extends Utf8Appendable
public void reset() public void reset()
{ {
_buffer.setLength(0); _buffer.setLength(0);
_more=0; _expectedContinuationBytes=0;
_bits=0; _codePoint=0;
} }
public StringBuffer getStringBuffer() public StringBuffer getStringBuffer()
{ {
if (_more!=0) if (_expectedContinuationBytes!=0)
throw new NotUtf8Exception(); throw new NotUtf8Exception();
return _buffer; return _buffer;
} }
@ -67,7 +67,7 @@ public class Utf8StringBuffer extends Utf8Appendable
@Override @Override
public String toString() public String toString()
{ {
if (_more!=0) if (_expectedContinuationBytes!=0)
throw new NotUtf8Exception(); throw new NotUtf8Exception();
return _buffer.toString(); return _buffer.toString();
} }

View File

@ -52,13 +52,13 @@ public class Utf8StringBuilder extends Utf8Appendable
public void reset() public void reset()
{ {
_buffer.setLength(0); _buffer.setLength(0);
_more=0; _expectedContinuationBytes=0;
_bits=0; _codePoint=0;
} }
public StringBuilder getStringBuilder() public StringBuilder getStringBuilder()
{ {
if (_more!=0) if (_expectedContinuationBytes!=0)
throw new NotUtf8Exception(); throw new NotUtf8Exception();
return _buffer; return _buffer;
} }
@ -66,7 +66,7 @@ public class Utf8StringBuilder extends Utf8Appendable
@Override @Override
public String toString() public String toString()
{ {
if (_more!=0) if (_expectedContinuationBytes!=0)
throw new NotUtf8Exception(); throw new NotUtf8Exception();
return _buffer.toString(); return _buffer.toString();
} }

View File

@ -7,6 +7,8 @@ import java.util.List;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.Scanner.Notification; import org.eclipse.jetty.util.Scanner.Notification;
import org.junit.AfterClass; import org.junit.AfterClass;
@ -25,10 +27,8 @@ public class ScannerTest
@BeforeClass @BeforeClass
public static void setUpBeforeClass() throws Exception public static void setUpBeforeClass() throws Exception
{ {
_directory = File.createTempFile("scan",""); _directory = MavenTestingUtils.getTargetTestingDir(ScannerTest.class.getSimpleName());
_directory.delete(); FS.ensureEmpty(_directory);
_directory.mkdir();
_directory.deleteOnExit();
_scanner = new Scanner(); _scanner = new Scanner();
_scanner.addScanDir(_directory); _scanner.addScanDir(_directory);
@ -88,7 +88,7 @@ public class ScannerTest
public void testAddedChangeRemove() throws Exception public void testAddedChangeRemove() throws Exception
{ {
// TODO needs to be further investigated // TODO needs to be further investigated
Assume.assumeTrue(!OS.IS_WINDOWS && !OS.IS_OSX); Assume.assumeTrue(!OS.IS_WINDOWS);
touch("a0"); touch("a0");
@ -96,7 +96,7 @@ public class ScannerTest
_scanner.scan(); _scanner.scan();
_scanner.scan(); _scanner.scan();
Event event = _queue.poll(); Event event = _queue.poll();
Assert.assertTrue(event!=null); Assert.assertNotNull("Event should not be null", event);
Assert.assertEquals(_directory+"/a0",event._filename); Assert.assertEquals(_directory+"/a0",event._filename);
Assert.assertEquals(Notification.ADDED,event._notification); Assert.assertEquals(Notification.ADDED,event._notification);
@ -197,7 +197,7 @@ public class ScannerTest
public void testSizeChange() throws Exception public void testSizeChange() throws Exception
{ {
// TODO needs to be further investigated // TODO needs to be further investigated
Assume.assumeTrue(!OS.IS_WINDOWS && !OS.IS_OSX); Assume.assumeTrue(!OS.IS_WINDOWS);
touch("tsc0"); touch("tsc0");
_scanner.scan(); _scanner.scan();

View File

@ -48,9 +48,9 @@ public class Utf8StringBufferTest
buffer.toString(); buffer.toString();
assertTrue(false); assertTrue(false);
} }
catch(IllegalStateException e) catch(Utf8Appendable.NotUtf8Exception e)
{ {
assertTrue(e.toString().indexOf("!UTF-8")>=0); assertTrue(true);
} }
} }
@ -70,11 +70,11 @@ public class Utf8StringBufferTest
buffer.append(bytes[i]); buffer.append(bytes[i]);
assertTrue(false); assertTrue(false);
} }
catch(IllegalStateException e) catch(Utf8Appendable.NotUtf8Exception e)
{ {
assertTrue(e.toString().indexOf("!UTF-8")>=0); assertTrue(e.toString().indexOf("!UTF-8")>=0);
} }
assertEquals("abc?",buffer.toString()); assertEquals("abc\ufffd",buffer.toString());
} }
@Test @Test

View File

@ -25,19 +25,44 @@ public class Utf8StringBuilderTest
public void testInvalid() public void testInvalid()
throws Exception throws Exception
{ {
Utf8StringBuilder buffer = new Utf8StringBuilder(); String[] invalids = {
buffer.append((byte)0xED); "c0af",
buffer.append((byte)0xA0); "EDA080",
try "f08080af",
{ "f8808080af",
buffer.append((byte)0x80); "e080af",
assertTrue(false); "F4908080",
} "fbbfbfbfbf"
catch(Utf8Appendable.NotUtf8Exception e) };
{
assertTrue(true);
}
for (String i : invalids)
{
byte[] bytes = TypeUtil.fromHexString(i);
/* Test what JVM does
try
{
String s = new String(bytes,0,bytes.length,"UTF-8");
System.err.println(i+": "+s);
}
catch(Exception e)
{
System.err.println(i+": "+e);
}
*/
try
{
Utf8StringBuilder buffer = new Utf8StringBuilder();
buffer.append(bytes,0,bytes.length);
assertEquals(i,"not expected",buffer.toString());
}
catch(IllegalArgumentException e)
{
assertTrue(i,true);
}
}
} }
@Test @Test
@ -69,7 +94,7 @@ public class Utf8StringBuilderTest
buffer.toString(); buffer.toString();
assertTrue(false); assertTrue(false);
} }
catch(IllegalStateException e) catch(Utf8Appendable.NotUtf8Exception e)
{ {
assertTrue(e.toString().indexOf("!UTF-8")>=0); assertTrue(e.toString().indexOf("!UTF-8")>=0);
} }
@ -91,11 +116,11 @@ public class Utf8StringBuilderTest
buffer.append(bytes[i]); buffer.append(bytes[i]);
assertTrue(false); assertTrue(false);
} }
catch(IllegalStateException e) catch(Utf8Appendable.NotUtf8Exception e)
{ {
assertTrue(e.toString().indexOf("!UTF-8")>=0); assertTrue(true);
} }
assertEquals("abc?", buffer.toString()); assertEquals("abc\ufffd", buffer.toString());
} }
@ -106,6 +131,7 @@ public class Utf8StringBuilderTest
String source="\uD842\uDF9F"; String source="\uD842\uDF9F";
byte[] bytes=source.getBytes("UTF-8"); byte[] bytes=source.getBytes("UTF-8");
// System.err.println(TypeUtil.toHexString(bytes));
String jvmcheck = new String(bytes,0,bytes.length,"UTF-8"); String jvmcheck = new String(bytes,0,bytes.length,"UTF-8");
assertEquals(source,jvmcheck); assertEquals(source,jvmcheck);

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.B64Code; import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.Utf8Appendable; import org.eclipse.jetty.util.Utf8Appendable;
import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -627,7 +628,7 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
public void onFrame(final byte flags, final byte opcode, final Buffer buffer) public void onFrame(final byte flags, final byte opcode, final Buffer buffer)
{ {
boolean lastFrame = isLastFrame(flags); boolean lastFrame = isLastFrame(flags);
synchronized(WebSocketConnectionD13.this) synchronized(WebSocketConnectionD13.this)
{ {
// Ignore incoming after a close // Ignore incoming after a close
@ -827,19 +828,21 @@ public class WebSocketConnectionD13 extends AbstractConnection implements WebSoc
return; return;
} }
} }
catch(ThreadDeath th)
{
throw th;
}
catch(Utf8Appendable.NotUtf8Exception notUtf8) catch(Utf8Appendable.NotUtf8Exception notUtf8)
{ {
LOG.warn("{} for {}",notUtf8,_endp); LOG.warn("{} for {}",notUtf8,_endp);
LOG.debug(notUtf8); LOG.debug(notUtf8);
errorClose(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,"Invalid UTF-8"); errorClose(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,"Invalid UTF-8");
} }
catch(ThreadDeath th) catch(Throwable probablyNotUtf8)
{ {
throw th; LOG.warn("{} for {}",probablyNotUtf8,_endp);
} LOG.debug(probablyNotUtf8);
catch(Throwable th) errorClose(WebSocketConnectionD13.CLOSE_BAD_PAYLOAD,"Invalid Payload: "+probablyNotUtf8);
{
LOG.warn(th);
} }
} }

View File

@ -52,6 +52,8 @@ public class TestClient implements WebSocket.OnFrame
public void onOpen(Connection connection) public void onOpen(Connection connection)
{ {
if (_verbose)
System.err.printf("%s#onHandshake %s %s\n",this.getClass().getSimpleName(),connection,connection.getClass().getSimpleName());
} }
public void onClose(int closeCode, String message) public void onClose(int closeCode, String message)
@ -141,7 +143,7 @@ public class TestClient implements WebSocket.OnFrame
byte op=(byte)(off==0?opcode:WebSocketConnectionD13.OP_CONTINUATION); byte op=(byte)(off==0?opcode:WebSocketConnectionD13.OP_CONTINUATION);
if (_verbose) if (_verbose)
System.err.printf("%s#addFrame %s|%s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(flags),TypeUtil.toHexString(op),TypeUtil.toHexString(data,off,len)); System.err.printf("%s#sendFrame %s|%s %s\n",this.getClass().getSimpleName(),TypeUtil.toHexString(flags),TypeUtil.toHexString(op),TypeUtil.toHexString(data,off,len));
_connection.sendFrame(flags,op,data,off,len); _connection.sendFrame(flags,op,data,off,len);
@ -168,6 +170,7 @@ public class TestClient implements WebSocket.OnFrame
System.err.println(" -p|--port PORT (default 8080)"); System.err.println(" -p|--port PORT (default 8080)");
System.err.println(" -b|--binary"); System.err.println(" -b|--binary");
System.err.println(" -v|--verbose"); System.err.println(" -v|--verbose");
System.err.println(" -q|--quiet");
System.err.println(" -c|--count n (default 10)"); System.err.println(" -c|--count n (default 10)");
System.err.println(" -s|--size n (default 64)"); System.err.println(" -s|--size n (default 64)");
System.err.println(" -f|--fragment n (default 4000) "); System.err.println(" -f|--fragment n (default 4000) ");
@ -226,6 +229,8 @@ public class TestClient implements WebSocket.OnFrame
try try
{ {
__start=System.currentTimeMillis(); __start=System.currentTimeMillis();
protocol=protocol==null?"echo":protocol;
for (int i=0;i<clients;i++) for (int i=0;i<clients;i++)
{ {
client[i]=new TestClient(host,port,protocol==null?null:protocol,60000); client[i]=new TestClient(host,port,protocol==null?null:protocol,60000);
@ -233,7 +238,7 @@ public class TestClient implements WebSocket.OnFrame
} }
System.out.println("Jetty WebSocket PING "+host+":"+port+ System.out.println("Jetty WebSocket PING "+host+":"+port+
" ("+ new InetSocketAddress(host,port)+") "+clients+" clients"); " ("+ new InetSocketAddress(host,port)+") "+clients+" clients "+protocol);
for (int p=0;p<count;p++) for (int p=0;p<count;p++)
@ -272,9 +277,11 @@ public class TestClient implements WebSocket.OnFrame
long duration=System.currentTimeMillis()-__start; long duration=System.currentTimeMillis()-__start;
System.out.println("--- "+host+" websocket ping statistics using "+clients+" connection"+(clients>1?"s":"")+" ---"); System.out.println("--- "+host+" websocket ping statistics using "+clients+" connection"+(clients>1?"s":"")+" ---");
System.out.println(__framesSent+" frames transmitted, "+__framesReceived+" received, "+ System.out.printf("%d/%d frames sent/recv, %d/%d mesg sent/recv, time %dms %dm/s %.2fbps%n",
__messagesSent+" messages transmitted, "+__messagesReceived+" received, "+ __framesSent,__framesReceived.get(),
"time "+duration+"ms "+ (1000L*__messagesReceived.get()/duration)+" req/s"); __messagesSent,__messagesReceived.get(),
duration,(1000L*__messagesReceived.get()/duration),
1000.0D*__messagesReceived.get()*8*size/duration/1024/1024);
System.out.printf("rtt min/ave/max = %.3f/%.3f/%.3f ms\n",__minDuration.get()/1000000.0,__messagesReceived.get()==0?0.0:(__totalTime.get()/__messagesReceived.get()/1000000.0),__maxDuration.get()/1000000.0); System.out.printf("rtt min/ave/max = %.3f/%.3f/%.3f ms\n",__minDuration.get()/1000000.0,__messagesReceived.get()==0?0.0:(__totalTime.get()/__messagesReceived.get()/1000000.0),__maxDuration.get()/1000000.0);
__clientFactory.stop(); __clientFactory.stop();

View File

@ -107,7 +107,7 @@ public class TestServer extends Server
public void onOpen(Connection connection) public void onOpen(Connection connection)
{ {
if (_verbose) if (_verbose)
System.err.printf("%s#onOpen %s\n",this.getClass().getSimpleName(),connection); System.err.printf("%s#onOpen %s %s\n",this.getClass().getSimpleName(),connection,connection.getProtocol());
} }
public void onHandshake(FrameConnection connection) public void onHandshake(FrameConnection connection)

View File

@ -3,7 +3,7 @@
<parent> <parent>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-parent</artifactId> <artifactId>jetty-parent</artifactId>
<version>18</version> <version>19-SNAPSHOT</version>
</parent> </parent>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId> <artifactId>jetty-project</artifactId>

View File

@ -73,7 +73,7 @@ public class TestFilter implements Filter
String to = request.getServerName(); String to = request.getServerName();
String path=((HttpServletRequest)request).getServletPath(); String path=((HttpServletRequest)request).getServletPath();
if (!_remote && !_allowed.contains(path) && ( if (!"/remote.html".equals(path) && !_remote && !_allowed.contains(path) && (
!from.equals("localhost") && !from.startsWith("127.") && from.indexOf(":1")<0 || !from.equals("localhost") && !from.startsWith("127.") && from.indexOf(":1")<0 ||
!to.equals("localhost")&&!to.startsWith("127.0.0.") && to.indexOf(":1")<0)) !to.equals("localhost")&&!to.startsWith("127.0.0.") && to.indexOf(":1")<0))
{ {