Merge remote-tracking branch 'origin/master' into jetty-8
This commit is contained in:
commit
17269583fb
|
@ -37,6 +37,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
{
|
||||
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
|
||||
|
||||
private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase().contains("win");
|
||||
private final SelectorManager.SelectSet _selectSet;
|
||||
private final SelectorManager _manager;
|
||||
private SelectionKey _key;
|
||||
|
@ -681,15 +682,23 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
try
|
||||
// On unix systems there is a JVM issue that if you cancel before closing, it can
|
||||
// cause the selector to block waiting for a channel to close and that channel can
|
||||
// block waiting for the remote end. But on windows, if you don't cancel before a
|
||||
// close, then the selector can block anyway!
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318
|
||||
if (WORK_AROUND_JVM_BUG_6346658)
|
||||
{
|
||||
SelectionKey key = _key;
|
||||
if (key!=null)
|
||||
key.cancel();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
try
|
||||
{
|
||||
SelectionKey key = _key;
|
||||
if (key!=null)
|
||||
key.cancel();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
-->
|
||||
<!--
|
||||
<Call name="createRegistry" class="java.rmi.registry.LocateRegistry">
|
||||
<Arg type="java.lang.Integer">1099</Arg>
|
||||
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
|
||||
<Call name="sleep" class="java.lang.Thread">
|
||||
<Arg type="java.lang.Integer">1000</Arg>
|
||||
</Call>
|
||||
|
@ -91,11 +91,11 @@
|
|||
<New class="javax.management.remote.JMXServiceURL">
|
||||
<Arg type="java.lang.String">rmi</Arg>
|
||||
<Arg type="java.lang.String" />
|
||||
<Arg type="java.lang.Integer">0</Arg>
|
||||
<Arg type="java.lang.String">/jndi/rmi://localhost:1099/jettyjmx</Arg>
|
||||
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
|
||||
<Arg type="java.lang.String">/jndi/rmi://<SystemProperty name="jetty.jmxrmihost" default="localhost"/>:<SystemProperty name="jetty.jmxrmiport" default="1099"/>/jmxrmi</Arg>
|
||||
</New>
|
||||
</Arg>
|
||||
<Arg>org.eclipse.jetty:name=rmiconnectorserver</Arg>
|
||||
<Arg>org.eclipse.jetty.jmx:name=rmiconnectorserver</Arg>
|
||||
<Call name="start" />
|
||||
</New>
|
||||
-->
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.osgi.framework.BundleContext;
|
|||
public class DefaultJettyAtJettyHomeHelper {
|
||||
private static final Logger LOG = Log.getLogger(DefaultJettyAtJettyHomeHelper.class);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* contains a comma separated list of pathes to the etc/jetty-*.xml files
|
||||
* used to configure jetty. By default the value is 'etc/jetty.xml' when the
|
||||
|
@ -69,7 +69,7 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
* Usual system property used as the port for https for a typical jetty configuration.
|
||||
*/
|
||||
public static final String SYS_PROP_JETTY_PORT_SSL = "jetty.port.ssl";
|
||||
|
||||
|
||||
/**
|
||||
* Called by the JettyBootStrapActivator.
|
||||
* If the system property jetty.home is defined and points to a folder,
|
||||
|
@ -88,81 +88,76 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
* that might use them as part of their properties.
|
||||
* </p>
|
||||
*/
|
||||
public static void startJettyAtJettyHome(BundleContext bundleContext)
|
||||
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
|
||||
{
|
||||
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
|
||||
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
|
||||
File jettyHome = null;
|
||||
Bundle jettyHomeBundle = null;
|
||||
if (jettyHomeSysProp != null)
|
||||
{
|
||||
jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp);
|
||||
//bug 329621
|
||||
if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"")
|
||||
|| (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'"))) {
|
||||
jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
|
||||
}
|
||||
if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
LOG.warn("Both the jetty.home property and the jetty.home.bundle property are defined."
|
||||
+ " jetty.home.bundle is not taken into account.");
|
||||
}
|
||||
jettyHome = new File(jettyHomeSysProp);
|
||||
if (!jettyHome.exists() || !jettyHome.isDirectory())
|
||||
{
|
||||
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
for (Bundle b : bundleContext.getBundles())
|
||||
{
|
||||
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
|
||||
{
|
||||
jettyHomeBundle = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
if (jettyHome == null && jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("No default jetty started.");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
Server server = new Server();
|
||||
Dictionary properties = new Hashtable();
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
|
||||
|
||||
String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
|
||||
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
|
||||
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
|
||||
File jettyHome = null;
|
||||
Bundle jettyHomeBundle = null;
|
||||
if (jettyHomeSysProp != null)
|
||||
{
|
||||
jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp);
|
||||
//bug 329621
|
||||
if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"")
|
||||
|| (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'"))) {
|
||||
jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
|
||||
}
|
||||
if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
LOG.warn("Both the jetty.home property and the jetty.home.bundle property are defined."
|
||||
+ " jetty.home.bundle is not taken into account.");
|
||||
}
|
||||
jettyHome = new File(jettyHomeSysProp);
|
||||
if (!jettyHome.exists() || !jettyHome.isDirectory())
|
||||
{
|
||||
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (jettyHomeBundleSysProp != null)
|
||||
{
|
||||
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
|
||||
for (Bundle b : bundleContext.getBundles())
|
||||
{
|
||||
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
|
||||
{
|
||||
jettyHomeBundle = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.info("Configuring the default jetty server with " + configURLs);
|
||||
|
||||
//these properties usually are the ones passed to this type of configuration.
|
||||
setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
|
||||
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
|
||||
}
|
||||
if (jettyHome == null && jettyHomeBundle == null)
|
||||
{
|
||||
LOG.warn("No default jetty started.");
|
||||
return;
|
||||
}
|
||||
|
||||
Server server = new Server();
|
||||
Dictionary properties = new Hashtable();
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
|
||||
|
||||
String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
|
||||
properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
|
||||
|
||||
LOG.info("Configuring the default jetty server with " + configURLs);
|
||||
|
||||
//these properties usually are the ones passed to this type of configuration.
|
||||
setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
|
||||
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
|
||||
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
|
||||
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
// hookNestedConnectorToBridgeServlet(server);
|
||||
|
||||
bundleContext.registerService(Server.class.getName(), server, properties);
|
||||
// hookNestedConnectorToBridgeServlet(server);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Minimum setup for the location of the configuration files given a jettyhome folder.
|
||||
* Reads the system property jetty.etc.config.urls and look for the corresponding jetty
|
||||
|
@ -172,22 +167,22 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
*/
|
||||
private static String getJettyConfigurationURLs(File jettyhome)
|
||||
{
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
|
||||
StringBuilder res = new StringBuilder();
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String next = tokenizer.nextToken().trim();
|
||||
if (!next.startsWith("/") && next.indexOf(':') == -1)
|
||||
{
|
||||
try {
|
||||
next = new File(jettyhome, next).toURI().toURL().toString();
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
appendToCommaSeparatedList(res, next);
|
||||
String next = tokenizer.nextToken().trim();
|
||||
if (!next.startsWith("/") && next.indexOf(':') == -1)
|
||||
{
|
||||
try {
|
||||
next = new File(jettyhome, next).toURI().toURL().toString();
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
appendToCommaSeparatedList(res, next);
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
@ -202,108 +197,108 @@ public class DefaultJettyAtJettyHomeHelper {
|
|||
*/
|
||||
private static String getJettyConfigurationURLs(Bundle configurationBundle)
|
||||
{
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
|
||||
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
|
||||
StringBuilder res = new StringBuilder();
|
||||
|
||||
|
||||
while (tokenizer.hasMoreTokens())
|
||||
{
|
||||
String etcFile = tokenizer.nextToken().trim();
|
||||
if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1)
|
||||
{
|
||||
appendToCommaSeparatedList(res, etcFile);
|
||||
appendToCommaSeparatedList(res, etcFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, etcFile);
|
||||
|
||||
//default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration.
|
||||
//default inside jettyhome. this way fragments to the bundle can define their own configuration.
|
||||
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
|
||||
{
|
||||
enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
|
||||
System.err.println("Configuring jetty with the default embedded configuration:" +
|
||||
"bundle: " + configurationBundle.getSymbolicName() +
|
||||
" config: /jettyhome/etc/jetty-osgi-default.xml");
|
||||
}
|
||||
if (enUrls == null || !enUrls.hasMoreElements())
|
||||
{
|
||||
System.err.println("Unable to locate a jetty configuration file for " + etcFile);
|
||||
}
|
||||
if (enUrls != null)
|
||||
{
|
||||
while (enUrls.hasMoreElements())
|
||||
{
|
||||
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
|
||||
}
|
||||
}
|
||||
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, etcFile);
|
||||
|
||||
//default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration.
|
||||
//default inside jettyhome. this way fragments to the bundle can define their own configuration.
|
||||
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
|
||||
{
|
||||
enUrls = BundleFileLocatorHelper.DEFAULT
|
||||
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
|
||||
System.err.println("Configuring jetty with the default embedded configuration:" +
|
||||
"bundle: " + configurationBundle.getSymbolicName() +
|
||||
" config: /jettyhome/etc/jetty-osgi-default.xml");
|
||||
}
|
||||
if (enUrls == null || !enUrls.hasMoreElements())
|
||||
{
|
||||
System.err.println("Unable to locate a jetty configuration file for " + etcFile);
|
||||
}
|
||||
if (enUrls != null)
|
||||
{
|
||||
while (enUrls.hasMoreElements())
|
||||
{
|
||||
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
|
||||
{
|
||||
if (buffer.length() != 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
private static void setProperty(Dictionary properties, String key, String value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
properties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively substitute the ${sysprop} by their actual system property.
|
||||
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no sysprop is defined.
|
||||
* Not the most efficient code but we are shooting for simplicity and speed of development here.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String resolvePropertyValue(String value)
|
||||
{
|
||||
int ind = value.indexOf("${");
|
||||
if (ind == -1) {
|
||||
return value;
|
||||
}
|
||||
int ind2 = value.indexOf('}', ind);
|
||||
if (ind2 == -1) {
|
||||
return value;
|
||||
}
|
||||
String sysprop = value.substring(ind+2, ind2);
|
||||
String defaultValue = null;
|
||||
int comma = sysprop.indexOf(',');
|
||||
if (comma != -1 && comma+1 != sysprop.length())
|
||||
{
|
||||
defaultValue = sysprop.substring(comma+1);
|
||||
defaultValue = resolvePropertyValue(defaultValue);
|
||||
sysprop = sysprop.substring(0,comma);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = "${" + sysprop + "}";
|
||||
}
|
||||
|
||||
String v = System.getProperty(sysprop);
|
||||
|
||||
String reminder = value.length() > ind2 + 1 ? value.substring(ind2+1) : "";
|
||||
reminder = resolvePropertyValue(reminder);
|
||||
if (v != null)
|
||||
{
|
||||
return value.substring(0, ind) + v + reminder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value.substring(0, ind) + defaultValue + reminder;
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
|
||||
{
|
||||
if (buffer.length() != 0)
|
||||
{
|
||||
buffer.append(",");
|
||||
}
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
private static void setProperty(Dictionary properties, String key, String value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
properties.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively substitute the ${sysprop} by their actual system property.
|
||||
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no sysprop is defined.
|
||||
* Not the most efficient code but we are shooting for simplicity and speed of development here.
|
||||
*
|
||||
* @param value
|
||||
* @return
|
||||
*/
|
||||
public static String resolvePropertyValue(String value)
|
||||
{
|
||||
int ind = value.indexOf("${");
|
||||
if (ind == -1) {
|
||||
return value;
|
||||
}
|
||||
int ind2 = value.indexOf('}', ind);
|
||||
if (ind2 == -1) {
|
||||
return value;
|
||||
}
|
||||
String sysprop = value.substring(ind+2, ind2);
|
||||
String defaultValue = null;
|
||||
int comma = sysprop.indexOf(',');
|
||||
if (comma != -1 && comma+1 != sysprop.length())
|
||||
{
|
||||
defaultValue = sysprop.substring(comma+1);
|
||||
defaultValue = resolvePropertyValue(defaultValue);
|
||||
sysprop = sysprop.substring(0,comma);
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = "${" + sysprop + "}";
|
||||
}
|
||||
|
||||
String v = System.getProperty(sysprop);
|
||||
|
||||
String reminder = value.length() > ind2 + 1 ? value.substring(ind2+1) : "";
|
||||
reminder = resolvePropertyValue(reminder);
|
||||
if (v != null)
|
||||
{
|
||||
return value.substring(0, ind) + v + reminder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return value.substring(0, ind) + defaultValue + reminder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,50 +18,53 @@ import java.util.Properties;
|
|||
|
||||
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.ServiceEvent;
|
||||
import org.osgi.framework.ServiceListener;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
|
||||
/**
|
||||
* Deploy the jetty server instances when they are registered as an OSGi service.
|
||||
* Deploy the jetty server instances when they are registered as an OSGi
|
||||
* service.
|
||||
*/
|
||||
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
|
||||
{
|
||||
|
||||
private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName());
|
||||
|
||||
/**
|
||||
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service.
|
||||
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin
|
||||
* service.
|
||||
*/
|
||||
private Map<String, ServerInstanceWrapper> _serversIndexedByName = new HashMap<String, ServerInstanceWrapper>();
|
||||
|
||||
/** The context-handler to deactivate indexed by ServerInstanceWrapper */
|
||||
private Map<ServiceReference, ServerInstanceWrapper> _indexByServiceReference = new HashMap<ServiceReference, ServerInstanceWrapper>();
|
||||
|
||||
|
||||
/**
|
||||
* Stops each one of the registered servers.
|
||||
*/
|
||||
public void stop()
|
||||
{
|
||||
//not sure that this is really useful but here we go.
|
||||
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
wrapper.stop();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
// not sure that this is really useful but here we go.
|
||||
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
wrapper.stop();
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
LOG.warn(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receives notification that a service has had a lifecycle change.
|
||||
*
|
||||
* @param ev
|
||||
* The <code>ServiceEvent</code> object.
|
||||
* @param ev The <code>ServiceEvent</code> object.
|
||||
*/
|
||||
public void serviceChanged(ServiceEvent ev)
|
||||
{
|
||||
|
@ -71,17 +74,16 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
case ServiceEvent.MODIFIED:
|
||||
case ServiceEvent.UNREGISTERING:
|
||||
{
|
||||
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
|
||||
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
|
||||
if (instance != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
instance.stop();
|
||||
instance.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,32 +98,35 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
}
|
||||
case ServiceEvent.REGISTERED:
|
||||
{
|
||||
Bundle contributor = sr.getBundle();
|
||||
Server server = (Server)contributor.getBundleContext().getService(sr);
|
||||
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
|
||||
Properties props = new Properties();
|
||||
for (String key : sr.getPropertyKeys())
|
||||
{
|
||||
Object value = sr.getProperty(key);
|
||||
props.put(key, value);
|
||||
}
|
||||
wrapper.start(server, props);
|
||||
break;
|
||||
try
|
||||
{
|
||||
Bundle contributor = sr.getBundle();
|
||||
Server server = (Server) contributor.getBundleContext().getService(sr);
|
||||
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
|
||||
Properties props = new Properties();
|
||||
for (String key : sr.getPropertyKeys())
|
||||
{
|
||||
Object value = sr.getProperty(key);
|
||||
props.put(key, value);
|
||||
}
|
||||
wrapper.start(server, props);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr)
|
||||
{
|
||||
String name = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
if (name == null)
|
||||
{
|
||||
throw new IllegalArgumentException("The property " +
|
||||
OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory");
|
||||
}
|
||||
String name = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
if (name == null) { throw new IllegalArgumentException("The property " + OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory"); }
|
||||
ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name);
|
||||
_indexByServiceReference.put(sr,wrapper);
|
||||
_serversIndexedByName.put(name,wrapper);
|
||||
_indexByServiceReference.put(sr, wrapper);
|
||||
_serversIndexedByName.put(name, wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
|
@ -133,7 +138,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
*/
|
||||
private ServerInstanceWrapper unregisterInIndex(ServiceReference sr)
|
||||
{
|
||||
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
|
||||
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
|
||||
if (handler == null)
|
||||
{
|
||||
// a warning?
|
||||
|
@ -149,13 +154,12 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
|
|||
|
||||
/**
|
||||
* @param managedServerName The server name
|
||||
* @return the corresponding jetty server wrapped with its deployment properties.
|
||||
* @return the corresponding jetty server wrapped with its deployment
|
||||
* properties.
|
||||
*/
|
||||
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
|
||||
{
|
||||
return _serversIndexedByName.get(managedServerName == null
|
||||
? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
|
||||
return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -99,14 +99,21 @@ public class JettyServersManagedFactory implements ManagedServiceFactory, IManag
|
|||
String name = (String)properties.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
|
||||
if (name == null)
|
||||
{
|
||||
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
|
||||
"The name of the server is mandatory");
|
||||
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
|
||||
"The name of the server is mandatory");
|
||||
}
|
||||
serverInstanceWrapper = new ServerInstanceWrapper(name);
|
||||
_serversIndexedByPID.put(pid, serverInstanceWrapper);
|
||||
_serversNameIndexedByPID.put(pid, name);
|
||||
_serversPIDIndexedByName.put(name, pid);
|
||||
serverInstanceWrapper.start(new Server(), properties);
|
||||
try
|
||||
{
|
||||
serverInstanceWrapper.start(new Server(), properties);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new ConfigurationException(null, "Error starting jetty server instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void deleted(String pid)
|
||||
|
|
|
@ -44,28 +44,29 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
/**
|
||||
* Exposes a Jetty Server to be managed by an OSGi ManagedServiceFactory
|
||||
* Configure and start it.
|
||||
* Can also be used from the ManagedServiceFactory
|
||||
* Configure and start it. Can also be used from the ManagedServiceFactory
|
||||
*/
|
||||
public class ServerInstanceWrapper {
|
||||
public class ServerInstanceWrapper
|
||||
{
|
||||
|
||||
/** The value of this property points to the parent director of
|
||||
* the jetty.xml configuration file currently executed.
|
||||
* Everything is passed as a URL to support the
|
||||
* case where the bundle is zipped. */
|
||||
/**
|
||||
* The value of this property points to the parent director of the jetty.xml
|
||||
* configuration file currently executed. Everything is passed as a URL to
|
||||
* support the case where the bundle is zipped.
|
||||
*/
|
||||
public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
|
||||
|
||||
private static Logger __logger = Log.getLogger(ServerInstanceWrapper.class.getName());
|
||||
|
||||
private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
|
||||
|
||||
private final String _managedServerName;
|
||||
|
||||
|
||||
/**
|
||||
* The managed jetty server
|
||||
*/
|
||||
private Server _server;
|
||||
|
||||
private ContextHandlerCollection _ctxtHandler;
|
||||
|
||||
/**
|
||||
|
@ -74,32 +75,34 @@ public class ServerInstanceWrapper {
|
|||
* let the TldScanner find the jars where the tld files are.
|
||||
*/
|
||||
private ClassLoader _commonParentClassLoaderForWebapps;
|
||||
|
||||
private DeploymentManager _deploymentManager;
|
||||
|
||||
private OSGiAppProvider _provider;
|
||||
|
||||
|
||||
private WebBundleDeployerHelper _webBundleDeployerHelper;
|
||||
|
||||
|
||||
|
||||
public ServerInstanceWrapper(String managedServerName)
|
||||
{
|
||||
_managedServerName = managedServerName;
|
||||
}
|
||||
|
||||
|
||||
public String getManagedServerName()
|
||||
{
|
||||
return _managedServerName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The classloader that should be the parent classloader for
|
||||
* each webapp deployed on this server.
|
||||
* The classloader that should be the parent classloader for each webapp
|
||||
* deployed on this server.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ClassLoader getParentClassLoaderForWebapps()
|
||||
{
|
||||
return _commonParentClassLoaderForWebapps;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The deployment manager registered on this server.
|
||||
*/
|
||||
|
@ -107,7 +110,7 @@ public class ServerInstanceWrapper {
|
|||
{
|
||||
return _deploymentManager;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The app provider registered on this server.
|
||||
*/
|
||||
|
@ -115,19 +118,17 @@ public class ServerInstanceWrapper {
|
|||
{
|
||||
return _provider;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Server getServer()
|
||||
{
|
||||
return _server;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public WebBundleDeployerHelper getWebBundleDeployerHelp()
|
||||
{
|
||||
return _webBundleDeployerHelper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The collection of context handlers
|
||||
*/
|
||||
|
@ -136,8 +137,7 @@ public class ServerInstanceWrapper {
|
|||
return _ctxtHandler;
|
||||
}
|
||||
|
||||
|
||||
public void start(Server server, Dictionary props)
|
||||
public void start(Server server, Dictionary props) throws Exception
|
||||
{
|
||||
_server = server;
|
||||
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
|
||||
|
@ -146,62 +146,61 @@ public class ServerInstanceWrapper {
|
|||
// passing this bundle's classloader as the context classlaoder
|
||||
// makes sure there is access to all the jetty's bundles
|
||||
ClassLoader libExtClassLoader = null;
|
||||
String sharedURLs = (String)props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
|
||||
try
|
||||
{
|
||||
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
|
||||
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(
|
||||
shared, null, server, JettyBootstrapActivator.class.getClassLoader());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
|
||||
|
||||
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
|
||||
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
|
||||
|
||||
Thread.currentThread().setContextClassLoader(libExtClassLoader);
|
||||
|
||||
|
||||
configure(server, props);
|
||||
|
||||
init();
|
||||
|
||||
//now that we have an app provider we can call the registration customizer.
|
||||
try
|
||||
{
|
||||
URL[] jarsWithTlds = getJarsWithTlds();
|
||||
_commonParentClassLoaderForWebapps = jarsWithTlds == null
|
||||
? libExtClassLoader
|
||||
:new TldLocatableURLClassloader(libExtClassLoader,jarsWithTlds);
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
// now that we have an app provider we can call the registration
|
||||
// customizer.
|
||||
|
||||
URL[] jarsWithTlds = getJarsWithTlds();
|
||||
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
|
||||
|
||||
|
||||
server.start();
|
||||
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
|
||||
}
|
||||
catch (Throwable t)
|
||||
catch (Exception e)
|
||||
{
|
||||
t.printStackTrace();
|
||||
if (server != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
LOG.ignore(x);
|
||||
}
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Thread.currentThread().setContextClassLoader(contextCl);
|
||||
}
|
||||
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void stop()
|
||||
{
|
||||
try {
|
||||
try
|
||||
{
|
||||
if (_server.isRunning())
|
||||
{
|
||||
_server.stop();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -229,14 +228,13 @@ public class ServerInstanceWrapper {
|
|||
private URL[] getJarsWithTlds() throws Exception
|
||||
{
|
||||
ArrayList<URL> res = new ArrayList<URL>();
|
||||
WebBundleDeployerHelper.staticInit();//that is not looking great.
|
||||
WebBundleDeployerHelper.staticInit();// that is not looking great.
|
||||
for (WebappRegistrationCustomizer regCustomizer : WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS)
|
||||
{
|
||||
URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER);
|
||||
for (URL url : urls)
|
||||
{
|
||||
if (!res.contains(url))
|
||||
res.add(url);
|
||||
if (!res.contains(url)) res.add(url);
|
||||
}
|
||||
}
|
||||
if (!res.isEmpty())
|
||||
|
@ -244,19 +242,15 @@ public class ServerInstanceWrapper {
|
|||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private void configure(Server server, Dictionary props) throws Exception
|
||||
{
|
||||
String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
|
||||
List<URL> jettyConfigurations = jettyConfigurationUrls != null
|
||||
? extractResources(jettyConfigurationUrls) : null;
|
||||
if (jettyConfigurations == null || jettyConfigurations.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Map<String,Object> id_map = new HashMap<String,Object>();
|
||||
id_map.put("Server",server);
|
||||
Map<String,String> properties = new HashMap<String,String>();
|
||||
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
|
||||
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
|
||||
Map<String, Object> id_map = new HashMap<String, Object>();
|
||||
id_map.put("Server", server);
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
Enumeration<Object> en = props.keys();
|
||||
while (en.hasMoreElements())
|
||||
{
|
||||
|
@ -275,15 +269,17 @@ public class ServerInstanceWrapper {
|
|||
is = r.getInputStream();
|
||||
XmlConfiguration config = new XmlConfiguration(is);
|
||||
config.getIdMap().putAll(id_map);
|
||||
|
||||
//#334062 compute the URL of the folder that contains the jetty.xml conf file
|
||||
//and set it as a property so we can compute relative paths from it.
|
||||
|
||||
// #334062 compute the URL of the folder that contains the
|
||||
// jetty.xml conf file
|
||||
// and set it as a property so we can compute relative paths
|
||||
// from it.
|
||||
String urlPath = jettyConfiguration.toString();
|
||||
int lastSlash = urlPath.lastIndexOf('/');
|
||||
if (lastSlash > 4)
|
||||
{
|
||||
urlPath = urlPath.substring(0, lastSlash);
|
||||
Map<String,String> properties2 = new HashMap<String,String>(properties);
|
||||
Map<String, String> properties2 = new HashMap<String, String>(properties);
|
||||
properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
|
||||
config.getProperties().putAll(properties2);
|
||||
}
|
||||
|
@ -292,11 +288,11 @@ public class ServerInstanceWrapper {
|
|||
config.getProperties().putAll(properties);
|
||||
}
|
||||
config.configure();
|
||||
id_map=config.getIdMap();
|
||||
id_map = config.getIdMap();
|
||||
}
|
||||
catch (SAXParseException saxparse)
|
||||
{
|
||||
__logger.warn("Unable to configure the jetty/etc file " + jettyConfiguration,saxparse);
|
||||
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
|
||||
throw saxparse;
|
||||
}
|
||||
finally
|
||||
|
@ -306,8 +302,7 @@ public class ServerInstanceWrapper {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Must be called after the server is configured.
|
||||
*
|
||||
|
@ -319,50 +314,48 @@ public class ServerInstanceWrapper {
|
|||
private void init()
|
||||
{
|
||||
// Get the context handler
|
||||
_ctxtHandler = (ContextHandlerCollection)_server.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
|
||||
_ctxtHandler = (ContextHandlerCollection) _server.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
|
||||
// get a deployerManager
|
||||
List<DeploymentManager> deployers = _server.getBeans(DeploymentManager.class);
|
||||
if (deployers != null && !deployers.isEmpty())
|
||||
{
|
||||
_deploymentManager = deployers.get(0);
|
||||
|
||||
|
||||
for (AppProvider provider : _deploymentManager.getAppProviders())
|
||||
{
|
||||
if (provider instanceof OSGiAppProvider)
|
||||
{
|
||||
_provider=(OSGiAppProvider)provider;
|
||||
_provider = (OSGiAppProvider) provider;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_provider == null)
|
||||
{
|
||||
//create it on the fly with reasonable default values.
|
||||
// create it on the fly with reasonable default values.
|
||||
try
|
||||
{
|
||||
_provider = new OSGiAppProvider();
|
||||
_provider.setMonitoredDirResource(
|
||||
Resource.newResource(getDefaultOSGiContextsHome(
|
||||
new File(System.getProperty("jetty.home"))).toURI()));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
_provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
_deploymentManager.addAppProvider(_provider);
|
||||
}
|
||||
}
|
||||
|
||||
if (_ctxtHandler == null || _provider==null)
|
||||
throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
|
||||
|
||||
if (_ctxtHandler == null || _provider == null) throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return The default folder in which the context files of the osgi bundles
|
||||
* are located and watched. Or null when the system property
|
||||
* "jetty.osgi.contexts.home" is not defined.
|
||||
* If the configuration file defines the OSGiAppProvider's context.
|
||||
* This will not be taken into account.
|
||||
* "jetty.osgi.contexts.home" is not defined. If the configuration
|
||||
* file defines the OSGiAppProvider's context. This will not be
|
||||
* taken into account.
|
||||
*/
|
||||
File getDefaultOSGiContextsHome(File jettyHome)
|
||||
{
|
||||
|
@ -370,20 +363,19 @@ public class ServerInstanceWrapper {
|
|||
if (jettyContextsHome != null)
|
||||
{
|
||||
File contextsHome = new File(jettyContextsHome);
|
||||
if (!contextsHome.exists() || !contextsHome.isDirectory())
|
||||
{
|
||||
throw new IllegalArgumentException("the ${jetty.osgi.contexts.home} '" + jettyContextsHome + " must exist and be a folder");
|
||||
}
|
||||
if (!contextsHome.exists() || !contextsHome.isDirectory()) { throw new IllegalArgumentException(
|
||||
"the ${jetty.osgi.contexts.home} '" + jettyContextsHome
|
||||
+ " must exist and be a folder"); }
|
||||
return contextsHome;
|
||||
}
|
||||
return new File(jettyHome, "/contexts");
|
||||
}
|
||||
|
||||
|
||||
File getOSGiContextsHome()
|
||||
{
|
||||
return _provider.getContextXmlDirAsFile();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the urls in this string.
|
||||
*/
|
||||
|
@ -396,19 +388,19 @@ public class ServerInstanceWrapper {
|
|||
String tok = tokenizer.nextToken();
|
||||
try
|
||||
{
|
||||
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper
|
||||
.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
|
||||
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
|
||||
}
|
||||
catch (Throwable mfe)
|
||||
{
|
||||
|
||||
LOG.warn(mfe);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the folders that might contain jars for the legacy J2EE shared libraries
|
||||
* Get the folders that might contain jars for the legacy J2EE shared
|
||||
* libraries
|
||||
*/
|
||||
private List<File> extractFiles(String propertyValue)
|
||||
{
|
||||
|
@ -420,8 +412,7 @@ public class ServerInstanceWrapper {
|
|||
try
|
||||
{
|
||||
URL url = new URL(tok);
|
||||
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper
|
||||
.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
|
||||
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
|
||||
if (url.getProtocol().equals("file"))
|
||||
{
|
||||
Resource res = Resource.newResource(url);
|
||||
|
@ -434,11 +425,10 @@ public class ServerInstanceWrapper {
|
|||
}
|
||||
catch (Throwable mfe)
|
||||
{
|
||||
|
||||
LOG.warn(mfe);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
mex.add(e);
|
||||
}
|
||||
|
||||
if (_connectors!=null)
|
||||
if (_connectors!=null && mex.size()==0)
|
||||
{
|
||||
for (int i=0;i<_connectors.length;i++)
|
||||
{
|
||||
|
|
|
@ -414,7 +414,7 @@ public class ProxyServlet implements Servlet
|
|||
if (request.getQueryString() != null)
|
||||
uri += "?" + request.getQueryString();
|
||||
|
||||
HttpURI url = proxyHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),uri);
|
||||
HttpURI url = proxyHttpURI(request,uri);
|
||||
|
||||
if (debug != 0)
|
||||
_log.debug(debug + " proxy " + uri + "-->" + url);
|
||||
|
@ -677,6 +677,11 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException
|
||||
{
|
||||
return proxyHttpURI(request.getScheme(), request.getServerName(), request.getServerPort(), uri);
|
||||
}
|
||||
|
||||
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri) throws MalformedURLException
|
||||
{
|
||||
if (!validateDestination(serverName,uri))
|
||||
|
|
|
@ -35,6 +35,4 @@ public interface ISession extends Session
|
|||
public <C> void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Handler<C> handler, C context);
|
||||
|
||||
public <C> void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Handler<C> handler, C context);
|
||||
|
||||
public int getWindowSize();
|
||||
}
|
||||
|
|
|
@ -18,10 +18,11 @@ package org.eclipse.jetty.spdy;
|
|||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.InterruptedByTimeoutException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
@ -253,9 +254,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Stream> getStreams()
|
||||
public Set<Stream> getStreams()
|
||||
{
|
||||
List<Stream> result = new ArrayList<>();
|
||||
Set<Stream> result = new HashSet<>();
|
||||
result.addAll(streams.values());
|
||||
return result;
|
||||
}
|
||||
|
@ -540,7 +541,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
Settings.Setting windowSizeSetting = frame.getSettings().get(Settings.ID.INITIAL_WINDOW_SIZE);
|
||||
if (windowSizeSetting != null)
|
||||
{
|
||||
int prevWindowSize = windowSize;
|
||||
windowSize = windowSizeSetting.value();
|
||||
for (IStream stream : streams.values())
|
||||
stream.updateWindowSize(windowSize - prevWindowSize);
|
||||
logger.debug("Updated window size to {}", windowSize);
|
||||
}
|
||||
|
||||
|
@ -774,12 +778,6 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
threadPool.execute(task);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindowSize()
|
||||
{
|
||||
return windowSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
|
@ -794,12 +792,21 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
|
|||
if (frameBytes == null)
|
||||
return;
|
||||
|
||||
buffer = frameBytes.getByteBuffer();
|
||||
if (buffer == null)
|
||||
FrameBytes stalled = null;
|
||||
while (true)
|
||||
{
|
||||
enqueueFirst(frameBytes);
|
||||
logger.debug("Flush skipped, {} frame(s) in queue", queue.size());
|
||||
return;
|
||||
buffer = frameBytes.getByteBuffer();
|
||||
if (buffer != null)
|
||||
break;
|
||||
|
||||
// We are stalled: enqueue as last so other frames can be flushed
|
||||
enqueueLast(frameBytes);
|
||||
if (stalled == null)
|
||||
stalled = frameBytes;
|
||||
else if (stalled == frameBytes)
|
||||
return;
|
||||
logger.debug("Flush stalled for {}, {} frame(s) in queue", frameBytes, queue.size());
|
||||
frameBytes = queue.poll();
|
||||
}
|
||||
|
||||
flushing = true;
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.eclipse.jetty.spdy.api;
|
||||
|
||||
import java.util.EventListener;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -181,7 +181,7 @@ public interface Session
|
|||
/**
|
||||
* @return the streams currently active in this session
|
||||
*/
|
||||
public List<Stream> getStreams();
|
||||
public Set<Stream> getStreams();
|
||||
|
||||
/**
|
||||
* <p>Super interface for listeners with callbacks that are invoked on specific session events.</p>
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.concurrent.Exchanger;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.spdy.api.BytesDataInfo;
|
||||
import org.eclipse.jetty.spdy.api.DataInfo;
|
||||
|
@ -41,6 +42,70 @@ import org.junit.Test;
|
|||
|
||||
public class FlowControlTest extends AbstractTest
|
||||
{
|
||||
@Test
|
||||
public void testFlowControlWithConcurrentSettings() throws Exception
|
||||
{
|
||||
// Initial window is 64 KiB. We allow the client to send 1024 B
|
||||
// then we change the window to 512 B. At this point, the client
|
||||
// must stop sending data (although the initial window allows it)
|
||||
|
||||
final int size = 512;
|
||||
final AtomicReference<DataInfo> dataInfoRef = new AtomicReference<>();
|
||||
final CountDownLatch dataLatch = new CountDownLatch(2);
|
||||
final CountDownLatch settingsLatch = new CountDownLatch(1);
|
||||
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
stream.reply(new ReplyInfo(true));
|
||||
return new StreamFrameListener.Adapter()
|
||||
{
|
||||
private final AtomicInteger dataFrames = new AtomicInteger();
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataInfo dataInfo)
|
||||
{
|
||||
int dataFrameCount = dataFrames.incrementAndGet();
|
||||
if (dataFrameCount == 1)
|
||||
{
|
||||
dataInfoRef.set(dataInfo);
|
||||
Settings settings = new Settings();
|
||||
settings.put(new Settings.Setting(Settings.ID.INITIAL_WINDOW_SIZE, size));
|
||||
stream.getSession().settings(new SettingsInfo(settings));
|
||||
}
|
||||
else if (dataFrameCount > 1)
|
||||
{
|
||||
dataInfo.consume(dataInfo.length());
|
||||
dataLatch.countDown();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}), new SessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(Session session, SettingsInfo settingsInfo)
|
||||
{
|
||||
settingsLatch.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
Stream stream = session.syn(new SynInfo(false), null).get(5, TimeUnit.SECONDS);
|
||||
stream.data(new BytesDataInfo(new byte[size * 2], false));
|
||||
settingsLatch.await(5, TimeUnit.SECONDS);
|
||||
|
||||
// Send the second chunk of data, must not arrive since we're flow control stalled now
|
||||
stream.data(new BytesDataInfo(new byte[size * 2], true));
|
||||
Assert.assertFalse(dataLatch.await(1, TimeUnit.SECONDS));
|
||||
|
||||
// Consume the data arrived to server, this will resume flow control
|
||||
DataInfo dataInfo = dataInfoRef.get();
|
||||
dataInfo.consume(dataInfo.length());
|
||||
|
||||
Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServerFlowControlOneBigWrite() throws Exception
|
||||
{
|
||||
|
@ -294,6 +359,98 @@ public class FlowControlTest extends AbstractTest
|
|||
Assert.assertEquals(dataInfo.length(), dataInfo.consumed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStreamsStalledDoesNotStallOtherStreams() throws Exception
|
||||
{
|
||||
final int windowSize = 1024;
|
||||
final CountDownLatch settingsLatch = new CountDownLatch(1);
|
||||
Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onSettings(Session session, SettingsInfo settingsInfo)
|
||||
{
|
||||
settingsLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
stream.reply(new ReplyInfo(false));
|
||||
stream.data(new BytesDataInfo(new byte[windowSize * 2], true));
|
||||
return null;
|
||||
}
|
||||
}), null);
|
||||
Settings settings = new Settings();
|
||||
settings.put(new Settings.Setting(Settings.ID.INITIAL_WINDOW_SIZE, windowSize));
|
||||
session.settings(new SettingsInfo(settings));
|
||||
|
||||
Assert.assertTrue(settingsLatch.await(5, TimeUnit.SECONDS));
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(3);
|
||||
final AtomicReference<DataInfo> dataInfoRef1 = new AtomicReference<>();
|
||||
final AtomicReference<DataInfo> dataInfoRef2 = new AtomicReference<>();
|
||||
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
|
||||
{
|
||||
private final AtomicInteger dataFrames = new AtomicInteger();
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataInfo dataInfo)
|
||||
{
|
||||
int frames = dataFrames.incrementAndGet();
|
||||
if (frames == 1)
|
||||
{
|
||||
// Do not consume it to stall flow control
|
||||
dataInfoRef1.set(dataInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataInfo.consume(dataInfo.length());
|
||||
if (dataInfo.isClose())
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
}).get(5, TimeUnit.SECONDS);
|
||||
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
|
||||
{
|
||||
private final AtomicInteger dataFrames = new AtomicInteger();
|
||||
|
||||
@Override
|
||||
public void onData(Stream stream, DataInfo dataInfo)
|
||||
{
|
||||
int frames = dataFrames.incrementAndGet();
|
||||
if (frames == 1)
|
||||
{
|
||||
// Do not consume it to stall flow control
|
||||
dataInfoRef2.set(dataInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
dataInfo.consume(dataInfo.length());
|
||||
if (dataInfo.isClose())
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
}).get(5, TimeUnit.SECONDS);
|
||||
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(Stream stream, DataInfo dataInfo)
|
||||
{
|
||||
DataInfo dataInfo1 = dataInfoRef1.getAndSet(null);
|
||||
if (dataInfo1 != null)
|
||||
dataInfo1.consume(dataInfo1.length());
|
||||
DataInfo dataInfo2 = dataInfoRef2.getAndSet(null);
|
||||
if (dataInfo2 != null)
|
||||
dataInfo2.consume(dataInfo2.length());
|
||||
dataInfo.consume(dataInfo.length());
|
||||
if (dataInfo.isClose())
|
||||
latch.countDown();
|
||||
}
|
||||
}).get(5, TimeUnit.SECONDS);
|
||||
|
||||
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private void expectException(Class<? extends Exception> exception, Callable command)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -381,7 +381,7 @@ public class Main
|
|||
}
|
||||
else if (info.equals("@STARTINI"))
|
||||
{
|
||||
List<String> ini = loadStartIni(null);
|
||||
List<String> ini = loadStartIni(new File(_jettyHome,"start.ini"));
|
||||
if (ini != null && ini.size() > 0)
|
||||
{
|
||||
for (String a : ini)
|
||||
|
|
|
@ -402,8 +402,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory());
|
||||
|
||||
LOG.debug("Try webapp=" + web_app + ", exists=" + web_app.exists() + ", directory=" + web_app.isDirectory()+" file="+(web_app.getFile()));
|
||||
// Is the WAR usable directly?
|
||||
if (web_app.exists() && !web_app.isDirectory() && !web_app.toString().startsWith("jar:"))
|
||||
{
|
||||
|
@ -485,57 +484,50 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
LOG.debug("webapp=" + web_app);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Do we need to extract WEB-INF/lib?
|
||||
if (context.isCopyWebInf())
|
||||
if (context.isCopyWebInf() && !context.isCopyWebDir())
|
||||
{
|
||||
Resource web_inf= web_app.addPath("WEB-INF/");
|
||||
|
||||
if (web_inf instanceof ResourceCollection ||
|
||||
web_inf.exists() &&
|
||||
web_inf.isDirectory() &&
|
||||
(web_inf.getFile()==null || !web_inf.getFile().isDirectory()))
|
||||
{
|
||||
File extractedWebInfDir= new File(context.getTempDirectory(), "webinf");
|
||||
if (extractedWebInfDir.exists())
|
||||
IO.delete(extractedWebInfDir);
|
||||
extractedWebInfDir.mkdir();
|
||||
Resource web_inf_lib = web_inf.addPath("lib/");
|
||||
File webInfDir=new File(extractedWebInfDir,"WEB-INF");
|
||||
webInfDir.mkdir();
|
||||
File extractedWebInfDir= new File(context.getTempDirectory(), "webinf");
|
||||
if (extractedWebInfDir.exists())
|
||||
IO.delete(extractedWebInfDir);
|
||||
extractedWebInfDir.mkdir();
|
||||
Resource web_inf_lib = web_inf.addPath("lib/");
|
||||
File webInfDir=new File(extractedWebInfDir,"WEB-INF");
|
||||
webInfDir.mkdir();
|
||||
|
||||
if (web_inf_lib.exists())
|
||||
{
|
||||
File webInfLibDir = new File(webInfDir, "lib");
|
||||
if (webInfLibDir.exists())
|
||||
IO.delete(webInfLibDir);
|
||||
webInfLibDir.mkdir();
|
||||
if (web_inf_lib.exists())
|
||||
{
|
||||
File webInfLibDir = new File(webInfDir, "lib");
|
||||
if (webInfLibDir.exists())
|
||||
IO.delete(webInfLibDir);
|
||||
webInfLibDir.mkdir();
|
||||
|
||||
LOG.info("Copying WEB-INF/lib " + web_inf_lib + " to " + webInfLibDir);
|
||||
web_inf_lib.copyTo(webInfLibDir);
|
||||
}
|
||||
LOG.info("Copying WEB-INF/lib " + web_inf_lib + " to " + webInfLibDir);
|
||||
web_inf_lib.copyTo(webInfLibDir);
|
||||
}
|
||||
|
||||
Resource web_inf_classes = web_inf.addPath("classes/");
|
||||
if (web_inf_classes.exists())
|
||||
{
|
||||
File webInfClassesDir = new File(webInfDir, "classes");
|
||||
if (webInfClassesDir.exists())
|
||||
IO.delete(webInfClassesDir);
|
||||
webInfClassesDir.mkdir();
|
||||
LOG.info("Copying WEB-INF/classes from "+web_inf_classes+" to "+webInfClassesDir.getAbsolutePath());
|
||||
web_inf_classes.copyTo(webInfClassesDir);
|
||||
}
|
||||
Resource web_inf_classes = web_inf.addPath("classes/");
|
||||
if (web_inf_classes.exists())
|
||||
{
|
||||
File webInfClassesDir = new File(webInfDir, "classes");
|
||||
if (webInfClassesDir.exists())
|
||||
IO.delete(webInfClassesDir);
|
||||
webInfClassesDir.mkdir();
|
||||
LOG.info("Copying WEB-INF/classes from "+web_inf_classes+" to "+webInfClassesDir.getAbsolutePath());
|
||||
web_inf_classes.copyTo(webInfClassesDir);
|
||||
}
|
||||
|
||||
web_inf=Resource.newResource(extractedWebInfDir.getCanonicalPath());
|
||||
web_inf=Resource.newResource(extractedWebInfDir.getCanonicalPath());
|
||||
|
||||
ResourceCollection rc = new ResourceCollection(web_inf,web_app);
|
||||
ResourceCollection rc = new ResourceCollection(web_inf,web_app);
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("context.resourcebase = "+rc);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("context.resourcebase = "+rc);
|
||||
|
||||
context.setBaseResource(rc);
|
||||
}
|
||||
context.setBaseResource(rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue