Merge remote-tracking branch 'origin/jetty-9.4.x'
This commit is contained in:
commit
4d7a629e1b
|
@ -28,9 +28,12 @@ import javax.servlet.ServletContext;
|
||||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||||
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
|
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
|
||||||
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
|
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
|
||||||
|
import org.eclipse.jetty.servlet.ServletMapping;
|
||||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
import org.eclipse.jetty.util.resource.ResourceCollection;
|
import org.eclipse.jetty.util.resource.ResourceCollection;
|
||||||
|
import org.eclipse.jetty.webapp.DefaultsDescriptor;
|
||||||
import org.eclipse.jetty.webapp.Descriptor;
|
import org.eclipse.jetty.webapp.Descriptor;
|
||||||
import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
|
import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
|
||||||
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||||
|
@ -44,11 +47,18 @@ import org.eclipse.jetty.xml.XmlParser;
|
||||||
*/
|
*/
|
||||||
public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private String _originAttributeName = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
public QuickStartDescriptorProcessor()
|
public QuickStartDescriptorProcessor()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
registerVisitor("context-param", this.getClass().getMethod("visitContextParam", __signature));
|
registerVisitor("context-param", this.getClass().getMethod("visitContextParam", __signature));
|
||||||
|
registerVisitor("servlet-mapping", this.getClass().getMethod("visitServletMapping", __signature));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@ -62,6 +72,7 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
@Override
|
@Override
|
||||||
public void start(WebAppContext context, Descriptor descriptor)
|
public void start(WebAppContext context, Descriptor descriptor)
|
||||||
{
|
{
|
||||||
|
_originAttributeName = context.getInitParameter(QuickStartGeneratorConfiguration.ORIGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,8 +81,50 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
@Override
|
@Override
|
||||||
public void end(WebAppContext context, Descriptor descriptor)
|
public void end(WebAppContext context, Descriptor descriptor)
|
||||||
{
|
{
|
||||||
|
_originAttributeName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a servlet-mapping element
|
||||||
|
*
|
||||||
|
* @param context the webapp
|
||||||
|
* @param descriptor the xml file to process
|
||||||
|
* @param node the servlet-mapping element in the xml file to process
|
||||||
|
*/
|
||||||
|
public void visitServletMapping(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
|
||||||
|
{
|
||||||
|
String servletName = node.getString("servlet-name", false, true);
|
||||||
|
ServletMapping mapping = null;
|
||||||
|
ServletMapping[] mappings = context.getServletHandler().getServletMappings();
|
||||||
|
|
||||||
|
if (mappings != null)
|
||||||
|
{
|
||||||
|
for (ServletMapping m:mappings)
|
||||||
|
{
|
||||||
|
if (servletName.equals(m.getServletName()))
|
||||||
|
{
|
||||||
|
mapping = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapping != null && _originAttributeName != null)
|
||||||
|
{
|
||||||
|
String origin = node.getAttribute(_originAttributeName);
|
||||||
|
if (!StringUtil.isBlank(origin) && origin.startsWith(DefaultsDescriptor.class.getSimpleName()))
|
||||||
|
mapping.setDefault(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process a context-param element
|
||||||
|
* @param context the webapp
|
||||||
|
* @param descriptor the xml file to process
|
||||||
|
* @param node the context-param node in the xml file
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
|
public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
|
@ -82,11 +135,16 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
// extract values
|
// extract values
|
||||||
switch(name)
|
switch(name)
|
||||||
{
|
{
|
||||||
|
case QuickStartGeneratorConfiguration.ORIGIN:
|
||||||
|
{
|
||||||
|
//value already contains what we need
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServletContext.ORDERED_LIBS:
|
case ServletContext.ORDERED_LIBS:
|
||||||
case AnnotationConfiguration.CONTAINER_INITIALIZERS:
|
case AnnotationConfiguration.CONTAINER_INITIALIZERS:
|
||||||
case MetaInfConfiguration.METAINF_TLDS:
|
case MetaInfConfiguration.METAINF_TLDS:
|
||||||
case MetaInfConfiguration.METAINF_RESOURCES:
|
case MetaInfConfiguration.METAINF_RESOURCES:
|
||||||
|
{
|
||||||
context.removeAttribute(name);
|
context.removeAttribute(name);
|
||||||
|
|
||||||
QuotedStringTokenizer tok = new QuotedStringTokenizer(value,",");
|
QuotedStringTokenizer tok = new QuotedStringTokenizer(value,",");
|
||||||
|
@ -94,7 +152,7 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
values.add(tok.nextToken().trim());
|
values.add(tok.nextToken().trim());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
values.add(value);
|
values.add(value);
|
||||||
}
|
}
|
||||||
|
@ -103,6 +161,11 @@ public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
|
||||||
// handle values
|
// handle values
|
||||||
switch(name)
|
switch(name)
|
||||||
{
|
{
|
||||||
|
case QuickStartGeneratorConfiguration.ORIGIN:
|
||||||
|
{
|
||||||
|
context.setAttribute(QuickStartGeneratorConfiguration.ORIGIN, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ServletContext.ORDERED_LIBS:
|
case ServletContext.ORDERED_LIBS:
|
||||||
{
|
{
|
||||||
List<Object> libs = new ArrayList<>();
|
List<Object> libs = new ArrayList<>();
|
||||||
|
|
|
@ -76,7 +76,7 @@ import org.eclipse.jetty.xml.XmlAppendable;
|
||||||
public class QuickStartGeneratorConfiguration extends AbstractConfiguration implements Configuration.DisabledByDefault
|
public class QuickStartGeneratorConfiguration extends AbstractConfiguration implements Configuration.DisabledByDefault
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(QuickStartGeneratorConfiguration.class);
|
private static final Logger LOG = Log.getLogger(QuickStartGeneratorConfiguration.class);
|
||||||
|
public static final String ORIGIN = "org.eclipse.jetty.originAttribute";
|
||||||
public static final String DEFAULT_ORIGIN_ATTRIBUTE_NAME = "origin";
|
public static final String DEFAULT_ORIGIN_ATTRIBUTE_NAME = "origin";
|
||||||
protected String _originAttribute;
|
protected String _originAttribute;
|
||||||
protected boolean _generateOrigin;
|
protected boolean _generateOrigin;
|
||||||
|
@ -183,6 +183,16 @@ public class QuickStartGeneratorConfiguration extends AbstractConfiguration impl
|
||||||
addContextParamFromAttribute(context,out,MetaInfConfiguration.METAINF_RESOURCES,normalizer);
|
addContextParamFromAttribute(context,out,MetaInfConfiguration.METAINF_RESOURCES,normalizer);
|
||||||
|
|
||||||
|
|
||||||
|
//add the name of the origin attribute, if it is being used
|
||||||
|
if (_generateOrigin)
|
||||||
|
{
|
||||||
|
out.openTag("context-param")
|
||||||
|
.tag("param-name", ORIGIN)
|
||||||
|
.tag("param-value", _originAttribute)
|
||||||
|
.closeTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// init params
|
// init params
|
||||||
for (String p : context.getInitParams().keySet())
|
for (String p : context.getInitParams().keySet())
|
||||||
out.openTag("context-param",origin(md,"context-param." + p))
|
out.openTag("context-param",origin(md,"context-param." + p))
|
||||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.start.Props.Prop;
|
||||||
import org.eclipse.jetty.start.builders.StartDirBuilder;
|
import org.eclipse.jetty.start.builders.StartDirBuilder;
|
||||||
import org.eclipse.jetty.start.builders.StartIniBuilder;
|
import org.eclipse.jetty.start.builders.StartIniBuilder;
|
||||||
import org.eclipse.jetty.start.fileinits.BaseHomeFileInitializer;
|
import org.eclipse.jetty.start.fileinits.BaseHomeFileInitializer;
|
||||||
|
@ -54,7 +55,7 @@ public class BaseBuilder
|
||||||
* @return The ini file if module was added, null if module was not added.
|
* @return The ini file if module was added, null if module was not added.
|
||||||
* @throws IOException if unable to add the module
|
* @throws IOException if unable to add the module
|
||||||
*/
|
*/
|
||||||
public String addModule(Module module) throws IOException;
|
public String addModule(Module module, Props props) throws IOException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
|
private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
|
||||||
|
@ -209,7 +210,7 @@ public class BaseBuilder
|
||||||
// if (explictly added and ini file modified)
|
// if (explictly added and ini file modified)
|
||||||
if (startArgs.getStartModules().contains(module.getName()))
|
if (startArgs.getStartModules().contains(module.getName()))
|
||||||
{
|
{
|
||||||
ini=builder.get().addModule(module);
|
ini=builder.get().addModule(module, startArgs.getProperties());
|
||||||
if (ini!=null)
|
if (ini!=null)
|
||||||
modified.set(true);
|
modified.set(true);
|
||||||
}
|
}
|
||||||
|
@ -240,7 +241,6 @@ public class BaseBuilder
|
||||||
StartLog.info("%-15s initialized in %s",
|
StartLog.info("%-15s initialized in %s",
|
||||||
module.getName(),
|
module.getName(),
|
||||||
ini);
|
ini);
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.start;
|
package org.eclipse.jetty.start;
|
||||||
|
|
||||||
import static org.eclipse.jetty.start.UsageException.ERR_BAD_GRAPH;
|
|
||||||
import static org.eclipse.jetty.start.UsageException.ERR_INVOKE_MAIN;
|
import static org.eclipse.jetty.start.UsageException.ERR_INVOKE_MAIN;
|
||||||
import static org.eclipse.jetty.start.UsageException.ERR_NOT_STOPPED;
|
import static org.eclipse.jetty.start.UsageException.ERR_NOT_STOPPED;
|
||||||
import static org.eclipse.jetty.start.UsageException.ERR_UNKNOWN;
|
import static org.eclipse.jetty.start.UsageException.ERR_UNKNOWN;
|
||||||
|
@ -205,7 +204,7 @@ public class Main
|
||||||
|
|
||||||
StartLog.debug("%s - %s",invoked_class,invoked_class.getPackage().getImplementationVersion());
|
StartLog.debug("%s - %s",invoked_class,invoked_class.getPackage().getImplementationVersion());
|
||||||
|
|
||||||
CommandLineBuilder cmd = args.getMainArgs(baseHome,false);
|
CommandLineBuilder cmd = args.getMainArgs(false);
|
||||||
String argArray[] = cmd.getArgs().toArray(new String[0]);
|
String argArray[] = cmd.getArgs().toArray(new String[0]);
|
||||||
StartLog.debug("Command Line Args: %s",cmd.toString());
|
StartLog.debug("Command Line Args: %s",cmd.toString());
|
||||||
|
|
||||||
|
@ -223,7 +222,7 @@ public class Main
|
||||||
StartLog.endStartLog();
|
StartLog.endStartLog();
|
||||||
|
|
||||||
// Dump Jetty Home / Base
|
// Dump Jetty Home / Base
|
||||||
args.dumpEnvironment(baseHome);
|
args.dumpEnvironment();
|
||||||
|
|
||||||
// Dump JVM Args
|
// Dump JVM Args
|
||||||
args.dumpJvmArgs();
|
args.dumpJvmArgs();
|
||||||
|
@ -238,7 +237,7 @@ public class Main
|
||||||
dumpClasspathWithVersions(args.getClasspath());
|
dumpClasspathWithVersions(args.getClasspath());
|
||||||
|
|
||||||
// Dump Resolved XMLs
|
// Dump Resolved XMLs
|
||||||
args.dumpActiveXmls(baseHome);
|
args.dumpActiveXmls();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void listModules(StartArgs args)
|
public void listModules(StartArgs args)
|
||||||
|
@ -288,7 +287,7 @@ public class Main
|
||||||
// the various start inis
|
// the various start inis
|
||||||
// and then the raw command line arguments
|
// and then the raw command line arguments
|
||||||
StartLog.debug("Parsing collected arguments");
|
StartLog.debug("Parsing collected arguments");
|
||||||
StartArgs args = new StartArgs();
|
StartArgs args = new StartArgs(baseHome);
|
||||||
args.parse(baseHome.getConfigSources());
|
args.parse(baseHome.getConfigSources());
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
|
@ -330,17 +329,17 @@ public class Main
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 5) Lib & XML Expansion / Resolution
|
// 5) Lib & XML Expansion / Resolution
|
||||||
args.expandLibs(baseHome);
|
args.expandLibs();
|
||||||
args.expandModules(baseHome,activeModules);
|
args.expandModules(activeModules);
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 6) Resolve Extra XMLs
|
// 6) Resolve Extra XMLs
|
||||||
args.resolveExtraXmls(baseHome);
|
args.resolveExtraXmls();
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
// ------------------------------------------------------------
|
||||||
// 9) Resolve Property Files
|
// 9) Resolve Property Files
|
||||||
args.resolvePropertyFiles(baseHome);
|
args.resolvePropertyFiles();
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +390,7 @@ public class Main
|
||||||
// Show Command Line to execute Jetty
|
// Show Command Line to execute Jetty
|
||||||
if (args.isDryRun())
|
if (args.isDryRun())
|
||||||
{
|
{
|
||||||
CommandLineBuilder cmd = args.getMainArgs(baseHome,true);
|
CommandLineBuilder cmd = args.getMainArgs(true);
|
||||||
System.out.println(cmd.toString(StartLog.isDebugEnabled()?" \\\n":" "));
|
System.out.println(cmd.toString(StartLog.isDebugEnabled()?" \\\n":" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +418,7 @@ public class Main
|
||||||
// execute Jetty in another JVM
|
// execute Jetty in another JVM
|
||||||
if (args.isExec())
|
if (args.isExec())
|
||||||
{
|
{
|
||||||
CommandLineBuilder cmd = args.getMainArgs(baseHome,true);
|
CommandLineBuilder cmd = args.getMainArgs(true);
|
||||||
cmd.debug();
|
cmd.debug();
|
||||||
ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
|
ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
|
||||||
StartLog.endStartLog();
|
StartLog.endStartLog();
|
||||||
|
|
|
@ -36,6 +36,9 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.start.Props.Prop;
|
||||||
|
import org.eclipse.jetty.start.config.CommandLineConfigSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a Module metadata, as defined in Jetty.
|
* Represents a Module metadata, as defined in Jetty.
|
||||||
*
|
*
|
||||||
|
@ -59,6 +62,8 @@ public class Module implements Comparable<Module>
|
||||||
{
|
{
|
||||||
private static final String VERSION_UNSPECIFIED = "9.2";
|
private static final String VERSION_UNSPECIFIED = "9.2";
|
||||||
private static Pattern MOD_NAME = Pattern.compile("^(.*)\\.mod",Pattern.CASE_INSENSITIVE);
|
private static Pattern MOD_NAME = Pattern.compile("^(.*)\\.mod",Pattern.CASE_INSENSITIVE);
|
||||||
|
private static Pattern SET_PROPERTY = Pattern.compile("^(#?)\\s*([^=\\s]+)=(.*)$");
|
||||||
|
|
||||||
|
|
||||||
/** The file of the module */
|
/** The file of the module */
|
||||||
private final Path _path;
|
private final Path _path;
|
||||||
|
@ -506,7 +511,7 @@ public class Module implements Comparable<Module>
|
||||||
return isEnabled() && !_notTransitive;
|
return isEnabled() && !_notTransitive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeIniSection(BufferedWriter writer)
|
public void writeIniSection(BufferedWriter writer, Props props)
|
||||||
{
|
{
|
||||||
PrintWriter out = new PrintWriter(writer);
|
PrintWriter out = new PrintWriter(writer);
|
||||||
out.println("# --------------------------------------- ");
|
out.println("# --------------------------------------- ");
|
||||||
|
@ -517,7 +522,23 @@ public class Module implements Comparable<Module>
|
||||||
out.println("--module=" + getName());
|
out.println("--module=" + getName());
|
||||||
out.println();
|
out.println();
|
||||||
for (String line : getIniTemplate())
|
for (String line : getIniTemplate())
|
||||||
out.println(line);
|
{
|
||||||
|
Matcher m = SET_PROPERTY.matcher(line);
|
||||||
|
if (m.matches() && m.groupCount()==3)
|
||||||
|
{
|
||||||
|
String name = m.group(2);
|
||||||
|
Prop p = props.getProp(name);
|
||||||
|
if (p!=null && p.origin.startsWith(CommandLineConfigSource.ORIGIN_CMD_LINE))
|
||||||
|
{
|
||||||
|
StartLog.info("%-15s property set %s=%s",this._name,name,p.value);
|
||||||
|
out.printf("%s=%s%n",name,p.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out.println(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out.println(line);
|
||||||
|
}
|
||||||
out.println();
|
out.println();
|
||||||
out.flush();
|
out.flush();
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,6 +112,8 @@ public class StartArgs
|
||||||
|
|
||||||
private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration";
|
private static final String SERVER_MAIN = "org.eclipse.jetty.xml.XmlConfiguration";
|
||||||
|
|
||||||
|
private final BaseHome baseHome;
|
||||||
|
|
||||||
/** List of enabled modules */
|
/** List of enabled modules */
|
||||||
private List<String> modules = new ArrayList<>();
|
private List<String> modules = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -182,8 +184,9 @@ public class StartArgs
|
||||||
private boolean approveAllLicenses = false;
|
private boolean approveAllLicenses = false;
|
||||||
|
|
||||||
|
|
||||||
public StartArgs()
|
public StartArgs(BaseHome baseHome)
|
||||||
{
|
{
|
||||||
|
this.baseHome = baseHome;
|
||||||
classpath = new Classpath();
|
classpath = new Classpath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +237,7 @@ public class StartArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpActiveXmls(BaseHome baseHome)
|
public void dumpActiveXmls()
|
||||||
{
|
{
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("Jetty Active XMLs:");
|
System.out.println("Jetty Active XMLs:");
|
||||||
|
@ -251,7 +254,7 @@ public class StartArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpEnvironment(BaseHome baseHome)
|
public void dumpEnvironment()
|
||||||
{
|
{
|
||||||
// Java Details
|
// Java Details
|
||||||
System.out.println();
|
System.out.println();
|
||||||
|
@ -442,7 +445,7 @@ public class StartArgs
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if unable to expand the libraries
|
* if unable to expand the libraries
|
||||||
*/
|
*/
|
||||||
public void expandLibs(BaseHome baseHome) throws IOException
|
public void expandLibs() throws IOException
|
||||||
{
|
{
|
||||||
StartLog.debug("Expanding Libs");
|
StartLog.debug("Expanding Libs");
|
||||||
for (String rawlibref : rawLibs)
|
for (String rawlibref : rawLibs)
|
||||||
|
@ -464,14 +467,12 @@ public class StartArgs
|
||||||
/**
|
/**
|
||||||
* Build up the Classpath and XML file references based on enabled Module list.
|
* Build up the Classpath and XML file references based on enabled Module list.
|
||||||
*
|
*
|
||||||
* @param baseHome
|
|
||||||
* the base home in use
|
|
||||||
* @param activeModules
|
* @param activeModules
|
||||||
* the active (selected) modules
|
* the active (selected) modules
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* if unable to expand the modules
|
* if unable to expand the modules
|
||||||
*/
|
*/
|
||||||
public void expandModules(BaseHome baseHome, List<Module> activeModules) throws IOException
|
public void expandModules(List<Module> activeModules) throws IOException
|
||||||
{
|
{
|
||||||
StartLog.debug("Expanding Modules");
|
StartLog.debug("Expanding Modules");
|
||||||
for (Module module : activeModules)
|
for (Module module : activeModules)
|
||||||
|
@ -543,7 +544,7 @@ public class StartArgs
|
||||||
return jvmArgs;
|
return jvmArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommandLineBuilder getMainArgs(BaseHome baseHome, boolean addJavaInit) throws IOException
|
public CommandLineBuilder getMainArgs(boolean addJavaInit) throws IOException
|
||||||
{
|
{
|
||||||
CommandLineBuilder cmd = new CommandLineBuilder();
|
CommandLineBuilder cmd = new CommandLineBuilder();
|
||||||
|
|
||||||
|
@ -851,6 +852,28 @@ public class StartArgs
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg.startsWith("--commands="))
|
||||||
|
{
|
||||||
|
Path commands = baseHome.getPath(Props.getValue(arg));
|
||||||
|
|
||||||
|
if (!Files.exists(commands) || !Files.isReadable(commands))
|
||||||
|
throw new UsageException(ERR_BAD_ARG,"--commands file must be readable: %s",commands);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TextFile file = new TextFile(commands);
|
||||||
|
StartLog.info("reading commands from %s",baseHome.toShortForm(commands));
|
||||||
|
String s = source+"|"+baseHome.toShortForm(commands);
|
||||||
|
for (String line: file)
|
||||||
|
{
|
||||||
|
parse(line,s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (arg.startsWith("--include-jetty-dir="))
|
if (arg.startsWith("--include-jetty-dir="))
|
||||||
{
|
{
|
||||||
// valid, but handled in ConfigSources instead
|
// valid, but handled in ConfigSources instead
|
||||||
|
@ -1133,7 +1156,7 @@ public class StartArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolveExtraXmls(BaseHome baseHome) throws IOException
|
public void resolveExtraXmls() throws IOException
|
||||||
{
|
{
|
||||||
// Find and Expand XML files
|
// Find and Expand XML files
|
||||||
for (String xmlRef : xmlRefs)
|
for (String xmlRef : xmlRefs)
|
||||||
|
@ -1148,7 +1171,7 @@ public class StartArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resolvePropertyFiles(BaseHome baseHome) throws IOException
|
public void resolvePropertyFiles() throws IOException
|
||||||
{
|
{
|
||||||
// Find and Expand property files
|
// Find and Expand property files
|
||||||
for (String propertyFileRef : propertyFileRefs)
|
for (String propertyFileRef : propertyFileRefs)
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.eclipse.jetty.start.BaseBuilder;
|
||||||
import org.eclipse.jetty.start.BaseHome;
|
import org.eclipse.jetty.start.BaseHome;
|
||||||
import org.eclipse.jetty.start.FS;
|
import org.eclipse.jetty.start.FS;
|
||||||
import org.eclipse.jetty.start.Module;
|
import org.eclipse.jetty.start.Module;
|
||||||
|
import org.eclipse.jetty.start.Props;
|
||||||
import org.eclipse.jetty.start.StartLog;
|
import org.eclipse.jetty.start.StartLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +52,7 @@ public class StartDirBuilder implements BaseBuilder.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String addModule(Module module) throws IOException
|
public String addModule(Module module, Props props) throws IOException
|
||||||
{
|
{
|
||||||
if (module.isDynamic())
|
if (module.isDynamic())
|
||||||
{
|
{
|
||||||
|
@ -69,7 +70,7 @@ public class StartDirBuilder implements BaseBuilder.Config
|
||||||
Path ini = startDir.resolve(module.getName() + ".ini");
|
Path ini = startDir.resolve(module.getName() + ".ini");
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING))
|
try (BufferedWriter writer = Files.newBufferedWriter(ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING))
|
||||||
{
|
{
|
||||||
module.writeIniSection(writer);
|
module.writeIniSection(writer,props);
|
||||||
}
|
}
|
||||||
return baseHome.toShortForm(ini);
|
return baseHome.toShortForm(ini);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,7 @@ public class StartIniBuilder implements BaseBuilder.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String addModule(Module module) throws IOException
|
public String addModule(Module module, Props props) throws IOException
|
||||||
{
|
{
|
||||||
if (modulesPresent.contains(module.getName()))
|
if (modulesPresent.contains(module.getName()))
|
||||||
{
|
{
|
||||||
|
@ -109,7 +109,7 @@ public class StartIniBuilder implements BaseBuilder.Config
|
||||||
// Append to start.ini
|
// Append to start.ini
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(startIni,StandardCharsets.UTF_8,StandardOpenOption.APPEND,StandardOpenOption.CREATE))
|
try (BufferedWriter writer = Files.newBufferedWriter(startIni,StandardCharsets.UTF_8,StandardOpenOption.APPEND,StandardOpenOption.CREATE))
|
||||||
{
|
{
|
||||||
module.writeIniSection(writer);
|
module.writeIniSection(writer, props);
|
||||||
}
|
}
|
||||||
return baseHome.toShortForm(startIni);
|
return baseHome.toShortForm(startIni);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,10 @@ Command Line Options:
|
||||||
generated properties file to be saved and reused.
|
generated properties file to be saved and reused.
|
||||||
Without this option, a temporary file is used.
|
Without this option, a temporary file is used.
|
||||||
|
|
||||||
|
--commands=<filename>
|
||||||
|
Use each line of the file as arguments on the command
|
||||||
|
line.
|
||||||
|
|
||||||
Debug and Start Logging:
|
Debug and Start Logging:
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
@ -92,6 +96,9 @@ Module Management:
|
||||||
exists then <modulename>.ini files are created within
|
exists then <modulename>.ini files are created within
|
||||||
that directory, otherwise then enabling configuration
|
that directory, otherwise then enabling configuration
|
||||||
is appended to the ${jetty.base}/start.ini file.
|
is appended to the ${jetty.base}/start.ini file.
|
||||||
|
If the ini template contains properties, these may be
|
||||||
|
amended in the generated file by specifying those
|
||||||
|
properties on the command line.
|
||||||
|
|
||||||
FS.ensureDirectoryExists(startDir);
|
FS.ensureDirectoryExists(startDir);
|
||||||
FS.ensureDirectoryExists(startDir);
|
FS.ensureDirectoryExists(startDir);
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class ModuleGraphWriterTest
|
||||||
// Initialize
|
// Initialize
|
||||||
BaseHome basehome = new BaseHome(config);
|
BaseHome basehome = new BaseHome(config);
|
||||||
|
|
||||||
StartArgs args = new StartArgs();
|
StartArgs args = new StartArgs(basehome);
|
||||||
args.parse(config);
|
args.parse(config);
|
||||||
|
|
||||||
Modules modules = new Modules(basehome, args);
|
Modules modules = new Modules(basehome, args);
|
||||||
|
|
|
@ -63,7 +63,7 @@ public class ModulesTest
|
||||||
// Initialize
|
// Initialize
|
||||||
BaseHome basehome = new BaseHome(config);
|
BaseHome basehome = new BaseHome(config);
|
||||||
|
|
||||||
StartArgs args = new StartArgs();
|
StartArgs args = new StartArgs(basehome);
|
||||||
args.parse(config);
|
args.parse(config);
|
||||||
|
|
||||||
// Test Modules
|
// Test Modules
|
||||||
|
@ -121,7 +121,7 @@ public class ModulesTest
|
||||||
// Initialize
|
// Initialize
|
||||||
BaseHome basehome = new BaseHome(config);
|
BaseHome basehome = new BaseHome(config);
|
||||||
|
|
||||||
StartArgs args = new StartArgs();
|
StartArgs args = new StartArgs(basehome);
|
||||||
args.parse(config);
|
args.parse(config);
|
||||||
|
|
||||||
// Test Modules
|
// Test Modules
|
||||||
|
@ -158,7 +158,7 @@ public class ModulesTest
|
||||||
// Initialize
|
// Initialize
|
||||||
BaseHome basehome = new BaseHome(config);
|
BaseHome basehome = new BaseHome(config);
|
||||||
|
|
||||||
StartArgs args = new StartArgs();
|
StartArgs args = new StartArgs(basehome);
|
||||||
args.parse(config);
|
args.parse(config);
|
||||||
|
|
||||||
// Test Modules
|
// Test Modules
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
## The XMLs we expect (order is important)
|
||||||
|
XML|${jetty.home}/etc/base.xml
|
||||||
|
XML|${jetty.home}/etc/main.xml
|
||||||
|
|
||||||
|
# The LIBs we expect (order is irrelevant)
|
||||||
|
LIB|${jetty.home}/lib/base.jar
|
||||||
|
LIB|${jetty.home}/lib/main.jar
|
||||||
|
LIB|${jetty.home}/lib/other.jar
|
||||||
|
|
||||||
|
# The Properties we expect (order is irrelevant)
|
||||||
|
PROP|main.prop=value0
|
||||||
|
PROP|name=value
|
||||||
|
PROP|name0=changed0
|
||||||
|
PROP|name1=changed1
|
||||||
|
|
||||||
|
# Files / Directories to create
|
||||||
|
EXISTS|start.d/parameterized.ini
|
|
@ -0,0 +1,5 @@
|
||||||
|
other=value
|
||||||
|
name=changed
|
||||||
|
name0=changed0
|
||||||
|
name1=changed1
|
||||||
|
--add-to-start=parameterized
|
|
@ -0,0 +1,17 @@
|
||||||
|
## The XMLs we expect (order is important)
|
||||||
|
XML|${jetty.home}/etc/base.xml
|
||||||
|
XML|${jetty.home}/etc/main.xml
|
||||||
|
|
||||||
|
# The LIBs we expect (order is irrelevant)
|
||||||
|
LIB|${jetty.home}/lib/base.jar
|
||||||
|
LIB|${jetty.home}/lib/main.jar
|
||||||
|
LIB|${jetty.home}/lib/other.jar
|
||||||
|
|
||||||
|
# The Properties we expect (order is irrelevant)
|
||||||
|
PROP|main.prop=value0
|
||||||
|
PROP|name=value
|
||||||
|
PROP|name0=changed0
|
||||||
|
PROP|name1=changed1
|
||||||
|
|
||||||
|
# Files / Directories to create
|
||||||
|
EXISTS|start.d/parameterized.ini
|
|
@ -0,0 +1,3 @@
|
||||||
|
other=value
|
||||||
|
name=changed
|
||||||
|
--commands=etc/commands.txt
|
|
@ -0,0 +1,5 @@
|
||||||
|
name0=changed0
|
||||||
|
name1=changed1
|
||||||
|
--add-to-start=parameterized
|
||||||
|
|
||||||
|
# ignore this
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
[depend]
|
||||||
|
main
|
||||||
|
|
||||||
|
[ini]
|
||||||
|
name=value
|
||||||
|
|
||||||
|
[ini-template]
|
||||||
|
name0=value0
|
||||||
|
# name1=value1
|
|
@ -166,6 +166,12 @@ public class DecoderFactory implements Configurable
|
||||||
{
|
{
|
||||||
LOG.debug("init({})",config);
|
LOG.debug("init({})",config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!containerScope.isRunning())
|
||||||
|
{
|
||||||
|
throw new RuntimeException(containerScope.getClass().getName() + " is not running yet");
|
||||||
|
}
|
||||||
|
|
||||||
// Instantiate all declared decoders
|
// Instantiate all declared decoders
|
||||||
for (DecoderMetadata metadata : metadatas)
|
for (DecoderMetadata metadata : metadatas)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import javax.websocket.server.ServerEndpointConfig;
|
import javax.websocket.server.ServerEndpointConfig;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||||
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
import org.eclipse.jetty.http.pathmap.UriTemplatePathSpec;
|
||||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||||
|
|
||||||
|
@ -38,7 +39,7 @@ public class PathParamServerEndpointConfig extends BasicServerEndpointConfig imp
|
||||||
super(containerScope, config);
|
super(containerScope, config);
|
||||||
|
|
||||||
Map<String, String> pathMap = pathSpec.getPathParams(requestPath);
|
Map<String, String> pathMap = pathSpec.getPathParams(requestPath);
|
||||||
pathParamMap = new HashMap<String, String>();
|
pathParamMap = new HashMap<>();
|
||||||
if (pathMap != null)
|
if (pathMap != null)
|
||||||
{
|
{
|
||||||
pathParamMap.putAll(pathMap);
|
pathParamMap.putAll(pathMap);
|
||||||
|
|
|
@ -40,28 +40,26 @@ import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
|
||||||
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
|
import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.EndpointInstance;
|
||||||
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
|
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
|
||||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||||
|
|
||||||
public class ServerContainer extends ClientContainer implements javax.websocket.server.ServerContainer
|
public class ServerContainer extends ClientContainer implements javax.websocket.server.ServerContainer
|
||||||
{
|
{
|
||||||
private static final Logger LOG = Log.getLogger(ServerContainer.class);
|
private static final Logger LOG = Log.getLogger(ServerContainer.class);
|
||||||
|
|
||||||
private final MappedWebSocketCreator mappedCreator;
|
private final NativeWebSocketConfiguration configuration;
|
||||||
private final WebSocketServerFactory webSocketServerFactory;
|
|
||||||
private List<Class<?>> deferredEndpointClasses;
|
private List<Class<?>> deferredEndpointClasses;
|
||||||
private List<ServerEndpointConfig> deferredEndpointConfigs;
|
private List<ServerEndpointConfig> deferredEndpointConfigs;
|
||||||
|
|
||||||
public ServerContainer(MappedWebSocketCreator creator, WebSocketServerFactory factory, Executor executor)
|
public ServerContainer(NativeWebSocketConfiguration configuration, Executor executor)
|
||||||
{
|
{
|
||||||
super(factory);
|
super(configuration.getFactory());
|
||||||
this.mappedCreator = creator;
|
this.configuration = configuration;
|
||||||
this.webSocketServerFactory = factory;
|
EventDriverFactory eventDriverFactory = this.configuration.getFactory().getEventDriverFactory();
|
||||||
EventDriverFactory eventDriverFactory = this.webSocketServerFactory.getEventDriverFactory();
|
|
||||||
eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
|
eventDriverFactory.addImplementation(new JsrServerEndpointImpl());
|
||||||
eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
|
eventDriverFactory.addImplementation(new JsrServerExtendsEndpointImpl());
|
||||||
this.webSocketServerFactory.addSessionFactory(new JsrSessionFactory(this));
|
this.configuration.getFactory().addSessionFactory(new JsrSessionFactory(this));
|
||||||
addBean(webSocketServerFactory);
|
addBean(this.configuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)
|
public EndpointInstance newClientEndpointInstance(Object endpoint, ServerEndpointConfig config, String path)
|
||||||
|
@ -102,8 +100,8 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
|
|
||||||
private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
|
private void addEndpoint(ServerEndpointMetadata metadata) throws DeploymentException
|
||||||
{
|
{
|
||||||
JsrCreator creator = new JsrCreator(this,metadata,webSocketServerFactory.getExtensionFactory());
|
JsrCreator creator = new JsrCreator(this,metadata,this.configuration.getFactory().getExtensionFactory());
|
||||||
mappedCreator.addMapping(new UriTemplatePathSpec(metadata.getPath()),creator);
|
this.configuration.addMapping(new UriTemplatePathSpec(metadata.getPath()),creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -154,13 +152,6 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStop() throws Exception
|
|
||||||
{
|
|
||||||
mappedCreator.getMappings().reset();
|
|
||||||
super.doStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException
|
public ServerEndpointMetadata getServerEndpointMetadata(final Class<?> endpoint, final ServerEndpointConfig config) throws DeploymentException
|
||||||
{
|
{
|
||||||
ServerEndpointMetadata metadata = null;
|
ServerEndpointMetadata metadata = null;
|
||||||
|
@ -197,32 +188,37 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
@Override
|
@Override
|
||||||
public long getDefaultAsyncSendTimeout()
|
public long getDefaultAsyncSendTimeout()
|
||||||
{
|
{
|
||||||
return webSocketServerFactory.getPolicy().getAsyncWriteTimeout();
|
return this.configuration.getPolicy().getAsyncWriteTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultMaxBinaryMessageBufferSize()
|
public int getDefaultMaxBinaryMessageBufferSize()
|
||||||
{
|
{
|
||||||
return webSocketServerFactory.getPolicy().getMaxBinaryMessageSize();
|
return this.configuration.getPolicy().getMaxBinaryMessageSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getDefaultMaxSessionIdleTimeout()
|
public long getDefaultMaxSessionIdleTimeout()
|
||||||
{
|
{
|
||||||
return webSocketServerFactory.getPolicy().getIdleTimeout();
|
return this.configuration.getPolicy().getIdleTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getDefaultMaxTextMessageBufferSize()
|
public int getDefaultMaxTextMessageBufferSize()
|
||||||
{
|
{
|
||||||
return webSocketServerFactory.getPolicy().getMaxTextMessageSize();
|
return this.configuration.getPolicy().getMaxTextMessageSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebSocketServerFactory getWebSocketServerFactory()
|
||||||
|
{
|
||||||
|
return this.configuration.getFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAsyncSendTimeout(long ms)
|
public void setAsyncSendTimeout(long ms)
|
||||||
{
|
{
|
||||||
super.setAsyncSendTimeout(ms);
|
super.setAsyncSendTimeout(ms);
|
||||||
webSocketServerFactory.getPolicy().setAsyncWriteTimeout(ms);
|
this.configuration.getPolicy().setAsyncWriteTimeout(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -230,16 +226,16 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
{
|
{
|
||||||
super.setDefaultMaxBinaryMessageBufferSize(max);
|
super.setDefaultMaxBinaryMessageBufferSize(max);
|
||||||
// overall message limit (used in non-streaming)
|
// overall message limit (used in non-streaming)
|
||||||
webSocketServerFactory.getPolicy().setMaxBinaryMessageSize(max);
|
this.configuration.getPolicy().setMaxBinaryMessageSize(max);
|
||||||
// incoming streaming buffer size
|
// incoming streaming buffer size
|
||||||
webSocketServerFactory.getPolicy().setMaxBinaryMessageBufferSize(max);
|
this.configuration.getPolicy().setMaxBinaryMessageBufferSize(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDefaultMaxSessionIdleTimeout(long ms)
|
public void setDefaultMaxSessionIdleTimeout(long ms)
|
||||||
{
|
{
|
||||||
super.setDefaultMaxSessionIdleTimeout(ms);
|
super.setDefaultMaxSessionIdleTimeout(ms);
|
||||||
webSocketServerFactory.getPolicy().setIdleTimeout(ms);
|
this.configuration.getPolicy().setIdleTimeout(ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -247,26 +243,26 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
{
|
{
|
||||||
super.setDefaultMaxTextMessageBufferSize(max);
|
super.setDefaultMaxTextMessageBufferSize(max);
|
||||||
// overall message limit (used in non-streaming)
|
// overall message limit (used in non-streaming)
|
||||||
webSocketServerFactory.getPolicy().setMaxTextMessageSize(max);
|
this.configuration.getPolicy().setMaxTextMessageSize(max);
|
||||||
// incoming streaming buffer size
|
// incoming streaming buffer size
|
||||||
webSocketServerFactory.getPolicy().setMaxTextMessageBufferSize(max);
|
this.configuration.getPolicy().setMaxTextMessageBufferSize(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionClosed(WebSocketSession session)
|
public void onSessionClosed(WebSocketSession session)
|
||||||
{
|
{
|
||||||
webSocketServerFactory.onSessionClosed(session);
|
getWebSocketServerFactory().onSessionClosed(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionOpened(WebSocketSession session)
|
public void onSessionOpened(WebSocketSession session)
|
||||||
{
|
{
|
||||||
webSocketServerFactory.onSessionOpened(session);
|
getWebSocketServerFactory().onSessionOpened(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Session> getOpenSessions()
|
public Set<Session> getOpenSessions()
|
||||||
{
|
{
|
||||||
return new HashSet<>(webSocketServerFactory.getBeans(Session.class));
|
return new HashSet<>(getWebSocketServerFactory().getBeans(Session.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,18 +33,14 @@ import javax.websocket.server.ServerApplicationConfig;
|
||||||
import javax.websocket.server.ServerEndpoint;
|
import javax.websocket.server.ServerEndpoint;
|
||||||
import javax.websocket.server.ServerEndpointConfig;
|
import javax.websocket.server.ServerEndpointConfig;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
|
||||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
import org.eclipse.jetty.util.TypeUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
|
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
|
||||||
import org.eclipse.jetty.websocket.server.DefaultMappedWebSocketCreator;
|
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
import org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer;
|
||||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
|
||||||
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
|
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
|
||||||
|
|
||||||
@HandlesTypes(
|
@HandlesTypes(
|
||||||
|
@ -137,18 +133,12 @@ public class WebSocketServerContainerInitializer implements ServletContainerInit
|
||||||
public static ServerContainer configureContext(ServletContextHandler context) throws ServletException
|
public static ServerContainer configureContext(ServletContextHandler context) throws ServletException
|
||||||
{
|
{
|
||||||
// Create Basic components
|
// Create Basic components
|
||||||
WebSocketPolicy policy = WebSocketPolicy.newServerPolicy();
|
NativeWebSocketConfiguration nativeWebSocketConfiguration = NativeWebSocketServletContainerInitializer.getDefaultFrom(context.getServletContext());
|
||||||
ByteBufferPool bufferPool = new MappedByteBufferPool();
|
|
||||||
MappedWebSocketCreator creator = new DefaultMappedWebSocketCreator();
|
|
||||||
WebSocketServerFactory factory = new WebSocketServerFactory(policy, bufferPool);
|
|
||||||
|
|
||||||
// Create the Jetty ServerContainer implementation
|
// Create the Jetty ServerContainer implementation
|
||||||
ServerContainer jettyContainer = new ServerContainer(creator,factory,context.getServer().getThreadPool());
|
ServerContainer jettyContainer = new ServerContainer(nativeWebSocketConfiguration, context.getServer().getThreadPool());
|
||||||
context.addBean(jettyContainer);
|
context.addBean(jettyContainer);
|
||||||
|
|
||||||
context.setAttribute(WebSocketUpgradeFilter.CREATOR_KEY, creator);
|
|
||||||
context.setAttribute(WebSocketUpgradeFilter.FACTORY_KEY, factory);
|
|
||||||
|
|
||||||
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
|
// Store a reference to the ServerContainer per javax.websocket spec 1.0 final section 6.4 Programmatic Server Deployment
|
||||||
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
|
context.setAttribute(javax.websocket.server.ServerContainer.class.getName(),jettyContainer);
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,19 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.jsr356.server;
|
package org.eclipse.jetty.websocket.jsr356.server;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathMappings;
|
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
public class DummyCreator implements MappedWebSocketCreator
|
public class DummyCreator implements MappedWebSocketCreator
|
||||||
{
|
{
|
||||||
|
@Override
|
||||||
|
public void addMapping(org.eclipse.jetty.websocket.server.pathmap.PathSpec spec, WebSocketCreator creator)
|
||||||
|
{
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
||||||
{
|
{
|
||||||
|
@ -32,7 +38,7 @@ public class DummyCreator implements MappedWebSocketCreator
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PathMappings<WebSocketCreator> getMappings()
|
public MappedResource<WebSocketCreator> getMapping(String target)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ import org.eclipse.jetty.websocket.jsr356.JsrExtension;
|
||||||
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpoint;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.echo.BasicEchoEndpoint;
|
||||||
import org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter;
|
import org.eclipse.jetty.websocket.server.NativeWebSocketConfiguration;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Assume;
|
import org.junit.Assume;
|
||||||
|
@ -88,8 +88,9 @@ public class ExtensionStackProcessingTest
|
||||||
|
|
||||||
private void assumeDeflateFrameAvailable()
|
private void assumeDeflateFrameAvailable()
|
||||||
{
|
{
|
||||||
WebSocketUpgradeFilter filter = (WebSocketUpgradeFilter)servletContextHandler.getAttribute(WebSocketUpgradeFilter.class.getName());
|
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) servletContextHandler
|
||||||
ExtensionFactory serverExtensionFactory = filter.getFactory().getExtensionFactory();
|
.getServletContext().getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||||
|
ExtensionFactory serverExtensionFactory = configuration.getFactory().getExtensionFactory();
|
||||||
Assume.assumeTrue("Server has permessage-deflate extension registered",serverExtensionFactory.isAvailable("permessage-deflate"));
|
Assume.assumeTrue("Server has permessage-deflate extension registered",serverExtensionFactory.isAvailable("permessage-deflate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ public class OnPartialTest
|
||||||
URI requestURI = URI.create("ws://localhost/" + id);
|
URI requestURI = URI.create("ws://localhost/" + id);
|
||||||
DummyConnection connection = new DummyConnection();
|
DummyConnection connection = new DummyConnection();
|
||||||
ClientContainer container = new ClientContainer();
|
ClientContainer container = new ClientContainer();
|
||||||
|
container.start();
|
||||||
|
|
||||||
@SuppressWarnings("resource")
|
@SuppressWarnings("resource")
|
||||||
JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
|
JsrSession session = new JsrSession(container,id,requestURI,driver,connection);
|
||||||
session.setPolicy(policy);
|
session.setPolicy(policy);
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class SessionTrackingTest
|
||||||
serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
|
serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler);
|
||||||
serverContainer.addEndpoint(EchoSocket.class);
|
serverContainer.addEndpoint(EchoSocket.class);
|
||||||
|
|
||||||
wsServerFactory = serverContainer.getBean(WebSocketServerFactory.class);
|
wsServerFactory = serverContainer.getWebSocketServerFactory();
|
||||||
|
|
||||||
server.start();
|
server.start();
|
||||||
|
|
||||||
|
|
|
@ -36,48 +36,54 @@ public interface WebSocketContainerScope
|
||||||
*
|
*
|
||||||
* @return the buffer pool (never null)
|
* @return the buffer pool (never null)
|
||||||
*/
|
*/
|
||||||
public ByteBufferPool getBufferPool();
|
ByteBufferPool getBufferPool();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executor in use by the container.
|
* Executor in use by the container.
|
||||||
*
|
*
|
||||||
* @return the Executor in use by the container.
|
* @return the Executor in use by the container.
|
||||||
*/
|
*/
|
||||||
public Executor getExecutor();
|
Executor getExecutor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object Factory used to create objects.
|
* Object Factory used to create objects.
|
||||||
*
|
*
|
||||||
* @return Object Factory used to create instances of objects.
|
* @return Object Factory used to create instances of objects.
|
||||||
*/
|
*/
|
||||||
public DecoratedObjectFactory getObjectFactory();
|
DecoratedObjectFactory getObjectFactory();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The policy the container is running on.
|
* The policy the container is running on.
|
||||||
*
|
*
|
||||||
* @return the websocket policy
|
* @return the websocket policy
|
||||||
*/
|
*/
|
||||||
public WebSocketPolicy getPolicy();
|
WebSocketPolicy getPolicy();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SslContextFactory in use by the container.
|
* The SslContextFactory in use by the container.
|
||||||
*
|
*
|
||||||
* @return the SslContextFactory in use by the container (can be null if no SSL context is defined)
|
* @return the SslContextFactory in use by the container (can be null if no SSL context is defined)
|
||||||
*/
|
*/
|
||||||
public SslContextFactory getSslContextFactory();
|
SslContextFactory getSslContextFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for if the container has been started.
|
||||||
|
*
|
||||||
|
* @return true if container is started and running
|
||||||
|
*/
|
||||||
|
boolean isRunning();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Session has been opened
|
* A Session has been opened
|
||||||
*
|
*
|
||||||
* @param session the session that was opened
|
* @param session the session that was opened
|
||||||
*/
|
*/
|
||||||
public void onSessionOpened(WebSocketSession session);
|
void onSessionOpened(WebSocketSession session);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Session has been closed
|
* A Session has been closed
|
||||||
*
|
*
|
||||||
* @param session the session that was closed
|
* @param session the session that was closed
|
||||||
*/
|
*/
|
||||||
public void onSessionClosed(WebSocketSession session);
|
void onSessionClosed(WebSocketSession session);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,18 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.websocket</groupId>
|
<groupId>org.eclipse.jetty.websocket</groupId>
|
||||||
<artifactId>websocket-common</artifactId>
|
<artifactId>websocket-common</artifactId>
|
||||||
|
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.server;
|
package org.eclipse.jetty.websocket.server;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathMappings;
|
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.websocket.server.pathmap.PathSpec;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +27,32 @@ import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
*/
|
*/
|
||||||
public interface MappedWebSocketCreator
|
public interface MappedWebSocketCreator
|
||||||
{
|
{
|
||||||
public void addMapping(PathSpec spec, WebSocketCreator creator);
|
/**
|
||||||
|
* Add a mapping.
|
||||||
|
*
|
||||||
|
* @param spec the path spec to use
|
||||||
|
* @param creator the creator for the mapping
|
||||||
|
* @deprecated use {@link #addMapping(org.eclipse.jetty.http.pathmap.PathSpec, WebSocketCreator)} instead.
|
||||||
|
* (support classes moved to generic jetty-http project)
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
void addMapping(PathSpec spec, WebSocketCreator creator);
|
||||||
|
|
||||||
public PathMappings<WebSocketCreator> getMappings();
|
/**
|
||||||
|
* Add a mapping.
|
||||||
|
*
|
||||||
|
* @param spec the path spec to use
|
||||||
|
* @param creator the creator for the mapping
|
||||||
|
* @since 9.2.20
|
||||||
|
*/
|
||||||
|
void addMapping(org.eclipse.jetty.http.pathmap.PathSpec spec, WebSocketCreator creator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get specific MappedResource for associated target.
|
||||||
|
*
|
||||||
|
* @param target the target to get mapping for
|
||||||
|
* @return the MappedResource for the target, or null if no match.
|
||||||
|
* @since 9.2.20
|
||||||
|
*/
|
||||||
|
MappedResource<WebSocketCreator> getMapping(String target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||||
|
import org.eclipse.jetty.http.pathmap.PathMappings;
|
||||||
|
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||||
|
import org.eclipse.jetty.http.pathmap.RegexPathSpec;
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
|
import org.eclipse.jetty.util.component.Dumpable;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for Configuring Jetty Server Native WebSockets
|
||||||
|
* <p>
|
||||||
|
* Only applicable if using {@link WebSocketUpgradeFilter}
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public class NativeWebSocketConfiguration extends ContainerLifeCycle implements Dumpable
|
||||||
|
{
|
||||||
|
private final WebSocketServerFactory factory;
|
||||||
|
private final PathMappings<WebSocketCreator> mappings = new PathMappings<>();
|
||||||
|
|
||||||
|
public NativeWebSocketConfiguration(ServletContext context)
|
||||||
|
{
|
||||||
|
this(new WebSocketServerFactory(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public NativeWebSocketConfiguration(WebSocketServerFactory webSocketServerFactory)
|
||||||
|
{
|
||||||
|
this.factory = webSocketServerFactory;
|
||||||
|
addBean(this.factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doStop() throws Exception
|
||||||
|
{
|
||||||
|
mappings.reset();
|
||||||
|
super.doStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String dump()
|
||||||
|
{
|
||||||
|
return ContainerLifeCycle.dump(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
|
{
|
||||||
|
// TODO: show factory/mappings ?
|
||||||
|
mappings.dump(out, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get WebSocketServerFactory being used.
|
||||||
|
*
|
||||||
|
* @return the WebSocketServerFactory being used.
|
||||||
|
*/
|
||||||
|
public WebSocketServerFactory getFactory()
|
||||||
|
{
|
||||||
|
return this.factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the matching {@link MappedResource} for the provided target.
|
||||||
|
*
|
||||||
|
* @param target the target path
|
||||||
|
* @return the matching resource, or null if no match.
|
||||||
|
*/
|
||||||
|
public MappedResource<WebSocketCreator> getMatch(String target)
|
||||||
|
{
|
||||||
|
return this.mappings.getMatch(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to configure the Default {@link WebSocketPolicy} used by all endpoints that
|
||||||
|
* don't redeclare the values.
|
||||||
|
*
|
||||||
|
* @return the default policy for all WebSockets
|
||||||
|
*/
|
||||||
|
public WebSocketPolicy getPolicy()
|
||||||
|
{
|
||||||
|
return this.factory.getPolicy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually add a WebSocket mapping.
|
||||||
|
*
|
||||||
|
* @param pathSpec the pathspec to respond on
|
||||||
|
* @param creator the websocket creator to activate on the provided mapping.
|
||||||
|
*/
|
||||||
|
public void addMapping(PathSpec pathSpec, WebSocketCreator creator)
|
||||||
|
{
|
||||||
|
mappings.put(pathSpec, creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually add a WebSocket mapping.
|
||||||
|
*
|
||||||
|
* @param spec the pathspec to respond on
|
||||||
|
* @param creator the websocket creator to activate on the provided mapping
|
||||||
|
* @deprecated use {@link #addMapping(PathSpec, Class)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public void addMapping(org.eclipse.jetty.websocket.server.pathmap.PathSpec spec, WebSocketCreator creator)
|
||||||
|
{
|
||||||
|
if (spec instanceof org.eclipse.jetty.websocket.server.pathmap.ServletPathSpec)
|
||||||
|
{
|
||||||
|
addMapping(new ServletPathSpec(spec.getSpec()), creator);
|
||||||
|
}
|
||||||
|
else if (spec instanceof org.eclipse.jetty.websocket.server.pathmap.RegexPathSpec)
|
||||||
|
{
|
||||||
|
addMapping(new RegexPathSpec(spec.getSpec()), creator);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Unsupported (Deprecated) PathSpec implementation type: " + spec.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually add a WebSocket mapping.
|
||||||
|
*
|
||||||
|
* @param pathSpec the pathspec to respond on
|
||||||
|
* @param endpointClass the endpoint class to use for new upgrade requests on the provided
|
||||||
|
* pathspec (can be an {@link org.eclipse.jetty.websocket.api.annotations.WebSocket} annotated
|
||||||
|
* POJO, or implementing {@link org.eclipse.jetty.websocket.api.WebSocketListener})
|
||||||
|
*/
|
||||||
|
public void addMapping(PathSpec pathSpec, final Class<?> endpointClass)
|
||||||
|
{
|
||||||
|
mappings.put(pathSpec, new WebSocketCreator()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return endpointClass.newInstance();
|
||||||
|
}
|
||||||
|
catch (InstantiationException | IllegalAccessException e)
|
||||||
|
{
|
||||||
|
throw new WebSocketException("Unable to create instance of " + endpointClass.getName(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContainerInitializer;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
|
||||||
|
public class NativeWebSocketServletContainerInitializer implements ServletContainerInitializer
|
||||||
|
{
|
||||||
|
public static NativeWebSocketConfiguration getDefaultFrom(ServletContext context)
|
||||||
|
{
|
||||||
|
final String KEY = NativeWebSocketConfiguration.class.getName();
|
||||||
|
|
||||||
|
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getAttribute(KEY);
|
||||||
|
if (configuration == null)
|
||||||
|
{
|
||||||
|
configuration = new NativeWebSocketConfiguration(context);
|
||||||
|
context.setAttribute(KEY, configuration);
|
||||||
|
}
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartup(Set<Class<?>> c, ServletContext ctx) throws ServletException
|
||||||
|
{
|
||||||
|
// initialize
|
||||||
|
getDefaultFrom(ctx);
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,7 +54,8 @@ public abstract class WebSocketHandler extends HandlerWrapper
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final WebSocketServletFactory webSocketFactory;
|
private final ByteBufferPool bufferPool;
|
||||||
|
private WebSocketServletFactory webSocketFactory;
|
||||||
|
|
||||||
public WebSocketHandler()
|
public WebSocketHandler()
|
||||||
{
|
{
|
||||||
|
@ -63,10 +64,7 @@ public abstract class WebSocketHandler extends HandlerWrapper
|
||||||
|
|
||||||
public WebSocketHandler(ByteBufferPool bufferPool)
|
public WebSocketHandler(ByteBufferPool bufferPool)
|
||||||
{
|
{
|
||||||
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
this.bufferPool = bufferPool;
|
||||||
configurePolicy(policy);
|
|
||||||
webSocketFactory = new WebSocketServerFactory(policy, bufferPool);
|
|
||||||
addBean(webSocketFactory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void configure(WebSocketServletFactory factory);
|
public abstract void configure(WebSocketServletFactory factory);
|
||||||
|
@ -79,12 +77,18 @@ public abstract class WebSocketHandler extends HandlerWrapper
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws Exception
|
protected void doStart() throws Exception
|
||||||
{
|
{
|
||||||
|
WebSocketPolicy policy = new WebSocketPolicy(WebSocketBehavior.SERVER);
|
||||||
|
configurePolicy(policy);
|
||||||
|
webSocketFactory = new WebSocketServerFactory(policy, getServer().getThreadPool(), bufferPool);
|
||||||
|
addBean(webSocketFactory);
|
||||||
configure(webSocketFactory);
|
configure(webSocketFactory);
|
||||||
super.doStart();
|
super.doStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServletFactory getWebSocketFactory()
|
public WebSocketServletFactory getWebSocketFactory()
|
||||||
{
|
{
|
||||||
|
if (!isRunning())
|
||||||
|
throw new IllegalStateException("Not Started yet");
|
||||||
return webSocketFactory;
|
return webSocketFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,12 +28,12 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@ import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
import org.eclipse.jetty.server.HttpConnection;
|
import org.eclipse.jetty.server.HttpConnection;
|
||||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
|
||||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
|
@ -86,9 +85,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
|
|
||||||
private final ClassLoader contextClassloader;
|
private final ClassLoader contextClassloader;
|
||||||
private final Map<Integer, WebSocketHandshake> handshakes = new HashMap<>();
|
private final Map<Integer, WebSocketHandshake> handshakes = new HashMap<>();
|
||||||
/**
|
// TODO: obtain shared (per server scheduler, somehow)
|
||||||
* Have the factory maintain 1 and only 1 scheduler. All connections share this scheduler.
|
|
||||||
*/
|
|
||||||
private final Scheduler scheduler = new ScheduledExecutorScheduler();
|
private final Scheduler scheduler = new ScheduledExecutorScheduler();
|
||||||
private final List<WebSocketSession.Listener> listeners = new CopyOnWriteArrayList<>();
|
private final List<WebSocketSession.Listener> listeners = new CopyOnWriteArrayList<>();
|
||||||
private final String supportedVersions;
|
private final String supportedVersions;
|
||||||
|
@ -96,29 +93,57 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
private final EventDriverFactory eventDriverFactory;
|
private final EventDriverFactory eventDriverFactory;
|
||||||
private final ByteBufferPool bufferPool;
|
private final ByteBufferPool bufferPool;
|
||||||
private final WebSocketExtensionFactory extensionFactory;
|
private final WebSocketExtensionFactory extensionFactory;
|
||||||
|
private final ServletContext context; // can be null when this factory is used from WebSocketHandler
|
||||||
|
private final List<SessionFactory> sessionFactories = new ArrayList<>();
|
||||||
|
private final List<Class<?>> registeredSocketClasses = new ArrayList<>();
|
||||||
private Executor executor;
|
private Executor executor;
|
||||||
private List<SessionFactory> sessionFactories;
|
|
||||||
private WebSocketCreator creator;
|
|
||||||
private List<Class<?>> registeredSocketClasses;
|
|
||||||
private DecoratedObjectFactory objectFactory;
|
private DecoratedObjectFactory objectFactory;
|
||||||
|
private WebSocketCreator creator;
|
||||||
|
|
||||||
public WebSocketServerFactory()
|
public WebSocketServerFactory(ServletContext context)
|
||||||
{
|
{
|
||||||
this(WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool());
|
this(context, WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServerFactory(WebSocketPolicy policy)
|
public WebSocketServerFactory(ServletContext context, ByteBufferPool bufferPool)
|
||||||
{
|
{
|
||||||
this(policy, new MappedByteBufferPool());
|
this(context, WebSocketPolicy.newServerPolicy(), bufferPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServerFactory(ByteBufferPool bufferPool)
|
/**
|
||||||
|
* Entry point for {@link org.eclipse.jetty.websocket.servlet.WebSocketServletFactory.Loader}
|
||||||
|
*
|
||||||
|
* @param context the servlet context
|
||||||
|
* @param policy the policy to use
|
||||||
|
*/
|
||||||
|
public WebSocketServerFactory(ServletContext context, WebSocketPolicy policy)
|
||||||
{
|
{
|
||||||
this(WebSocketPolicy.newServerPolicy(), bufferPool);
|
this(context, policy, new MappedByteBufferPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServerFactory(WebSocketPolicy policy, ByteBufferPool bufferPool)
|
public WebSocketServerFactory(ServletContext context, WebSocketPolicy policy, ByteBufferPool bufferPool)
|
||||||
{
|
{
|
||||||
|
this(Objects.requireNonNull(context, ServletContext.class.getName()), policy, null, null, bufferPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protected entry point for {@link WebSocketHandler}
|
||||||
|
*
|
||||||
|
* @param policy the policy to use
|
||||||
|
* @param executor the executor to use
|
||||||
|
* @param bufferPool the buffer pool to use
|
||||||
|
*/
|
||||||
|
protected WebSocketServerFactory(WebSocketPolicy policy, Executor executor, ByteBufferPool bufferPool)
|
||||||
|
{
|
||||||
|
this(null, policy, new DecoratedObjectFactory(), executor, bufferPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WebSocketServerFactory(ServletContext context, WebSocketPolicy policy, DecoratedObjectFactory objectFactory, Executor executor, ByteBufferPool bufferPool)
|
||||||
|
{
|
||||||
|
this.context = context;
|
||||||
|
this.objectFactory = objectFactory;
|
||||||
|
this.executor = executor;
|
||||||
|
|
||||||
handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455());
|
handshakes.put(HandshakeRFC6455.VERSION, new HandshakeRFC6455());
|
||||||
|
|
||||||
addBean(scheduler);
|
addBean(scheduler);
|
||||||
|
@ -126,14 +151,11 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
|
|
||||||
this.contextClassloader = Thread.currentThread().getContextClassLoader();
|
this.contextClassloader = Thread.currentThread().getContextClassLoader();
|
||||||
|
|
||||||
this.registeredSocketClasses = new ArrayList<>();
|
|
||||||
|
|
||||||
this.defaultPolicy = policy;
|
this.defaultPolicy = policy;
|
||||||
this.eventDriverFactory = new EventDriverFactory(defaultPolicy);
|
this.eventDriverFactory = new EventDriverFactory(defaultPolicy);
|
||||||
this.bufferPool = bufferPool;
|
this.bufferPool = bufferPool;
|
||||||
this.extensionFactory = new WebSocketExtensionFactory(this);
|
this.extensionFactory = new WebSocketExtensionFactory(this);
|
||||||
|
|
||||||
this.sessionFactories = new ArrayList<>();
|
|
||||||
this.sessionFactories.add(new WebSocketSessionFactory(this));
|
this.sessionFactories.add(new WebSocketSessionFactory(this));
|
||||||
this.creator = this;
|
this.creator = this;
|
||||||
|
|
||||||
|
@ -203,7 +225,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
websocketPojo = getObjectFactory().decorate(websocketPojo);
|
websocketPojo = getObjectFactory().decorate(websocketPojo);
|
||||||
|
|
||||||
// Get the original HTTPConnection
|
// Get the original HTTPConnection
|
||||||
HttpConnection connection = (HttpConnection)request.getAttribute("org.eclipse.jetty.server.HttpConnection");
|
HttpConnection connection = (HttpConnection) request.getAttribute("org.eclipse.jetty.server.HttpConnection");
|
||||||
|
|
||||||
// Send the upgrade
|
// Send the upgrade
|
||||||
EventDriver driver = eventDriverFactory.wrap(websocketPojo);
|
EventDriver driver = eventDriverFactory.wrap(websocketPojo);
|
||||||
|
@ -228,25 +250,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
this.sessionFactories.add(sessionFactory);
|
this.sessionFactories.add(sessionFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void cleanup()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LOG.warn(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WebSocketServletFactory createFactory(WebSocketPolicy policy)
|
|
||||||
{
|
|
||||||
return new WebSocketServerFactory(policy, bufferPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
private WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
|
private WebSocketSession createSession(URI requestURI, EventDriver websocket, LogicalConnection connection)
|
||||||
{
|
{
|
||||||
if (websocket == null)
|
if (websocket == null)
|
||||||
|
@ -302,11 +305,24 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws Exception
|
protected void doStart() throws Exception
|
||||||
{
|
{
|
||||||
if(this.objectFactory == null)
|
if(this.objectFactory == null && context != null)
|
||||||
{
|
{
|
||||||
this.objectFactory = new DecoratedObjectFactory();
|
this.objectFactory = (DecoratedObjectFactory) context.getAttribute(DecoratedObjectFactory.ATTR);
|
||||||
|
if (this.objectFactory == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Unable to find required ServletContext attribute: " + DecoratedObjectFactory.ATTR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(this.executor == null && context != null)
|
||||||
|
{
|
||||||
|
ContextHandler contextHandler = ContextHandler.getContextHandler(context);
|
||||||
|
this.executor = contextHandler.getServer().getThreadPool();
|
||||||
|
}
|
||||||
|
|
||||||
|
Objects.requireNonNull(this.objectFactory, DecoratedObjectFactory.class.getName());
|
||||||
|
Objects.requireNonNull(this.executor, Executor.class.getName());
|
||||||
|
|
||||||
super.doStart();
|
super.doStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,52 +380,6 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(ServletContextHandler context) throws ServletException
|
|
||||||
{
|
|
||||||
this.objectFactory = (DecoratedObjectFactory)context.getServletContext().getAttribute(DecoratedObjectFactory.ATTR);
|
|
||||||
if (this.objectFactory == null)
|
|
||||||
{
|
|
||||||
this.objectFactory = new DecoratedObjectFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.executor = context.getServer().getThreadPool();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(ServletContext context) throws ServletException
|
|
||||||
{
|
|
||||||
// Setup ObjectFactory
|
|
||||||
this.objectFactory = (DecoratedObjectFactory)context.getAttribute(DecoratedObjectFactory.ATTR);
|
|
||||||
if (this.objectFactory == null)
|
|
||||||
{
|
|
||||||
this.objectFactory = new DecoratedObjectFactory();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate Environment
|
|
||||||
ContextHandler handler = ContextHandler.getContextHandler(context);
|
|
||||||
|
|
||||||
if (handler == null)
|
|
||||||
{
|
|
||||||
throw new ServletException("Not running on Jetty, WebSocket support unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.executor = handler.getServer().getThreadPool();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// start lifecycle
|
|
||||||
start();
|
|
||||||
}
|
|
||||||
catch (ServletException e)
|
|
||||||
{
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new ServletException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
|
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
|
||||||
{
|
{
|
||||||
|
@ -515,11 +485,10 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
|
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
|
||||||
* connection.
|
* connection.
|
||||||
*
|
*
|
||||||
* @param http the raw http connection
|
* @param http the raw http connection
|
||||||
* @param request The request to upgrade
|
* @param request The request to upgrade
|
||||||
* @param response The response to upgrade
|
* @param response The response to upgrade
|
||||||
* @param driver The websocket handler implementation to use
|
* @param driver The websocket handler implementation to use
|
||||||
* @throws IOException
|
|
||||||
*/
|
*/
|
||||||
private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException
|
private boolean upgrade(HttpConnection http, ServletUpgradeRequest request, ServletUpgradeResponse response, EventDriver driver) throws IOException
|
||||||
{
|
{
|
||||||
|
@ -638,7 +607,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
LOG.debug("Handshake Response: {}", handshaker);
|
LOG.debug("Handshake Response: {}", handshaker);
|
||||||
|
|
||||||
if (getSendServerVersion(connector))
|
if (getSendServerVersion(connector))
|
||||||
response.setHeader("Server",HttpConfiguration.SERVER_VERSION);
|
response.setHeader("Server", HttpConfiguration.SERVER_VERSION);
|
||||||
|
|
||||||
// Process (version specific) handshake response
|
// Process (version specific) handshake response
|
||||||
handshaker.doHandshakeResponse(request, response);
|
handshaker.doHandshakeResponse(request, response);
|
||||||
|
@ -657,7 +626,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
|
|
||||||
if (connFactory instanceof HttpConnectionFactory)
|
if (connFactory instanceof HttpConnectionFactory)
|
||||||
{
|
{
|
||||||
HttpConfiguration httpConf = ((HttpConnectionFactory)connFactory).getHttpConfiguration();
|
HttpConfiguration httpConf = ((HttpConnectionFactory) connFactory).getHttpConfiguration();
|
||||||
if (httpConf != null)
|
if (httpConf != null)
|
||||||
return httpConf.getSendServerVersion();
|
return httpConf.getSendServerVersion();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,35 +33,28 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.MappedResource;
|
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||||
import org.eclipse.jetty.http.pathmap.PathMappings;
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||||
import org.eclipse.jetty.http.pathmap.RegexPathSpec;
|
|
||||||
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
|
||||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.servlet.FilterHolder;
|
import org.eclipse.jetty.servlet.FilterHolder;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
import org.eclipse.jetty.util.component.Dumpable;
|
import org.eclipse.jetty.util.component.Dumpable;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inline Servlet Filter to capture WebSocket upgrade requests and perform path mappings to {@link WebSocketCreator} objects.
|
* Inline Servlet Filter to capture WebSocket upgrade requests and perform path mappings to {@link WebSocketCreator} objects.
|
||||||
*/
|
*/
|
||||||
@ManagedObject("WebSocket Upgrade Filter")
|
@ManagedObject("WebSocket Upgrade Filter")
|
||||||
public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter, MappedWebSocketCreator, Dumpable
|
public class WebSocketUpgradeFilter implements Filter, MappedWebSocketCreator, Dumpable
|
||||||
{
|
{
|
||||||
public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey";
|
|
||||||
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
|
private static final Logger LOG = Log.getLogger(WebSocketUpgradeFilter.class);
|
||||||
private boolean localMapper;
|
public static final String CONTEXT_ATTRIBUTE_KEY = "contextAttributeKey";
|
||||||
private boolean localFactory;
|
public static final String CONFIG_ATTRIBUTE_KEY = "configAttributeKey";
|
||||||
|
|
||||||
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) throws ServletException
|
public static WebSocketUpgradeFilter configureContext(ServletContextHandler context) throws ServletException
|
||||||
{
|
{
|
||||||
|
@ -73,7 +66,8 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dynamically add filter
|
// Dynamically add filter
|
||||||
filter = new WebSocketUpgradeFilter();
|
NativeWebSocketConfiguration configuration = NativeWebSocketServletContainerInitializer.getDefaultFrom(context.getServletContext());
|
||||||
|
filter = new WebSocketUpgradeFilter(configuration);
|
||||||
filter.setToAttribute(context, WebSocketUpgradeFilter.class.getName());
|
filter.setToAttribute(context, WebSocketUpgradeFilter.class.getName());
|
||||||
|
|
||||||
String name = "Jetty_WebSocketUpgradeFilter";
|
String name = "Jetty_WebSocketUpgradeFilter";
|
||||||
|
@ -115,69 +109,71 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
return configureContext((ServletContextHandler) handler);
|
return configureContext((ServletContextHandler) handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String CREATOR_KEY = "org.eclipse.jetty.websocket.server.creator";
|
private NativeWebSocketConfiguration configuration;
|
||||||
public static final String FACTORY_KEY = "org.eclipse.jetty.websocket.server.factory";
|
private boolean localConfiguration = false;
|
||||||
|
|
||||||
private final WebSocketPolicy policy;
|
|
||||||
private final ByteBufferPool bufferPool;
|
|
||||||
private WebSocketServerFactory factory;
|
|
||||||
private MappedWebSocketCreator mappedWebSocketCreator;
|
|
||||||
private String fname;
|
|
||||||
private boolean alreadySetToAttribute = false;
|
private boolean alreadySetToAttribute = false;
|
||||||
|
|
||||||
public WebSocketUpgradeFilter()
|
public WebSocketUpgradeFilter()
|
||||||
{
|
{
|
||||||
this(WebSocketPolicy.newServerPolicy(), new MappedByteBufferPool());
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketUpgradeFilter(WebSocketPolicy policy, ByteBufferPool bufferPool)
|
public WebSocketUpgradeFilter(WebSocketServerFactory factory)
|
||||||
{
|
{
|
||||||
this.policy = policy;
|
this(new NativeWebSocketConfiguration(factory));
|
||||||
this.bufferPool = bufferPool;
|
}
|
||||||
|
|
||||||
|
public WebSocketUpgradeFilter(NativeWebSocketConfiguration configuration)
|
||||||
|
{
|
||||||
|
this.configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
||||||
{
|
{
|
||||||
mappedWebSocketCreator.addMapping(spec, creator);
|
configuration.addMapping(spec, creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use new {@link #addMapping(org.eclipse.jetty.http.pathmap.PathSpec, WebSocketCreator)} instead
|
* @deprecated use new {@link #addMapping(org.eclipse.jetty.http.pathmap.PathSpec, WebSocketCreator)} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@Override
|
||||||
public void addMapping(org.eclipse.jetty.websocket.server.pathmap.PathSpec spec, WebSocketCreator creator)
|
public void addMapping(org.eclipse.jetty.websocket.server.pathmap.PathSpec spec, WebSocketCreator creator)
|
||||||
{
|
{
|
||||||
if (spec instanceof org.eclipse.jetty.websocket.server.pathmap.ServletPathSpec)
|
configuration.addMapping(spec, creator);
|
||||||
{
|
|
||||||
addMapping(new ServletPathSpec(spec.getSpec()), creator);
|
|
||||||
}
|
|
||||||
else if (spec instanceof org.eclipse.jetty.websocket.server.pathmap.RegexPathSpec)
|
|
||||||
{
|
|
||||||
addMapping(new RegexPathSpec(spec.getSpec()), creator);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Unsupported (Deprecated) PathSpec implementation: " + spec.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
if (localFactory)
|
try
|
||||||
{
|
{
|
||||||
factory.cleanup();
|
alreadySetToAttribute = false;
|
||||||
|
if(localConfiguration)
|
||||||
|
{
|
||||||
|
configuration.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (localMapper)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
mappedWebSocketCreator.getMappings().reset();
|
LOG.ignore(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
|
||||||
{
|
{
|
||||||
|
if (configuration == null)
|
||||||
|
{
|
||||||
|
// no configuration, cannot operate
|
||||||
|
LOG.debug("WebSocketUpgradeFilter is not operational - missing " + NativeWebSocketConfiguration.class.getName());
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebSocketServletFactory factory = configuration.getFactory();
|
||||||
|
|
||||||
if (factory == null)
|
if (factory == null)
|
||||||
{
|
{
|
||||||
// no factory, cannot operate
|
// no factory, cannot operate
|
||||||
|
@ -206,14 +202,9 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
target = target.substring(contextPath.length());
|
target = target.substring(contextPath.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedResource<WebSocketCreator> resource = mappedWebSocketCreator.getMappings().getMatch(target);
|
MappedResource<WebSocketCreator> resource = configuration.getMatch(target);
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("WebSocket Upgrade on {} has no associated endpoint", target);
|
|
||||||
LOG.debug("PathMappings: {}", mappedWebSocketCreator.getMappings().dump());
|
|
||||||
}
|
|
||||||
// no match.
|
// no match.
|
||||||
chain.doFilter(request, response);
|
chain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
|
@ -267,68 +258,89 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
@Override
|
@Override
|
||||||
public void dump(Appendable out, String indent) throws IOException
|
public void dump(Appendable out, String indent) throws IOException
|
||||||
{
|
{
|
||||||
out.append(indent).append(" +- pathmap=").append(mappedWebSocketCreator.toString()).append("\n");
|
out.append(indent).append(" +- configuration=").append(configuration.toString()).append("\n");
|
||||||
mappedWebSocketCreator.getMappings().dump(out, indent + " ");
|
configuration.dump(out, indent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketServerFactory getFactory()
|
public WebSocketServletFactory getFactory()
|
||||||
{
|
{
|
||||||
return factory;
|
return configuration.getFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ManagedAttribute(value = "configuration", readonly = true)
|
||||||
|
public NativeWebSocketConfiguration getConfiguration()
|
||||||
|
{
|
||||||
|
if (configuration == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(this.getClass().getName() + " not initialized yet");
|
||||||
|
}
|
||||||
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManagedAttribute(value = "mappings", readonly = true)
|
|
||||||
@Override
|
@Override
|
||||||
public PathMappings<WebSocketCreator> getMappings()
|
public MappedResource<WebSocketCreator> getMapping(String target)
|
||||||
{
|
{
|
||||||
return mappedWebSocketCreator.getMappings();
|
return getConfiguration().getMatch(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(FilterConfig config) throws ServletException
|
public void init(FilterConfig config) throws ServletException
|
||||||
{
|
{
|
||||||
fname = config.getFilterName();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ServletContext context = config.getServletContext();
|
String configurationKey = config.getInitParameter(CONFIG_ATTRIBUTE_KEY);
|
||||||
|
if (configurationKey == null)
|
||||||
mappedWebSocketCreator = (MappedWebSocketCreator) context.getAttribute(CREATOR_KEY);
|
|
||||||
if (mappedWebSocketCreator == null)
|
|
||||||
{
|
{
|
||||||
mappedWebSocketCreator = new DefaultMappedWebSocketCreator();
|
configurationKey = NativeWebSocketConfiguration.class.getName();
|
||||||
localMapper = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
factory = (WebSocketServerFactory) context.getAttribute(FACTORY_KEY);
|
if (configuration == null)
|
||||||
if (factory == null)
|
|
||||||
{
|
{
|
||||||
factory = new WebSocketServerFactory(policy, bufferPool);
|
this.configuration = (NativeWebSocketConfiguration) config.getServletContext().getAttribute(configurationKey);
|
||||||
localFactory = true;
|
if (this.configuration == null)
|
||||||
|
{
|
||||||
|
// The NativeWebSocketConfiguration should have arrived from the NativeWebSocketServletContainerInitializer
|
||||||
|
throw new ServletException("Unable to find required instance of " +
|
||||||
|
NativeWebSocketConfiguration.class.getName() + " at ServletContext attribute '" + configurationKey + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We have a NativeWebSocketConfiguration already present, make sure it exists on the ServletContext
|
||||||
|
if (config.getServletContext().getAttribute(configurationKey) == null)
|
||||||
|
{
|
||||||
|
config.getServletContext().setAttribute(configurationKey, this.configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.configuration.isRunning())
|
||||||
|
{
|
||||||
|
localConfiguration = true;
|
||||||
|
this.configuration.start();
|
||||||
}
|
}
|
||||||
factory.init(context);
|
|
||||||
|
|
||||||
String max = config.getInitParameter("maxIdleTime");
|
String max = config.getInitParameter("maxIdleTime");
|
||||||
if (max != null)
|
if (max != null)
|
||||||
{
|
{
|
||||||
factory.getPolicy().setIdleTimeout(Long.parseLong(max));
|
getFactory().getPolicy().setIdleTimeout(Long.parseLong(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
max = config.getInitParameter("maxTextMessageSize");
|
max = config.getInitParameter("maxTextMessageSize");
|
||||||
if (max != null)
|
if (max != null)
|
||||||
{
|
{
|
||||||
factory.getPolicy().setMaxTextMessageSize(Integer.parseInt(max));
|
getFactory().getPolicy().setMaxTextMessageSize(Integer.parseInt(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
max = config.getInitParameter("maxBinaryMessageSize");
|
max = config.getInitParameter("maxBinaryMessageSize");
|
||||||
if (max != null)
|
if (max != null)
|
||||||
{
|
{
|
||||||
factory.getPolicy().setMaxBinaryMessageSize(Integer.parseInt(max));
|
getFactory().getPolicy().setMaxBinaryMessageSize(Integer.parseInt(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
max = config.getInitParameter("inputBufferSize");
|
max = config.getInitParameter("inputBufferSize");
|
||||||
if (max != null)
|
if (max != null)
|
||||||
{
|
{
|
||||||
factory.getPolicy().setInputBufferSize(Integer.parseInt(max));
|
getFactory().getPolicy().setInputBufferSize(Integer.parseInt(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = config.getInitParameter(CONTEXT_ATTRIBUTE_KEY);
|
String key = config.getInitParameter(CONTEXT_ATTRIBUTE_KEY);
|
||||||
|
@ -338,33 +350,22 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
key = WebSocketUpgradeFilter.class.getName();
|
key = WebSocketUpgradeFilter.class.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
setToAttribute(context, key);
|
// Set instance of this filter to context attribute
|
||||||
|
setToAttribute(config.getServletContext(), key);
|
||||||
factory.start();
|
|
||||||
}
|
}
|
||||||
catch (Exception x)
|
catch (ServletException e)
|
||||||
{
|
{
|
||||||
throw new ServletException(x);
|
throw e;
|
||||||
|
}
|
||||||
|
catch (Throwable t)
|
||||||
|
{
|
||||||
|
throw new ServletException(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setToAttribute(ServletContextHandler context, String key) throws ServletException
|
private void setToAttribute(ServletContextHandler context, String key) throws ServletException
|
||||||
{
|
{
|
||||||
if (alreadySetToAttribute)
|
setToAttribute(context.getServletContext(), key);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (context.getAttribute(key) != null)
|
|
||||||
{
|
|
||||||
throw new ServletException(WebSocketUpgradeFilter.class.getName() +
|
|
||||||
" is defined twice for the same context attribute key '" + key
|
|
||||||
+ "'. Make sure you have different init-param '" +
|
|
||||||
CONTEXT_ATTRIBUTE_KEY + "' values set");
|
|
||||||
}
|
|
||||||
context.setAttribute(key, this);
|
|
||||||
|
|
||||||
alreadySetToAttribute = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setToAttribute(ServletContext context, String key) throws ServletException
|
public void setToAttribute(ServletContext context, String key) throws ServletException
|
||||||
|
@ -389,6 +390,6 @@ public class WebSocketUpgradeFilter extends AbstractLifeCycle implements Filter,
|
||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return String.format("%s[factory=%s,creator=%s]", this.getClass().getSimpleName(), factory, mappedWebSocketCreator);
|
return String.format("%s[configuration=%s]", this.getClass().getSimpleName(), configuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,47 +25,60 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.MappedResource;
|
import org.eclipse.jetty.http.pathmap.MappedResource;
|
||||||
import org.eclipse.jetty.http.pathmap.PathMappings;
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.http.pathmap.PathSpec;
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements MappedWebSocketCreator
|
public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements MappedWebSocketCreator
|
||||||
{
|
{
|
||||||
private PathMappings<WebSocketCreator> pathmap = new PathMappings<>();
|
private NativeWebSocketConfiguration configuration;
|
||||||
private final WebSocketServerFactory factory;
|
|
||||||
|
|
||||||
public WebSocketUpgradeHandlerWrapper()
|
public WebSocketUpgradeHandlerWrapper(ServletContextHandler context)
|
||||||
{
|
{
|
||||||
this(new MappedByteBufferPool());
|
this(context, new MappedByteBufferPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebSocketUpgradeHandlerWrapper(ByteBufferPool bufferPool)
|
public WebSocketUpgradeHandlerWrapper(ServletContextHandler context, ByteBufferPool bufferPool)
|
||||||
{
|
{
|
||||||
factory = new WebSocketServerFactory(bufferPool);
|
this.configuration = new NativeWebSocketConfiguration(new WebSocketServerFactory(context.getServletContext(), bufferPool));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
||||||
{
|
{
|
||||||
pathmap.put(spec,creator);
|
this.configuration.addMapping(spec, creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a mapping.
|
||||||
|
*
|
||||||
|
* @param spec the path spec to use
|
||||||
|
* @param creator the creator for the mapping
|
||||||
|
* @deprecated use {@link #addMapping(PathSpec, WebSocketCreator)} instead.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void addMapping(org.eclipse.jetty.websocket.server.pathmap.PathSpec spec, WebSocketCreator creator)
|
||||||
|
{
|
||||||
|
configuration.addMapping(spec, creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PathMappings<WebSocketCreator> getMappings()
|
public MappedResource<WebSocketCreator> getMapping(String target)
|
||||||
{
|
{
|
||||||
return pathmap;
|
return this.configuration.getMatch(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||||
{
|
{
|
||||||
if (factory.isUpgradeRequest(request,response))
|
if (configuration.getFactory().isUpgradeRequest(request,response))
|
||||||
{
|
{
|
||||||
MappedResource<WebSocketCreator> resource = pathmap.getMatch(target);
|
MappedResource<WebSocketCreator> resource = configuration.getMatch(target);
|
||||||
if (resource == null)
|
if (resource == null)
|
||||||
{
|
{
|
||||||
// no match.
|
// no match.
|
||||||
|
@ -79,7 +92,7 @@ public class WebSocketUpgradeHandlerWrapper extends HandlerWrapper implements Ma
|
||||||
request.setAttribute(PathSpec.class.getName(),resource);
|
request.setAttribute(PathSpec.class.getName(),resource);
|
||||||
|
|
||||||
// We have an upgrade request
|
// We have an upgrade request
|
||||||
if (factory.acceptWebSocket(creator,request,response))
|
if (configuration.getFactory().acceptWebSocket(creator,request,response))
|
||||||
{
|
{
|
||||||
// We have a socket instance created
|
// We have a socket instance created
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.eclipse.jetty.websocket.server.NativeWebSocketServletContainerInitializer
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
|
public class InfoContextAltAttributeListener implements WebSocketCreator, ServletContextListener
|
||||||
|
{
|
||||||
|
private static final String ATTR = "alt.config";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(sce.getServletContext());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), this);
|
||||||
|
sce.getServletContext().setAttribute(ATTR, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
return new InfoSocket();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
|
public class InfoContextAttributeListener implements WebSocketCreator, ServletContextListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) sce.getServletContext().getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
return new InfoSocket();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
|
public class InfoContextListener implements WebSocketCreator, ServletContextListener
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(sce.getServletContext());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), this);
|
||||||
|
sce.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
return new InfoSocket();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
|
||||||
|
public class InfoServlet extends HttpServlet implements WebSocketCreator
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
return new InfoSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws ServletException
|
||||||
|
{
|
||||||
|
ServletContext context = config.getServletContext();
|
||||||
|
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,23 +18,27 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.server;
|
package org.eclipse.jetty.websocket.server;
|
||||||
|
|
||||||
import org.eclipse.jetty.http.pathmap.PathMappings;
|
import org.eclipse.jetty.websocket.api.RemoteEndpoint;
|
||||||
import org.eclipse.jetty.http.pathmap.PathSpec;
|
import org.eclipse.jetty.websocket.api.Session;
|
||||||
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
|
||||||
|
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
|
||||||
|
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
|
||||||
|
|
||||||
public class DefaultMappedWebSocketCreator implements MappedWebSocketCreator
|
@WebSocket
|
||||||
|
public class InfoSocket
|
||||||
{
|
{
|
||||||
private final PathMappings<WebSocketCreator> mappings = new PathMappings<>();
|
private Session session;
|
||||||
|
|
||||||
@Override
|
@OnWebSocketConnect
|
||||||
public void addMapping(PathSpec spec, WebSocketCreator creator)
|
public void onConnect(Session session)
|
||||||
{
|
{
|
||||||
this.mappings.put(spec, creator);
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@OnWebSocketMessage
|
||||||
public PathMappings<WebSocketCreator> getMappings()
|
public void onMessage(String msg)
|
||||||
{
|
{
|
||||||
return this.mappings;
|
RemoteEndpoint remote = this.session.getRemote();
|
||||||
|
remote.sendStringByFuture("session.maxTextMessageSize=" + session.getPolicy().getMaxTextMessageSize());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,204 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||||
|
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||||
|
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||||
|
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||||
|
import org.eclipse.jetty.toolchain.test.FS;
|
||||||
|
import org.eclipse.jetty.toolchain.test.IO;
|
||||||
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
|
import org.eclipse.jetty.toolchain.test.OS;
|
||||||
|
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.webapp.Configuration;
|
||||||
|
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility to build out exploded directory WebApps, in the /target/tests/ directory, for testing out servers that use javax.websocket endpoints.
|
||||||
|
* <p>
|
||||||
|
* This is particularly useful when the WebSocket endpoints are discovered via the javax.websocket annotation scanning.
|
||||||
|
*/
|
||||||
|
public class WSServer
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(WSServer.class);
|
||||||
|
private final File contextDir;
|
||||||
|
private final String contextPath;
|
||||||
|
private Server server;
|
||||||
|
private URI serverUri;
|
||||||
|
private ContextHandlerCollection contexts;
|
||||||
|
private File webinf;
|
||||||
|
private File classesDir;
|
||||||
|
|
||||||
|
public WSServer(TestingDir testdir, String contextName)
|
||||||
|
{
|
||||||
|
this(testdir.getDir(),contextName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WSServer(File testdir, String contextName)
|
||||||
|
{
|
||||||
|
this.contextDir = new File(testdir,contextName);
|
||||||
|
this.contextPath = "/" + contextName;
|
||||||
|
FS.ensureEmpty(contextDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyClass(Class<?> clazz) throws Exception
|
||||||
|
{
|
||||||
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
|
String endpointPath = clazz.getName().replace('.','/') + ".class";
|
||||||
|
URL classUrl = cl.getResource(endpointPath);
|
||||||
|
Assert.assertThat("Class URL for: " + clazz,classUrl,notNullValue());
|
||||||
|
File destFile = new File(classesDir,OS.separators(endpointPath));
|
||||||
|
FS.ensureDirExists(destFile.getParentFile());
|
||||||
|
File srcFile = new File(classUrl.toURI());
|
||||||
|
IO.copy(srcFile,destFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyEndpoint(Class<?> endpointClass) throws Exception
|
||||||
|
{
|
||||||
|
copyClass(endpointClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void copyWebInf(String testResourceName) throws IOException
|
||||||
|
{
|
||||||
|
webinf = new File(contextDir,"WEB-INF");
|
||||||
|
FS.ensureDirExists(webinf);
|
||||||
|
classesDir = new File(webinf,"classes");
|
||||||
|
FS.ensureDirExists(classesDir);
|
||||||
|
File webxml = new File(webinf,"web.xml");
|
||||||
|
File testWebXml = MavenTestingUtils.getTestResourceFile(testResourceName);
|
||||||
|
IO.copy(testWebXml,webxml);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebAppContext createWebAppContext() throws MalformedURLException, IOException
|
||||||
|
{
|
||||||
|
WebAppContext context = new WebAppContext();
|
||||||
|
context.setContextPath(this.contextPath);
|
||||||
|
context.setBaseResource(Resource.newResource(this.contextDir));
|
||||||
|
context.setAttribute("org.eclipse.jetty.websocket.jsr356",Boolean.TRUE);
|
||||||
|
|
||||||
|
// @formatter:off
|
||||||
|
context.setConfigurations(new Configuration[] {
|
||||||
|
new AnnotationConfiguration(),
|
||||||
|
new WebXmlConfiguration(),
|
||||||
|
new WebInfConfiguration(),
|
||||||
|
new PlusConfiguration(),
|
||||||
|
new MetaInfConfiguration(),
|
||||||
|
new FragmentConfiguration(),
|
||||||
|
new EnvConfiguration()});
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createWebInf() throws IOException
|
||||||
|
{
|
||||||
|
copyWebInf("empty-web.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deployWebapp(WebAppContext webapp) throws Exception
|
||||||
|
{
|
||||||
|
contexts.addHandler(webapp);
|
||||||
|
contexts.manage(webapp);
|
||||||
|
webapp.start();
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
webapp.dump(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump()
|
||||||
|
{
|
||||||
|
server.dumpStdErr();
|
||||||
|
}
|
||||||
|
|
||||||
|
public URI getServerBaseURI()
|
||||||
|
{
|
||||||
|
return serverUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Server getServer()
|
||||||
|
{
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWebAppDir()
|
||||||
|
{
|
||||||
|
return this.contextDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() throws Exception
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
HandlerCollection handlers = new HandlerCollection();
|
||||||
|
contexts = new ContextHandlerCollection();
|
||||||
|
handlers.addHandler(contexts);
|
||||||
|
server.setHandler(handlers);
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
String host = connector.getHost();
|
||||||
|
if (host == null)
|
||||||
|
{
|
||||||
|
host = "localhost";
|
||||||
|
}
|
||||||
|
int port = connector.getLocalPort();
|
||||||
|
serverUri = new URI(String.format("ws://%s:%d%s/",host,port,contextPath));
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Server started on {}",serverUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
if (server != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace(System.err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2016 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.websocket.server;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.servlet.DispatcherType;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.pathmap.ServletPathSpec;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.ServerConnector;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.toolchain.test.EventQueue;
|
||||||
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||||
|
import org.eclipse.jetty.websocket.common.frames.TextFrame;
|
||||||
|
import org.eclipse.jetty.websocket.common.test.BlockheadClient;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
|
@RunWith(Parameterized.class)
|
||||||
|
public class WebSocketUpgradeFilterTest
|
||||||
|
{
|
||||||
|
interface ServerProvider
|
||||||
|
{
|
||||||
|
Server newServer() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
public static List<Object[]> data()
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Case A:
|
||||||
|
* 1. embedded-jetty WSUF.configureContext() / app-ws configured at ...
|
||||||
|
* a. during server construction / before server.start (might not be possible with current impl, native SCI not run (yet))
|
||||||
|
* might require NativeSCI.getDefaultFrom() first
|
||||||
|
* b. during server construction / after server.start
|
||||||
|
* c. during server start / via CustomServlet.init()
|
||||||
|
* 2. embedded-jetty WSUF addFilter / app-ws configured at server construction (before server.start)
|
||||||
|
* Case B:
|
||||||
|
* 1. web.xml WSUF / app-ws configured in CustomServlet.init() load-on-start
|
||||||
|
* Case C:
|
||||||
|
* 1. embedded-jetty WSUF.configureContext() / app-ws configured via ServletContextListener.contextInitialized
|
||||||
|
* 2. embedded-jetty WSUF addFilter / app-ws configured via ServletContextListener.contextInitialized
|
||||||
|
* Case D:
|
||||||
|
* 1. web.xml WSUF / app-ws configured via ServletContextListener.contextInitialized
|
||||||
|
*
|
||||||
|
* Every "app-ws configured" means it should access/set ws policy and add ws mappings
|
||||||
|
*/
|
||||||
|
|
||||||
|
final WebSocketCreator infoCreator = new WebSocketCreator()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp)
|
||||||
|
{
|
||||||
|
return new InfoSocket();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
List<Object[]> cases = new ArrayList<>();
|
||||||
|
|
||||||
|
// Embedded WSUF.configureContext(), directly app-ws configuration
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf.configureContext/Direct configure", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
ServletContextHandler context = new ServletContextHandler();
|
||||||
|
context.setContextPath("/");
|
||||||
|
server.setHandler(context);
|
||||||
|
|
||||||
|
WebSocketUpgradeFilter wsuf = WebSocketUpgradeFilter.configureContext(context);
|
||||||
|
|
||||||
|
// direct configuration via WSUF
|
||||||
|
wsuf.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
wsuf.addMapping(new ServletPathSpec("/info/*"), infoCreator);
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Embedded WSUF.configureContext(), apply app-ws configuration via attribute
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf.configureContext/Attribute based configure", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
ServletContextHandler context = new ServletContextHandler();
|
||||||
|
context.setContextPath("/");
|
||||||
|
server.setHandler(context);
|
||||||
|
|
||||||
|
WebSocketUpgradeFilter.configureContext(context);
|
||||||
|
|
||||||
|
// configuration via attribute
|
||||||
|
NativeWebSocketConfiguration configuration = (NativeWebSocketConfiguration) context.getServletContext().getAttribute(NativeWebSocketConfiguration.class.getName());
|
||||||
|
assertThat("NativeWebSocketConfiguration", configuration, notNullValue());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), infoCreator);
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Embedded WSUF, added as filter, apply app-ws configuration via attribute
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf/addFilter/Attribute based configure", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
ServletContextHandler context = new ServletContextHandler();
|
||||||
|
context.setContextPath("/");
|
||||||
|
server.setHandler(context);
|
||||||
|
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||||
|
|
||||||
|
NativeWebSocketConfiguration configuration = new NativeWebSocketConfiguration(context.getServletContext());
|
||||||
|
configuration.getFactory().getPolicy().setMaxTextMessageSize(10 * 1024 * 1024);
|
||||||
|
configuration.addMapping(new ServletPathSpec("/info/*"), infoCreator);
|
||||||
|
context.getServletContext().setAttribute(NativeWebSocketConfiguration.class.getName(), configuration);
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// Embedded WSUF, added as filter, apply app-ws configuration via ServletContextListener
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf.configureContext/ServletContextListener configure", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
Server server = new Server();
|
||||||
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
connector.setPort(0);
|
||||||
|
server.addConnector(connector);
|
||||||
|
|
||||||
|
ServletContextHandler context = new ServletContextHandler();
|
||||||
|
context.setContextPath("/");
|
||||||
|
server.setHandler(context);
|
||||||
|
context.addFilter(WebSocketUpgradeFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||||
|
context.addEventListener(new InfoContextListener());
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// WSUF from web.xml, SCI active, apply app-ws configuration via ServletContextListener
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
|
||||||
|
|
||||||
|
WSServer server = new WSServer(testDir, "/");
|
||||||
|
|
||||||
|
server.copyWebInf("wsuf-config-via-listener.xml");
|
||||||
|
server.copyClass(InfoSocket.class);
|
||||||
|
server.copyClass(InfoContextAttributeListener.class);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
WebAppContext webapp = server.createWebAppContext();
|
||||||
|
server.deployWebapp(webapp);
|
||||||
|
|
||||||
|
return server.getServer();
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// WSUF from web.xml, SCI active, apply app-ws configuration via Servlet.init
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/Servlet.init", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
|
||||||
|
|
||||||
|
WSServer server = new WSServer(testDir, "/");
|
||||||
|
|
||||||
|
server.copyWebInf("wsuf-config-via-servlet-init.xml");
|
||||||
|
server.copyClass(InfoSocket.class);
|
||||||
|
server.copyClass(InfoServlet.class);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
WebAppContext webapp = server.createWebAppContext();
|
||||||
|
server.deployWebapp(webapp);
|
||||||
|
|
||||||
|
return server.getServer();
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
// xml based, wsuf, on alternate url-pattern and config attribute location
|
||||||
|
|
||||||
|
cases.add(new Object[]{"wsuf/WebAppContext/web.xml/ServletContextListener/alt-config", new ServerProvider()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public Server newServer() throws Exception
|
||||||
|
{
|
||||||
|
File testDir = MavenTestingUtils.getTargetTestingDir("WSUF-webxml");
|
||||||
|
|
||||||
|
WSServer server = new WSServer(testDir, "/");
|
||||||
|
|
||||||
|
server.copyWebInf("wsuf-alt-config-via-listener.xml");
|
||||||
|
server.copyClass(InfoSocket.class);
|
||||||
|
server.copyClass(InfoContextAltAttributeListener.class);
|
||||||
|
server.start();
|
||||||
|
|
||||||
|
WebAppContext webapp = server.createWebAppContext();
|
||||||
|
server.deployWebapp(webapp);
|
||||||
|
|
||||||
|
return server.getServer();
|
||||||
|
}
|
||||||
|
}});
|
||||||
|
|
||||||
|
return cases;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Server server;
|
||||||
|
private final URI serverUri;
|
||||||
|
|
||||||
|
public WebSocketUpgradeFilterTest(String testId, ServerProvider serverProvider) throws Exception
|
||||||
|
{
|
||||||
|
this.server = serverProvider.newServer();
|
||||||
|
|
||||||
|
ServerConnector connector = (ServerConnector) server.getConnectors()[0];
|
||||||
|
|
||||||
|
// Establish the Server URI
|
||||||
|
String host = connector.getHost();
|
||||||
|
if (host == null)
|
||||||
|
{
|
||||||
|
host = "localhost";
|
||||||
|
}
|
||||||
|
int port = connector.getLocalPort();
|
||||||
|
|
||||||
|
serverUri = new URI(String.format("ws://%s:%d/", host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfiguration() throws Exception
|
||||||
|
{
|
||||||
|
URI destUri = serverUri.resolve("/info/");
|
||||||
|
|
||||||
|
try (BlockheadClient client = new BlockheadClient(destUri))
|
||||||
|
{
|
||||||
|
client.connect();
|
||||||
|
client.sendStandardRequest();
|
||||||
|
client.expectUpgradeResponse();
|
||||||
|
|
||||||
|
client.write(new TextFrame().setPayload("hello"));
|
||||||
|
|
||||||
|
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1000, TimeUnit.MILLISECONDS);
|
||||||
|
String payload = frames.poll().getPayloadAsUTF8();
|
||||||
|
|
||||||
|
// If we can connect and send a text message, we know that the endpoint was
|
||||||
|
// added properly, and the response will help us verify the policy configuration too
|
||||||
|
assertThat("payload", payload, containsString("session.maxTextMessageSize=" + (10 * 1024 * 1024)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||||
|
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<listener>
|
||||||
|
<listener-class>org.eclipse.jetty.websocket.server.InfoContextAltAttributeListener</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
<init-param>
|
||||||
|
<param-name>configAttributeKey</param-name>
|
||||||
|
<param-value>alt.config</param-value>
|
||||||
|
</init-param>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>wsuf-alt</filter-name>
|
||||||
|
<url-pattern>/info/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||||
|
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<listener>
|
||||||
|
<listener-class>org.eclipse.jetty.websocket.server.InfoContextAttributeListener</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>wsuf</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>wsuf</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app
|
||||||
|
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||||
|
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
|
version="3.1">
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>info-servlet</servlet-name>
|
||||||
|
<servlet-class>org.eclipse.jetty.websocket.server.InfoServlet</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>wsuf</filter-name>
|
||||||
|
<filter-class>org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>wsuf</filter-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
</web-app>
|
|
@ -90,7 +90,14 @@ public abstract class WebSocketServlet extends HttpServlet
|
||||||
@Override
|
@Override
|
||||||
public void destroy()
|
public void destroy()
|
||||||
{
|
{
|
||||||
factory.cleanup();
|
try
|
||||||
|
{
|
||||||
|
factory.stop();
|
||||||
|
}
|
||||||
|
catch (Exception ignore)
|
||||||
|
{
|
||||||
|
// ignore;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,13 +134,12 @@ public abstract class WebSocketServlet extends HttpServlet
|
||||||
policy.setInputBufferSize(Integer.parseInt(max));
|
policy.setInputBufferSize(Integer.parseInt(max));
|
||||||
}
|
}
|
||||||
|
|
||||||
factory = WebSocketServletFactory.Loader.create(policy);
|
ServletContext ctx = getServletContext();
|
||||||
|
factory = WebSocketServletFactory.Loader.load(ctx, policy);
|
||||||
|
|
||||||
configure(factory);
|
configure(factory);
|
||||||
|
|
||||||
ServletContext ctx = getServletContext();
|
factory.start();
|
||||||
|
|
||||||
factory.init(ctx);
|
|
||||||
|
|
||||||
ctx.setAttribute(WebSocketServletFactory.class.getName(),factory);
|
ctx.setAttribute(WebSocketServletFactory.class.getName(),factory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
package org.eclipse.jetty.websocket.servlet;
|
package org.eclipse.jetty.websocket.servlet;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.lang.reflect.Constructor;
|
||||||
import java.util.ServiceLoader;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -35,54 +35,40 @@ import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||||
*/
|
*/
|
||||||
public interface WebSocketServletFactory
|
public interface WebSocketServletFactory
|
||||||
{
|
{
|
||||||
public static class Loader
|
class Loader
|
||||||
{
|
{
|
||||||
private static WebSocketServletFactory INSTANCE;
|
final static String DEFAULT_IMPL = "org.eclipse.jetty.websocket.server.WebSocketServerFactory";
|
||||||
|
|
||||||
public static WebSocketServletFactory create(WebSocketPolicy policy) throws ClassNotFoundException, InstantiationException, IllegalAccessException
|
public static WebSocketServletFactory load(ServletContext ctx, WebSocketPolicy policy)
|
||||||
{
|
{
|
||||||
return load().createFactory(policy);
|
try
|
||||||
}
|
|
||||||
|
|
||||||
public static WebSocketServletFactory load() throws ClassNotFoundException, InstantiationException, IllegalAccessException
|
|
||||||
{
|
|
||||||
if (INSTANCE != null)
|
|
||||||
{
|
{
|
||||||
return INSTANCE;
|
Class<? extends WebSocketServletFactory> wsClazz =
|
||||||
|
(Class<? extends WebSocketServletFactory>) Class.forName(DEFAULT_IMPL);
|
||||||
|
Constructor<? extends WebSocketServletFactory> ctor = wsClazz.getDeclaredConstructor(new Class<?>[]{ServletContext.class, WebSocketPolicy.class});
|
||||||
|
return ctor.newInstance(ctx, policy);
|
||||||
}
|
}
|
||||||
WebSocketServletFactory baseFactory;
|
catch (ClassNotFoundException e)
|
||||||
Iterator<WebSocketServletFactory> factories = ServiceLoader.load(WebSocketServletFactory.class).iterator();
|
|
||||||
|
|
||||||
if (factories.hasNext())
|
|
||||||
{
|
{
|
||||||
baseFactory = factories.next();
|
throw new RuntimeException("Unable to load " + DEFAULT_IMPL, e);
|
||||||
}
|
}
|
||||||
else
|
catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e)
|
||||||
{
|
{
|
||||||
// Load the default class if ServiceLoader mechanism isn't valid in this environment. (such as OSGi)
|
throw new RuntimeException("Unable to instantiate " + DEFAULT_IMPL, e);
|
||||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Class<WebSocketServletFactory> wssf = (Class<WebSocketServletFactory>)loader
|
|
||||||
.loadClass("org.eclipse.jetty.websocket.server.WebSocketServerFactory");
|
|
||||||
baseFactory = wssf.newInstance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANCE = baseFactory;
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException;
|
boolean acceptWebSocket(HttpServletRequest request, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
public boolean acceptWebSocket(WebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException;
|
boolean acceptWebSocket(WebSocketCreator creator, HttpServletRequest request, HttpServletResponse response) throws IOException;
|
||||||
|
|
||||||
public void cleanup();
|
void start() throws Exception;
|
||||||
|
void stop() throws Exception;
|
||||||
|
|
||||||
public WebSocketServletFactory createFactory(WebSocketPolicy policy);
|
WebSocketCreator getCreator();
|
||||||
|
|
||||||
public abstract WebSocketCreator getCreator();
|
ExtensionFactory getExtensionFactory();
|
||||||
|
|
||||||
public abstract ExtensionFactory getExtensionFactory();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the base policy in use for WebSockets.
|
* Get the base policy in use for WebSockets.
|
||||||
|
@ -91,21 +77,18 @@ public interface WebSocketServletFactory
|
||||||
*
|
*
|
||||||
* @return the base policy
|
* @return the base policy
|
||||||
*/
|
*/
|
||||||
public WebSocketPolicy getPolicy();
|
WebSocketPolicy getPolicy();
|
||||||
|
|
||||||
public void init(ServletContext servletContext) throws Exception;
|
boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response);
|
||||||
|
|
||||||
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a websocket class pojo with the default {@link WebSocketCreator}.
|
* Register a websocket class pojo with the default {@link WebSocketCreator}.
|
||||||
* <p>
|
* <p>
|
||||||
* Note: only required if using the default {@link WebSocketCreator} provided by this factory.
|
* Note: only required if using the default {@link WebSocketCreator} provided by this factory.
|
||||||
*
|
*
|
||||||
* @param websocketPojo
|
* @param websocketPojo the class to instantiate for each incoming websocket upgrade request.
|
||||||
* the class to instantiate for each incoming websocket upgrade request.
|
|
||||||
*/
|
*/
|
||||||
public void register(Class<?> websocketPojo);
|
void register(Class<?> websocketPojo);
|
||||||
|
|
||||||
public abstract void setCreator(WebSocketCreator creator);
|
void setCreator(WebSocketCreator creator);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue