git diff 54e885d9670548c12cf9ffbd58702b73d373c186 remotes/origin/jetty-8-historical | patch -p1 ; git add -A

This commit is contained in:
Greg Wilkins 2011-07-07 18:18:24 +10:00
parent 54e885d967
commit 17e907c2fb
229 changed files with 7918 additions and 5271 deletions

View File

@ -1,3 +1,10 @@
jetty-8.0.0.M3
+ 324505 Implement API login
+ 335500 request.getParts() throws a NullPointerException
+ 343472 isUserInRole does not prevent subsequent login call.
+ 346180 jsp-2.2 support
+ Updated to jetty-7.4.2.v20110526
jetty-7.4.2.v20110526
+ 334443 Improve the ability to specify extra class paths using the Jetty Maven Plugin
+ 336220 tmp directory is not set if you reload a webapp with jetty-maven-plugin
@ -95,6 +102,20 @@ jetty-7.4.0.RC0
+ Ensure generated fragment names are unique
+ Added extra session removal test
jetty-8.0.0.M2 16 November 2010
+ 320073 Reconsile configuration mechanism
+ 321068 JSF2 fails to initialize
+ 324493 Registration init parameter handling null check, setInitParameters additive
+ 324505 Request.login method must throw ServletException if it cant login
+ 324872 allow disabling listener restriction from using *Registration interfaces
+ 327416 Change meaning of @HandlesTypes in line with latest interpretation by JSR315
+ 327489 Change meaning of @MultipartConfig to match servlet spec 3.0 maintenance release 3.0a
+ 328008 Handle update to Servlet Spec 3 Section 8.2.3.h.ii
+ 330188 Reject web-fragment.xml with same <name> as another already loaded one
+ 330208 Support new wording on servlet-mapping and filter-mapping merging from servlet3.0a
+ 330292 request.getParts() returns only one part when the name is the same
+ Update to jetty-7.2.1.v20101111
jetty-7.3.1.v20110307 7 March 2011
+ 316382 Support a more strict SSL option with certificates
+ 333481 Handle UCS-4 codepoints in decode and encode
@ -118,9 +139,7 @@ jetty-7.3.1.v20110307 7 March 2011
+ 338068 Leaking ConstraintMappings on redeploy
+ 338092 ProxyServlet leaks memory
+ 338607 Removed managed attributes when context is stopped
+ 338880 Fixed failing buffer range checks
+ 338920 Handle non existent real path directories
+ 338961 AJP packet size
+ 338819 Externally control Deployment Manager application lifecycle
+ JETTY-1304 Allow quoted boundaries in Multipart filter
+ JETTY-1317 More elegent handling of bad URIs in requests
+ JETTY-1331 Allow alternate XML configuration processors (eg spring)
@ -291,7 +310,6 @@ jetty-7.2.0.RC0 1 October 2010
+ JETTY-1245 Do not use direct buffers with NIO SSL
+ JETTY-1249 Apply max idle time to all connectors
+ JETTY-1250 Parallel start of HandlerCollection
+ JETTY-1252 Handle more multipart transfer encodings
+ JETTY-1256 annotation and jta jars from Orbit
+ JETTY-1259 NullPointerException in JDBCSessionIdManager when invalidating session
+ JETTY-1261 errant listener usage in StandardDescriptorProcessor
@ -317,6 +335,13 @@ jetty-7.1.6.v20100715
+ JETTY-1249 Apply max idle time to all connectors
+ JETTY-1251 Replace then close selector for JVM bugs
jetty-8.0.0.M1 12 July 2010
+ 306350 Ensure jars excluded by ordering are not scanned for annotations
+ JETTY-1224 Change jetty-8 merge rules for fragment descriptors and annotations
+ Ensure <absolute-ordering> in web.xml overrides relative <ordering> in fragments
+ Ensure empty <absolute-ordering> implies exclusion of all fragments
+ Ensure servlet-api jar class inheritance hierarchy is scanned
jetty-7.1.5.v20100705
+ Update ecj to 3.6 Helios release drop
+ 288194 Add blacklist/whitelist to ProxyServlet and ProxyHandler
@ -473,6 +498,9 @@ jetty-7.1.0.RC0 27 April 2010
+ Fix jetty-plus.xml reference to addLifeCycle
+ JETTY-1200 SSL NIO Endpoint wraps non NIO buffers
+ JETTY-1202 Use platform default algorithm for SecureRandom
+ Merged 7.0.2.v20100331
+ Add NPE protection to ContainerInitializerConfiguration
+ Temporarily remove jetty-osgi module to clarify jsp version compatibility
+ JETTY-1212 handle long content lengths
+ JETTY-1214 avoid ISE when scavenging invalid session
+ JETTY-903 Stop both caches
@ -611,6 +639,13 @@ jetty-7.0.2.RC0
+ 305997 Coalesce buffers in ChannelEndPoint.flush()
+ 306028 Enable TCP_NODELAY by default in client connectors
jetty-8.0.0.M0 28 February 2010
+ Updated servlet 3.0 spec 20100224
+ Merged 7.0.1.v20091116
+ Updated to cometd 1.0.1
jetty-7.0.1.v20091125 25 November 2009
+ 274251 DefaultServlet supports exact match mode.
+ 288401 HttpExchange.cancel() Method Unimplemented

View File

@ -0,0 +1,24 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-jar</artifactId>
<packaging>jar</packaging>
<name>Example Async Rest :: Jar</name>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,116 @@
//========================================================================
//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
package org.eclipse.jetty.example.asyncrest;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Queue;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Abstract Servlet implementation class AsyncRESTServlet.
* Enquires ebay REST service for auctions by key word.
* May be configured with init parameters: <dl>
* <dt>appid</dt><dd>The eBay application ID to use</dd>
* </dl>
* Each request examines the following request parameters:<dl>
* <dt>items</dt><dd>The keyword to search for</dd>
* </dl>
*/
public class AbstractRestServlet extends HttpServlet
{
protected final static String __DEFAULT_APPID = "Webtide81-adf4-4f0a-ad58-d91e41bbe85";
protected final static String STYLE =
"<style type='text/css'>"+
" img.thumb:hover {height:50px}"+
" img.thumb {vertical-align:text-top}"+
" span.red {color: #ff0000}"+
" span.green {color: #00ff00}"+
" iframe {border: 0px}"+
"</style>";
protected final static String ITEMS_PARAM = "items";
protected final static String APPID_PARAM = "appid";
protected String _appid;
public void init(ServletConfig servletConfig) throws ServletException
{
if (servletConfig.getInitParameter(APPID_PARAM) == null)
_appid = __DEFAULT_APPID;
else
_appid = servletConfig.getInitParameter(APPID_PARAM);
}
protected String restURL(String item)
{
try
{
return ("http://open.api.ebay.com/shopping?MaxEntries=3&appid=" + _appid +
"&version=573&siteid=0&callname=FindItems&responseencoding=JSON&QueryKeywords=" +
URLEncoder.encode(item,"UTF-8"));
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
protected String generateThumbs(Queue<Map<String,String>> results)
{
StringBuilder thumbs = new StringBuilder();
for (Map<String, String> m : results)
{
if (!m.containsKey("GalleryURL"))
continue;
thumbs.append("<a href=\""+m.get("ViewItemURLForNaturalSearch")+"\">");
thumbs.append("<img class='thumb' border='1px' height='25px'"+
" src='"+m.get("GalleryURL")+"'"+
" title='"+m.get("Title")+"'"+
"/>");
thumbs.append("</a>&nbsp;");
}
return thumbs.toString();
}
protected String ms(long nano)
{
BigDecimal dec = new BigDecimal(nano);
return dec.divide(new BigDecimal(1000000L)).setScale(1,RoundingMode.UP).toString();
}
protected int width(long nano)
{
int w=(int)((nano+999999L)/5000000L);
if (w==0)
w=2;
return w;
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
}

View File

@ -0,0 +1,207 @@
//========================================================================
//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
package org.eclipse.jetty.example.asyncrest;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.AsyncContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.util.ajax.JSON;
/**
* Servlet implementation class AsyncRESTServlet.
* Enquires ebay REST service for auctions by key word.
* May be configured with init parameters: <dl>
* <dt>appid</dt><dd>The eBay application ID to use</dd>
* </dl>
* Each request examines the following request parameters:<dl>
* <dt>items</dt><dd>The keyword to search for</dd>
* </dl>
*/
public class AsyncRestServlet extends AbstractRestServlet
{
final static String RESULTS_ATTR = "org.eclipse.jetty.demo.client";
final static String DURATION_ATTR = "org.eclipse.jetty.demo.duration";
final static String START_ATTR = "org.eclispe.jetty.demo.start";
HttpClient _client;
public void init(ServletConfig servletConfig) throws ServletException
{
super.init(servletConfig);
_client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
try
{
_client.start();
}
catch (Exception e)
{
throw new ServletException(e);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Long start=System.nanoTime();
// Do we have results yet?
Queue<Map<String, String>> results = (Queue<Map<String, String>>) request.getAttribute(RESULTS_ATTR);
// If no results, this must be the first dispatch, so send the REST request(s)
if (results==null)
{
// define results data structures
final Queue<Map<String, String>> resultsQueue = new ConcurrentLinkedQueue<Map<String,String>>();
request.setAttribute(RESULTS_ATTR, results=resultsQueue);
// suspend the request
// This is done before scheduling async handling to avoid race of
// dispatch before startAsync!
final AsyncContext async = request.startAsync();
async.setTimeout(30000);
// extract keywords to search for
String[] keywords=request.getParameter(ITEMS_PARAM).split(",");
final AtomicInteger outstanding=new AtomicInteger(keywords.length);
// Send request each keyword
for (final String item:keywords)
{
_client.send(
new AsyncRestRequest(item)
{
void onAuctionFound(Map<String,String> auction)
{
resultsQueue.add(auction);
}
void onComplete()
{
if (outstanding.decrementAndGet()<=0)
async.dispatch();
}
});
}
// save timing info and return
request.setAttribute(START_ATTR, start);
request.setAttribute(DURATION_ATTR, new Long(System.nanoTime() - start));
return;
}
// We have results!
// Generate the response
String thumbs = generateThumbs(results);
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head>");
out.println(STYLE);
out.println("</head><body><small>");
long initial = (Long) request.getAttribute(DURATION_ATTR);
long start0 = (Long) request.getAttribute(START_ATTR);
long now = System.nanoTime();
long total=now-start0;
long generate=now-start;
long thread=initial+generate;
out.print("<b>Asynchronous: "+request.getParameter(ITEMS_PARAM)+"</b><br/>");
out.print("Total Time: "+ms(total)+"ms<br/>");
out.print("Thread held (<span class='red'>red</span>): "+ms(thread)+"ms (" + ms(initial) + " initial + " + ms(generate) + " generate )<br/>");
out.print("Async wait (<span class='green'>green</span>): "+ms(total-thread)+"ms<br/>");
out.println("<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(initial)+"px'>"+
"<img border='0px' src='asyncrest/green.png' height='20px' width='"+width(total-thread)+"px'>"+
"<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(generate)+"px'>");
out.println("<hr />");
out.println(thumbs);
out.println("</small>");
out.println("</body></html>");
out.close();
}
private abstract class AsyncRestRequest extends ContentExchange
{
AsyncRestRequest(final String item)
{
// send the exchange
setMethod("GET");
setURL(restURL(item));
}
abstract void onAuctionFound(Map<String,String> details);
abstract void onComplete();
protected void onResponseComplete() throws IOException
{
// extract auctions from the results
Map<String,?> query = (Map<String,?>) JSON.parse(this.getResponseContent());
Object[] auctions = (Object[]) query.get("Item");
if (auctions != null)
{
for (Object o : auctions)
onAuctionFound((Map<String,String>)o);
}
onComplete();
}
/* ------------------------------------------------------------ */
protected void onConnectionFailed(Throwable ex)
{
getServletContext().log("onConnectionFailed: ",ex);
onComplete();
}
/* ------------------------------------------------------------ */
protected void onException(Throwable ex)
{
getServletContext().log("onConnectionFailed: ",ex);
onComplete();
}
/* ------------------------------------------------------------ */
protected void onExpire()
{
getServletContext().log("onConnectionFailed: expired");
onComplete();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
}

View File

@ -0,0 +1,102 @@
//========================================================================
//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
package org.eclipse.jetty.example.asyncrest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.ajax.JSON;
/**
* Servlet implementation class SerialRestServlet
*/
public class SerialRestServlet extends AbstractRestServlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
long start = System.nanoTime();
String[] keywords=request.getParameter(ITEMS_PARAM).split(",");
Queue<Map<String,String>> results = new LinkedList<Map<String,String>>();
// make all requests serially
for (String itemName : keywords)
{
URL url = new URL(restURL(itemName));
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
Map query = (Map)JSON.parse(new BufferedReader(new InputStreamReader(connection.getInputStream())));
Object[] auctions = (Object[]) query.get("Item");
if (auctions != null)
{
for (Object o : auctions)
results.add((Map) o);
}
}
// Generate the response
String thumbs=generateThumbs(results);
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><head>");
out.println(STYLE);
out.println("</head><body><small>");
long now = System.nanoTime();
long total=now-start;
out.print("<b>Blocking: "+request.getParameter(ITEMS_PARAM)+"</b><br/>");
out.print("Total Time: "+ms(total)+"ms<br/>");
out.print("Thread held (<span class='red'>red</span>): "+ms(total)+"ms<br/>");
out.println("<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(total)+"px'>");
out.println("<hr />");
out.println(thumbs);
out.println("</small>");
out.println("</body></html>");
out.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doGet(request, response);
}
}

View File

@ -0,0 +1,38 @@
<html>
<head>
<style type='text/css'>
iframe {border: 0px}
table, tr, td {border: 0px}
</style>
</head>
<body>
<h1>Blocking vs Asynchronous REST</h1>
<p>
This demo calls the EBay WS API both synchronously and asynchronously,
to obtain items matching each of the keywords passed on the query
string. The time the request thread is head is displayed for both.
</p>
<table width='100%'>
<tr>
<td>
<iframe id="f1" width='100%' height='175px' src="testSerial?items=kayak"></iframe>
</td>
<td>
<iframe id="f3" width='100%' height='175px' src="testSerial?items=mouse,beer,gnome"></iframe>
</td>
</tr>
<tr>
<td>
<iframe id="f2" width='100%' height='175px' src="testAsync?items=kayak"/></iframe>
</td>
<td>
<iframe id="f4" width='100%' height='175px' src="testAsync?items=mouse,beer,gnome"/></iframe>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,22 @@
<web-fragment>
<servlet>
<display-name>SerialRestServlet</display-name>
<servlet-name>SerialRestServlet</servlet-name>
<servlet-class>org.eclipse.jetty.example.asyncrest.SerialRestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SerialRestServlet</servlet-name>
<url-pattern>/testSerial</url-pattern>
</servlet-mapping>
<servlet>
<display-name>AsyncRestServlet</display-name>
<servlet-name>AsyncRestServlet</servlet-name>
<servlet-class>org.eclipse.jetty.example.asyncrest.AsyncRestServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>AsyncRestServlet</servlet-name>
<url-pattern>/testAsync</url-pattern>
</servlet-mapping>
</web-fragment>

View File

@ -0,0 +1,33 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-webapp</artifactId>
<packaging>war</packaging>
<name>Example Async Rest :: Webapp</name>
<build>
<finalName>async-rest</finalName>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-jar</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Class-Path:

View File

@ -0,0 +1,9 @@
<?xml version="1.0"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Async REST Webservice Example</display-name>
</web-app>

View File

@ -0,0 +1,38 @@
<html>
<head>
<style type='text/css'>
iframe {border: 0px}
table, tr, td {border: 0px}
</style>
</head>
<body>
<h1>Blocking vs Asynchronous REST</h1>
<p>
This demo calls the EBay WS API both synchronously and asynchronously,
to obtain items matching each of the keywords passed on the query
string. The time the request thread is head is displayed for both.
</p>
<table width='100%'>
<tr>
<td>
<iframe id="f1" width='100%' height='175px' src="testSerial?items=kayak"></iframe>
</td>
<td>
<iframe id="f3" width='100%' height='175px' src="testSerial?items=mouse,beer,gnome"></iframe>
</td>
</tr>
<tr>
<td>
<iframe id="f2" width='100%' height='175px' src="testAsync?items=kayak"/></iframe>
</td>
<td>
<iframe id="f4" width='100%' height='175px' src="testAsync?items=mouse,beer,gnome"/></iframe>
</td>
</tr>
</table>
</body>
</html>

View File

@ -0,0 +1,30 @@
package org.eclipse.jetty.example.asyncrest;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;
public class DemoServer
{
public static void main(String[] args)
throws Exception
{
String jetty_home = System.getProperty("jetty.home",".");
Server server = new Server();
Connector connector=new SelectChannelConnector();
connector.setPort(Integer.getInteger("jetty.port",8080).intValue());
server.setConnectors(new Connector[]{connector});
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setWar(jetty_home+"/target/example-async-rest-webapp-8.0.0.M0-SNAPSHOT");
server.setHandler(webapp);
server.start();
server.join();
}
}

View File

@ -0,0 +1,16 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<packaging>pom</packaging>
<name>Example Async Rest</name>
<modules>
<module>async-rest-jar</module>
<module>async-rest-webapp</module>
</modules>
</project>

View File

@ -2,11 +2,11 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>
<name>Example :: Jetty Embedded</name>
<name>Example :: Embedded Jetty Examples</name>
<description>Jetty Embedded Examples</description>
<build>
<plugins>

View File

@ -123,7 +123,7 @@ public class LikeJettyXml
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
webapp_provider.setContextXmlDir(jetty_home + "/contexts");
deployer.addAppProvider(webapp_provider);
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
login.setConfig(jetty_home + "/etc/realm.properties");

View File

@ -69,5 +69,4 @@ public class ManyContexts
System.err.println(server.dump());
server.join();
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -136,9 +136,9 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<version>${servlet.spec.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -146,12 +146,6 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -92,12 +92,8 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
</exclusions>
</dependency>
@ -108,8 +104,8 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
@ -118,12 +114,6 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
@ -131,8 +121,8 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
@ -200,6 +190,11 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-nested</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -86,8 +86,8 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.geronimo.specs</groupId>
@ -104,9 +104,10 @@
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<version>${servlet.spec.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -86,21 +86,20 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -86,16 +86,15 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>
@ -86,21 +86,15 @@
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</artifactId>

View File

@ -33,10 +33,10 @@ public class Ajp13SocketConnector extends SocketConnector
static boolean __allowShutdown = false;
public Ajp13SocketConnector()
{
super.setRequestHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
super.setResponseHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
super.setRequestBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
super.setResponseBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
super.setRequestHeaderSize(Ajp13Packet.MAX_DATA_SIZE);
super.setResponseHeaderSize(Ajp13Packet.MAX_DATA_SIZE);
super.setRequestBufferSize(Ajp13Packet.MAX_DATA_SIZE);
super.setResponseBufferSize(Ajp13Packet.MAX_DATA_SIZE);
// IN AJP protocol the socket stay open, so
// by default the time out is set to 0 seconds
super.setMaxIdleTime(0);

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>
@ -25,7 +25,7 @@
</goals>
<configuration>
<instructions>
<Import-Package>javax.servlet.*;version="[2.5,3.0)",*</Import-Package>
<Import-Package>javax.servlet.*;version="3.0",*</Import-Package>
</instructions>
</configuration>
</execution>

View File

@ -13,8 +13,29 @@
package org.eclipse.jetty.annotations;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ServiceLoader;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.annotation.HandlesTypes;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.Descriptor;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.MetaDataComplete;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebDescriptor;
/**
* Configuration for Annotations
@ -23,15 +44,343 @@ import org.eclipse.jetty.webapp.WebAppContext;
*/
public class AnnotationConfiguration extends AbstractConfiguration
{
public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
public void preConfigure(final WebAppContext context) throws Exception
{
}
@Override
public void configure(WebAppContext context) throws Exception
{
{
boolean metadataComplete = context.getMetaData().isMetaDataComplete();
context.addDecorator(new AnnotationDecorator(context));
if (metadataComplete)
{
//Never scan any jars or classes for annotations if metadata is complete
if (Log.isDebugEnabled()) Log.debug("Metadata-complete==true, not processing annotations for context "+context);
return;
}
else
{
//Only scan jars and classes if metadata is not complete and the web app is version 3.0, or
//a 2.5 version webapp that has specifically asked to discover annotations
if (Log.isDebugEnabled()) Log.debug("parsing annotations");
AnnotationParser parser = createAnnotationParser();
//Discoverable annotations - those that you have to look for without loading a class
parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", new WebServletAnnotationHandler(context));
parser.registerAnnotationHandler("javax.servlet.annotation.WebFilter", new WebFilterAnnotationHandler(context));
parser.registerAnnotationHandler("javax.servlet.annotation.WebListener", new WebListenerAnnotationHandler(context));
ClassInheritanceHandler classHandler = new ClassInheritanceHandler();
parser.registerClassHandler(classHandler);
registerServletContainerInitializerAnnotationHandlers(context, parser);
if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
{
if (Log.isDebugEnabled()) Log.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered());
parseContainerPath(context, parser);
//email from Rajiv Mordani jsrs 315 7 April 2010
// If there is a <others/> then the ordering should be
// WEB-INF/classes the order of the declared elements + others.
// In case there is no others then it is
// WEB-INF/classes + order of the elements.
parseWebInfClasses(context, parser);
parseWebInfLib (context, parser);
}
//save the type inheritance map created by the parser for later reference
context.setAttribute(CLASS_INHERITANCE_MAP, classHandler.getMap());
}
}
/**
* @return a new AnnotationParser. This method can be overridden to use a different impleemntation of
* the AnnotationParser. Note that this is considered internal API.
*/
protected AnnotationParser createAnnotationParser()
{
return new AnnotationParser();
}
@Override
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
{
context.addDecorator(new AnnotationDecorator(context));
}
public void registerServletContainerInitializerAnnotationHandlers (WebAppContext context, AnnotationParser parser)
throws Exception
{
//TODO verify my interpretation of the spec. That is, that metadata-complete has nothing
//to do with finding the ServletContainerInitializers, classes designated to be of interest to them,
//or even calling them on startup.
//Get all ServletContainerInitializers, and check them for HandlesTypes annotations.
//For each class in the HandlesTypes value, if it IS an annotation, register a handler
//that will record the classes that have that annotation.
//If it is NOT an annotation, then we will interrogate the type hierarchy discovered during
//parsing later on to find the applicable classes.
ArrayList<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
context.setAttribute(ContainerInitializerConfiguration.CONTAINER_INITIALIZERS, initializers);
//We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspect
ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader());
if (loadedInitializers != null)
{
for (ServletContainerInitializer service : loadedInitializers)
{
if (!isFromExcludedJar(context, service))
{
HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
ContainerInitializer initializer = new ContainerInitializer();
initializer.setTarget(service);
initializers.add(initializer);
if (annotation != null)
{
Class[] classes = annotation.value();
if (classes != null)
{
initializer.setInterestedTypes(classes);
for (Class c: classes)
{
if (c.isAnnotation())
{
if (Log.isDebugEnabled()) Log.debug("Registering annotation handler for "+c.getName());
parser.registerAnnotationHandler(c.getName(), new ContainerInitializerAnnotationHandler(initializer, c));
}
}
}
else
if (Log.isDebugEnabled()) Log.debug("No classes in HandlesTypes on initializer "+service.getClass());
}
else
if (Log.isDebugEnabled()) Log.debug("No annotation on initializer "+service.getClass());
}
}
}
}
/**
* Check to see if the ServletContainerIntializer loaded via the ServiceLoader came
* from a jar that is excluded by the fragment ordering. See ServletSpec 3.0 p.85.
* @param orderedJars
* @param service
* @return
*/
public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer service)
throws Exception
{
List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();
//If no ordering, nothing is excluded
if (context.getMetaData().getOrdering() == null)
return false;
//there is an ordering, but there are no jars resulting from the ordering, everything excluded
if (orderedJars.isEmpty())
return true;
String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString();
int i = loadingJarName.indexOf(".jar");
if (i < 0)
return false; //not from a jar therefore not from WEB-INF so not excludable
loadingJarName = loadingJarName.substring(0,i+4);
loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
URI loadingJarURI = Resource.newResource(loadingJarName).getURI();
boolean found = false;
Iterator<Resource> itor = orderedJars.iterator();
while (!found && itor.hasNext())
{
Resource r = itor.next();
found = r.getURI().equals(loadingJarURI);
}
return !found;
}
public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
//if no pattern for the container path is defined, then by default scan NOTHING
Log.debug("Scanning container jars");
//clear any previously discovered annotations
clearAnnotationList(parser.getAnnotationHandlers());
//Convert from Resource to URI
ArrayList<URI> containerUris = new ArrayList<URI>();
for (Resource r : context.getMetaData().getOrderedContainerJars())
{
URI uri = r.getURI();
containerUris.add(uri);
}
parser.parse (containerUris.toArray(new URI[containerUris.size()]),
new ClassNameResolver ()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return false;
if (context.isServerClass(name)) return true;
return false;
}
public boolean shouldOverride (String name)
{
//looking at system classpath
if (context.isParentLoaderPriority())
return true;
return false;
}
});
//gather together all annotations discovered
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations(annotations);
}
public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
List<FragmentDescriptor> frags = context.getMetaData().getFragments();
//email from Rajiv Mordani jsrs 315 7 April 2010
//jars that do not have a web-fragment.xml are still considered fragments
//they have to participate in the ordering
ArrayList<URI> webInfUris = new ArrayList<URI>();
List<Resource> jars = context.getMetaData().getOrderedWebInfJars();
//No ordering just use the jars in any order
if (jars == null || jars.isEmpty())
jars = context.getMetaData().getWebInfJars();
for (Resource r : jars)
{
//clear any previously discovered annotations from handlers
clearAnnotationList(parser.getAnnotationHandlers());
URI uri = r.getURI();
FragmentDescriptor f = getFragmentFromJar(r, frags);
//if a jar has no web-fragment.xml we scan it (because it is not exluded by the ordering)
//or if it has a fragment we scan it if it is not metadata complete
if (f == null || !isMetaDataComplete(f))
{
parser.parse(uri,
new ClassNameResolver()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return true;
if (context.isServerClass(name)) return false;
return false;
}
public boolean shouldOverride (String name)
{
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
if (context.isParentLoaderPriority())
return false;
return true;
}
});
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations(r, annotations);
}
}
}
public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
throws Exception
{
Log.debug("Scanning classes in WEB-INF/classes");
if (context.getWebInf() != null)
{
Resource classesDir = context.getWebInf().addPath("classes/");
if (classesDir.exists())
{
clearAnnotationList(parser.getAnnotationHandlers());
parser.parse(classesDir,
new ClassNameResolver()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return true;
if (context.isServerClass(name)) return false;
return false;
}
public boolean shouldOverride (String name)
{
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
if (context.isParentLoaderPriority())
return false;
return true;
}
});
//TODO - where to set the annotations discovered from WEB-INF/classes?
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
context.getMetaData().addDiscoveredAnnotations (annotations);
}
}
}
public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
throws Exception
{
//check if the jar has a web-fragment.xml
FragmentDescriptor d = null;
for (FragmentDescriptor frag: frags)
{
Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml
if (Resource.isContainedIn(fragResource,jar))
{
d = frag;
break;
}
}
return d;
}
public boolean isMetaDataComplete (WebDescriptor d)
{
return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
}
protected void clearAnnotationList (List<DiscoverableAnnotationHandler> handlers)
{
if (handlers == null)
return;
for (DiscoverableAnnotationHandler h:handlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).resetList();
}
}
protected void gatherAnnotations (List<DiscoveredAnnotation> annotations, List<DiscoverableAnnotationHandler> handlers)
{
for (DiscoverableAnnotationHandler h:handlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
annotations.addAll(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
}
}
}

View File

@ -45,6 +45,7 @@ public class AnnotationDecorator implements Decorator
_introspector.registerHandler(new PostConstructAnnotationHandler(context));
_introspector.registerHandler(new PreDestroyAnnotationHandler(context));
_introspector.registerHandler(new DeclareRolesAnnotationHandler(context));
_introspector.registerHandler(new MultiPartConfigAnnotationHandler(context));
}
/* ------------------------------------------------------------ */

View File

@ -43,7 +43,7 @@ import org.objectweb.asm.commons.EmptyVisitor;
* a handler being able to be registered to handle each annotation type.
*/
public class AnnotationParser
{
{
protected List<String> _parsedClassNames = new ArrayList<String>();
protected Map<String, List<DiscoverableAnnotationHandler>> _annotationHandlers = new HashMap<String, List<DiscoverableAnnotationHandler>>();
protected List<ClassHandler> _classHandlers = new ArrayList<ClassHandler>();
@ -636,10 +636,11 @@ public class AnnotationParser
parse(uris, resolver);
}
private void scanClass (InputStream is)
protected void scanClass (InputStream is)
throws IOException
{
ClassReader reader = new ClassReader(is);
reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
}
}

View File

@ -0,0 +1,67 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import java.util.List;
import javax.servlet.annotation.HandlesTypes;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
/**
* ContainerInitializerAnnotationHandler
*
* Discovers classes that contain the specified annotation, either at class or
* method level. The specified annotation is derived from an @HandlesTypes on
* a ServletContainerInitializer class.
*/
public class ContainerInitializerAnnotationHandler implements DiscoverableAnnotationHandler
{
ContainerInitializer _initializer;
Class _annotation;
public ContainerInitializerAnnotationHandler (ContainerInitializer initializer, Class annotation)
{
_initializer = initializer;
_annotation = annotation;
}
/**
* Handle finding a class that is annotated with the annotation we were constructed with.
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
List<Value> values)
{
_initializer.addAnnotatedTypeName(className);
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
_initializer.addAnnotatedTypeName(className);
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
_initializer.addAnnotatedTypeName(className);
}
}

View File

@ -0,0 +1,118 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* ContainerInitializerConfiguration
*
* Apply the ServletContainerInitializers.
*/
public class ContainerInitializerConfiguration extends AbstractConfiguration
{
public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
public void preConfigure(WebAppContext context) throws Exception
{
}
public void configure(WebAppContext context) throws Exception
{
List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
MultiMap classMap = (MultiMap)context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
if (initializers != null)
{
for (ContainerInitializer i : initializers)
{
//We have already found the classes that directly have an annotation that was in the HandlesTypes
//annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance
//hierarchy to find classes that extend or implement them.
if (i.getAnnotatedTypeNames() != null)
{
Set<String> annotatedClassNames = new HashSet<String>(i.getAnnotatedTypeNames());
for (String name : annotatedClassNames)
{
//add the class with the annotation
i.addApplicableTypeName(name);
//add the classes that inherit the annotation
List<String> implementsOrExtends = (List<String>)classMap.getValues(name);
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes(classMap, i, implementsOrExtends);
}
}
//Now we need to look at the HandlesTypes classes that were not annotations. We need to
//find all classes that extend or implement them.
if (i.getInterestedTypes() != null)
{
for (Class c : i.getInterestedTypes())
{
if (!c.isAnnotation())
{
//add the classes that implement or extend the class.
//TODO but not including the class itself?
List<String> implementsOrExtends = (List<String>)classMap.getValues(c.getName());
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes(classMap, i, implementsOrExtends);
}
}
}
//instantiate ServletContainerInitializers, call doStart
i.callStartup(context);
}
//TODO Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
//called, need to check to see if there are any ServletRegistrations remaining
//that are "preliminary" and fail the deployment if so.
}
}
public void postConfigure(WebAppContext context) throws Exception
{
}
public void deconfigure(WebAppContext context) throws Exception
{
}
void addInheritedTypes (MultiMap classMap, ContainerInitializer initializer, List<String> applicableTypes)
{
for (String s : applicableTypes)
{
//add the name of the class that extends or implements
initializer.addApplicableTypeName(s);
//walk the hierarchy and find all types that extend or implement it
List<String> implementsOrExtends = (List<String>)classMap.getValues(s);
if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
addInheritedTypes (classMap, initializer, implementsOrExtends);
}
}
}

View File

@ -0,0 +1,90 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.annotation.MultipartConfig;
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.Descriptor;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* MultiPartConfigAnnotationHandler
*
*
*/
public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnnotationHandler
{
protected WebAppContext _context;
public MultiPartConfigAnnotationHandler(WebAppContext context)
{
//TODO verify that MultipartConfig is not inheritable
super(false);
_context = context;
}
/**
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
*/
public void doHandle(Class clazz)
{
if (!Servlet.class.isAssignableFrom(clazz))
return;
MultipartConfig multi = (MultipartConfig) clazz.getAnnotation(MultipartConfig.class);
if (multi == null)
return;
MetaData metaData = _context.getMetaData();
//TODO: The MultipartConfigElement needs to be set on the ServletHolder's Registration.
//How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig
//annotation applies to all declared instances in web.xml/programmatically?
//Assuming TRUE for now.
ServletHolder holder = getServletHolderForClass(clazz);
if (holder != null)
{
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config");
//if a descriptor has already set the value for multipart config, do not
//let the annotation override it
if (d == null)
{
metaData.setOrigin(holder.getName()+".servlet.multipart-config");
holder.getRegistration().setMultipartConfig(new MultipartConfigElement(multi));
}
}
}
private ServletHolder getServletHolderForClass (Class clazz)
{
ServletHolder holder = null;
ServletHolder[] holders = _context.getServletHandler().getServlets();
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName().equals(clazz.getName()))
{
holder = h;
}
}
}
return holder;
}
}

View File

@ -0,0 +1,291 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* ServletSecurityAnnotationHandler
*
* Inspect a class to see if it has an @ServletSecurity annotation on it,
* setting up the <security-constraint>s.
*
* A servlet can be defined in:
* <ul>
* <li>web.xml
* <li>web-fragment.xml
* <li>@WebServlet annotation discovered
* <li>ServletContext.createServlet
* </ul>
*
* The ServletSecurity annotation for a servlet should only be processed
* iff metadata-complete == false.
*/
public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnnotationHandler
{
private WebAppContext _context;
public ServletSecurityAnnotationHandler(WebAppContext wac)
{
super(false);
_context = wac;
}
/**
* @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class)
*/
public void doHandle(Class clazz)
{
if (!(_context.getSecurityHandler() instanceof ConstraintAware))
{
Log.warn("SecurityHandler not ConstraintAware, skipping security annotation processing");
return;
}
ServletSecurity servletSecurity = (ServletSecurity)clazz.getAnnotation(ServletSecurity.class);
if (servletSecurity == null)
return;
//If there are already constraints defined (ie from web.xml or programmatically(?)) that match any
//of the url patterns defined for this servlet, then skip the security annotation.
List<ServletMapping> servletMappings = getServletMappings(clazz.getCanonicalName());
List<ConstraintMapping> constraintMappings = ((ConstraintAware)_context.getSecurityHandler()).getConstraintMappings();
if (constraintsExist(servletMappings, constraintMappings))
{
Log.warn("Constraints already defined for "+clazz.getName()+", skipping ServletSecurity annotation");
return;
}
//Make a fresh list
constraintMappings = new ArrayList<ConstraintMapping>();
//Get the values that form the constraints that will apply unless there are HttpMethodConstraints to augment them
HttpConstraint defaults = servletSecurity.value();
//Make a Constraint for the <auth-constraint> and <user-data-constraint> specified by the HttpConstraint
Constraint defaultConstraint = makeConstraint (clazz,
defaults.rolesAllowed(),
defaults.value(),
defaults.transportGuarantee());
constraintMappings.addAll(makeMethodMappings(clazz,
defaultConstraint,
servletMappings,
servletSecurity.httpMethodConstraints()));
//set up the security constraints produced by the annotation
ConstraintAware securityHandler = (ConstraintAware)_context.getSecurityHandler();
for (ConstraintMapping m:constraintMappings)
securityHandler.addConstraintMapping(m);
}
/**
* Make a jetty Constraint object, which represents the <auth-constraint> and
* <user-data-constraint> elements, based on the security annotation.
* @param servlet
* @param rolesAllowed
* @param permitOrDeny
* @param transport
* @return
*/
protected Constraint makeConstraint (Class servlet, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport)
{
Constraint constraint = new Constraint();
if (rolesAllowed == null || rolesAllowed.length==0)
{
if (permitOrDeny.equals(EmptyRoleSemantic.DENY))
{
//Equivalent to <auth-constraint> with no roles
constraint.setName(servlet.getName()+"-Deny");
constraint.setAuthenticate(true);
}
else
{
//Equivalent to no <auth-constraint>
constraint.setAuthenticate(false);
constraint.setName(servlet.getName()+"-Permit");
}
}
else
{
//Equivalent to <auth-constraint> with list of <security-role-name>s
constraint.setAuthenticate(true);
constraint.setRoles(rolesAllowed);
constraint.setName(servlet.getName()+"-RolesAllowed");
}
//Equivalent to //<user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint>
constraint.setDataConstraint((transport.equals(TransportGuarantee.CONFIDENTIAL)?Constraint.DC_CONFIDENTIAL:Constraint.DC_NONE));
return constraint;
}
/**
* Make a ConstraintMapping which captures the <http-method> or <http-method-omission> elements for a particular url pattern,
* and relates it to a Constraint object (<auth-constraint> and <user-data-constraint>).
* @param constraint
* @param url
* @param method
* @param omissions
* @return
*/
protected ConstraintMapping makeConstraintMapping (Constraint constraint, String url, String method, String[] omissions)
{
ConstraintMapping mapping = new ConstraintMapping();
mapping.setConstraint(constraint);
mapping.setPathSpec(url);
if (method != null)
mapping.setMethod(method);
if (omissions != null)
mapping.setMethodOmissions(omissions);
return mapping;
}
/**
* Make the Jetty Constraints and ConstraintMapping objects that correspond to the HttpMethodConstraint
* annotations for each url pattern for the servlet.
* @param servlet
* @param defaultConstraint
* @param servletMappings
* @param annotations
* @return
*/
protected List<ConstraintMapping> makeMethodMappings (Class servlet, Constraint defaultConstraint, List<ServletMapping> servletMappings, HttpMethodConstraint[] annotations)
{
List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
//for each url-pattern existing for the servlet make a ConstraintMapping for the HttpConstraint, and ConstraintMappings for
//each HttpMethodConstraint
for (ServletMapping sm : servletMappings)
{
for (String url : sm.getPathSpecs())
{
//Make a ConstraintMapping that matches the defaultConstraint
ConstraintMapping defaultMapping = makeConstraintMapping(defaultConstraint, url, null, null);
//If there are HttpMethodConstraint annotations, make a Constraint and a ConstraintMapping for it
if (annotations != null && annotations.length>0)
{
List<String> omissions = new ArrayList<String>();
//for each HttpMethodConstraint annotation, make a new Constraint and ConstraintMappings for this url
for (int i=0; i < annotations.length;i++)
{
//Make a Constraint that captures the <auth-constraint> and <user-data-constraint> elements
Constraint methodConstraint = makeConstraint(servlet,
annotations[i].rolesAllowed(),
annotations[i].emptyRoleSemantic(),
annotations[i].transportGuarantee());
//Make ConstraintMapping that captures the <http-method> elements
ConstraintMapping methodConstraintMapping = makeConstraintMapping (methodConstraint,
url,annotations[i].value(),
null);
mappings.add(methodConstraintMapping);
omissions.add(annotations[i].value());
}
defaultMapping.setMethodOmissions(omissions.toArray(new String[0]));
}
//add the constraint mapping containing the http-method-omissions, if there are any
mappings.add(defaultMapping);
}
}
return mappings;
}
/**
* Get the ServletMappings for the servlet's class.
* @param className
* @return
*/
protected List<ServletMapping> getServletMappings(String className)
{
List<ServletMapping> results = new ArrayList<ServletMapping>();
ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
for (ServletMapping mapping : mappings)
{
//Check the name of the servlet that this mapping applies to, and then find the ServletHolder for it to find it's class
ServletHolder holder = _context.getServletHandler().getServlet(mapping.getServletName());
if (holder.getClassName().equals(className))
results.add(mapping);
}
return results;
}
/**
* Check if there are already <security-constraint> elements defined that match the url-patterns for
* the servlet.
* @param servletMappings
* @return
*/
protected boolean constraintsExist (List<ServletMapping> servletMappings, List<ConstraintMapping> constraintMappings)
{
boolean exists = false;
//Check to see if the path spec on each constraint mapping matches a pathSpec in the servlet mappings.
//If it does, then we should ignore the security annotations.
for (ServletMapping mapping : servletMappings)
{
//Get its url mappings
String[] pathSpecs = mapping.getPathSpecs();
if (pathSpecs == null)
continue;
//Check through the constraints to see if there are any whose pathSpecs (url mappings)
//match the servlet. If so, then we already have constraints defined for this servlet,
//and we will not be processing the annotation (ie web.xml or programmatic override).
for (int i=0; constraintMappings != null && i < constraintMappings.size() && !exists; i++)
{
for (int j=0; j < pathSpecs.length; j++)
{
if (pathSpecs[j].equals(constraintMappings.get(i).getPathSpec()))
{
exists = true;
break;
}
}
}
}
return exists;
}
}

View File

@ -56,7 +56,8 @@ public class Util
javax.servlet.ServletRequestListener.class.isAssignableFrom(c) ||
javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) ||
javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) ||
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c))
javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c) ||
javax.servlet.AsyncListener.class.isAssignableFrom(c))
isServlet=true;

View File

@ -0,0 +1,210 @@
// ========================================================================
// Copyright (c) 2010 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.annotations;
import java.util.ArrayList;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.Origin;
/**
* WebFilterAnnotation
*
*
*/
public class WebFilterAnnotation extends DiscoveredAnnotation
{
/**
* @param context
* @param className
*/
public WebFilterAnnotation(WebAppContext context, String className)
{
super(context, className);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
*/
public void apply()
{
// TODO verify against rules for annotation v descriptor
Class clazz = getTargetClass();
if (clazz == null)
{
Log.warn(_className+" cannot be loaded");
return;
}
//Servlet Spec 8.1.2
if (!Filter.class.isAssignableFrom(clazz))
{
Log.warn(clazz.getName()+" is not assignable from javax.servlet.Filter");
return;
}
MetaData metaData = _context.getMetaData();
WebFilter filterAnnotation = (WebFilter)clazz.getAnnotation(WebFilter.class);
if (filterAnnotation.value().length > 0 && filterAnnotation.urlPatterns().length > 0)
{
Log.warn(clazz.getName()+" defines both @WebFilter.value and @WebFilter.urlPatterns");
return;
}
String name = (filterAnnotation.filterName().equals("")?clazz.getName():filterAnnotation.filterName());
String[] urlPatterns = filterAnnotation.value();
if (urlPatterns.length == 0)
urlPatterns = filterAnnotation.urlPatterns();
FilterHolder holder = _context.getServletHandler().getFilter(name);
if (holder == null)
{
//Filter with this name does not already exist, so add it
holder = _context.getServletHandler().newFilterHolder(Holder.Source.ANNOTATION);
holder.setName(name);
holder.setHeldClass(clazz);
metaData.setOrigin(name+".filter.filter-class");
holder.setDisplayName(filterAnnotation.displayName());
metaData.setOrigin(name+".filter.display-name");
for (WebInitParam ip: filterAnnotation.initParams())
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(name+".filter.init-param."+ip.name());
}
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
if (urlPatterns.length > 0)
{
ArrayList paths = new ArrayList();
for (String s:urlPatterns)
{
paths.add(Util.normalizePattern(s));
}
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
}
if (filterAnnotation.servletNames().length > 0)
{
ArrayList<String> names = new ArrayList<String>();
for (String s : filterAnnotation.servletNames())
{
names.add(s);
}
mapping.setServletNames((String[])names.toArray(new String[names.size()]));
}
EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
for (DispatcherType d : filterAnnotation.dispatcherTypes())
{
dispatcherSet.add(d);
}
mapping.setDispatcherTypes(dispatcherSet);
metaData.setOrigin(name+".filter.mappings");
holder.setAsyncSupported(filterAnnotation.asyncSupported());
metaData.setOrigin(name+".filter.async-supported");
_context.getServletHandler().addFilter(holder);
_context.getServletHandler().addFilterMapping(mapping);
}
else
{
//A Filter definition for the same name already exists from web.xml
//ServletSpec 3.0 p81 if the Filter is already defined and has mappings,
//they override the annotation. If it already has DispatcherType set, that
//also overrides the annotation. Init-params are additive, but web.xml overrides
//init-params of the same name.
for (WebInitParam ip: filterAnnotation.initParams())
{
//if (holder.getInitParameter(ip.name()) == null)
if (metaData.getOrigin(name+".filter.init-param."+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(name+".filter.init-param."+ip.name());
}
}
FilterMapping[] mappings = _context.getServletHandler().getFilterMappings();
boolean mappingExists = false;
if (mappings != null)
{
for (FilterMapping m:mappings)
{
if (m.getFilterName().equals(name))
{
mappingExists = true;
break;
}
}
}
//if a descriptor didn't specify at least one mapping, use the mappings from the annotation and the DispatcherTypes
//from the annotation
if (!mappingExists)
{
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
if (urlPatterns.length > 0)
{
ArrayList paths = new ArrayList();
for (String s:urlPatterns)
{
paths.add(Util.normalizePattern(s));
}
mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
}
if (filterAnnotation.servletNames().length > 0)
{
ArrayList<String> names = new ArrayList<String>();
for (String s : filterAnnotation.servletNames())
{
names.add(s);
}
mapping.setServletNames((String[])names.toArray(new String[names.size()]));
}
EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
for (DispatcherType d : filterAnnotation.dispatcherTypes())
{
dispatcherSet.add(d);
}
mapping.setDispatcherTypes(dispatcherSet);
_context.getServletHandler().addFilterMapping(mapping);
metaData.setOrigin(name+".filter.mappings");
}
}
}
}

View File

@ -0,0 +1,55 @@
// ========================================================================
// Copyright (c) 2009-2010 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.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* WebFilterAnnotationHandler
*
*
*/
public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHandler
{
public WebFilterAnnotationHandler (WebAppContext context)
{
super(context);
}
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className);
addAnnotation(wfAnnotation);
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
Log.warn ("@WebFilter not applicable for fields: "+className+"."+fieldName);
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
Log.warn ("@WebFilter not applicable for methods: "+className+"."+methodName+" "+signature);
}
}

View File

@ -0,0 +1,83 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionListener;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.Origin;
/**
* WebListenerAnnotation
*
*
*/
public class WebListenerAnnotation extends DiscoveredAnnotation
{
/**
* @param context
* @param className
*/
public WebListenerAnnotation(WebAppContext context, String className)
{
super(context, className);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
*/
public void apply()
{
// TODO check algorithm against ordering rules for descriptors v annotations
Class clazz = getTargetClass();
if (clazz == null)
{
Log.warn(_className+" cannot be loaded");
return;
}
try
{
if (ServletContextListener.class.isAssignableFrom(clazz) ||
ServletContextAttributeListener.class.isAssignableFrom(clazz) ||
ServletRequestListener.class.isAssignableFrom(clazz) ||
ServletRequestAttributeListener.class.isAssignableFrom(clazz) ||
HttpSessionListener.class.isAssignableFrom(clazz) ||
HttpSessionAttributeListener.class.isAssignableFrom(clazz))
{
java.util.EventListener listener = (java.util.EventListener)clazz.newInstance();
MetaData metaData = _context.getMetaData();
if (metaData.getOrigin(clazz.getName()+".listener") == Origin.NotSet)
_context.addEventListener(listener);
}
else
Log.warn(clazz.getName()+" does not implement one of the servlet listener interfaces");
}
catch (Exception e)
{
Log.warn(e);
}
}
}

View File

@ -0,0 +1,50 @@
// ========================================================================
// Copyright (c) 2009-2010 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.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.WebAppContext;
public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotationHandler
{
public WebListenerAnnotationHandler (WebAppContext context)
{
super(context);
}
/**
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className);
addAnnotation(wlAnnotation);
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
Log.warn ("@WebListener is not applicable to fields: "+className+"."+fieldName);
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
Log.warn ("@WebListener is not applicable to methods: "+className+"."+methodName+" "+signature);
}
}

View File

@ -0,0 +1,169 @@
// ========================================================================
// Copyright (c) 2010 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.annotations;
import java.util.ArrayList;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.Origin;
/**
* WebServletAnnotation
*
*
*/
public class WebServletAnnotation extends DiscoveredAnnotation
{
public WebServletAnnotation (WebAppContext context, String className)
{
super(context, className);
}
/**
* @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
*/
public void apply()
{
//TODO check this algorithm with new rules for applying descriptors and annotations in order
Class clazz = getTargetClass();
if (clazz == null)
{
Log.warn(_className+" cannot be loaded");
return;
}
//Servlet Spec 8.1.1
if (!HttpServlet.class.isAssignableFrom(clazz))
{
Log.warn(clazz.getName()+" is not assignable from javax.servlet.http.HttpServlet");
return;
}
WebServlet annotation = (WebServlet)clazz.getAnnotation(WebServlet.class);
if (annotation.urlPatterns().length > 0 && annotation.value().length > 0)
{
Log.warn(clazz.getName()+ " defines both @WebServlet.value and @WebServlet.urlPatterns");
return;
}
String[] urlPatterns = annotation.value();
if (urlPatterns.length == 0)
urlPatterns = annotation.urlPatterns();
if (urlPatterns.length == 0)
{
Log.warn(clazz.getName()+ " defines neither @WebServlet.value nor @WebServlet.urlPatterns");
return;
}
//canonicalize the patterns
ArrayList<String> urlPatternList = new ArrayList<String>();
for (String p : urlPatterns)
urlPatternList.add(Util.normalizePattern(p));
String servletName = (annotation.name().equals("")?clazz.getName():annotation.name());
MetaData metaData = _context.getMetaData();
//Find out if a <servlet> of this type already exists with this name
ServletHolder[] holders = _context.getServletHandler().getServlets();
boolean isNew = true;
ServletHolder holder = null;
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName().equals(clazz.getName()) && h.getName().equals(servletName))
{
holder = h;
isNew = false;
break;
}
}
}
if (isNew)
{
//No servlet of this name has already been defined, either by a descriptor
//or another annotation (which would be impossible).
holder = _context.getServletHandler().newServletHolder(Holder.Source.ANNOTATION);
holder.setHeldClass(clazz);
metaData.setOrigin(servletName+".servlet.servlet-class");
holder.setName(servletName);
holder.setDisplayName(annotation.displayName());
metaData.setOrigin(servletName+".servlet.display-name");
holder.setInitOrder(annotation.loadOnStartup());
metaData.setOrigin(servletName+".servlet.load-on-startup");
holder.setAsyncSupported(annotation.asyncSupported());
metaData.setOrigin(servletName+".servlet.async-supported");
for (WebInitParam ip:annotation.initParams())
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
}
_context.getServletHandler().addServlet(holder);
ServletMapping mapping = new ServletMapping();
mapping.setServletName(holder.getName());
mapping.setPathSpecs( LazyList.toStringArray(urlPatternList));
_context.getServletHandler().addServletMapping(mapping);
metaData.setOrigin(servletName+".servlet.mappings");
}
else
{
//check if the existing servlet has each init-param from the annotation
//if not, add it
for (WebInitParam ip:annotation.initParams())
{
//if (holder.getInitParameter(ip.name()) == null)
if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
}
}
//check the url-patterns, if there annotation has a new one, add it
ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
//ServletSpec 3.0 p81 If a servlet already has url mappings from a
//descriptor the annotation is ignored
if (mappings == null && metaData.getOriginDescriptor(servletName+".servlet.mappings") != null)
{
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servletName);
mapping.setPathSpecs(LazyList.toStringArray(urlPatternList));
_context.getServletHandler().addServletMapping(mapping);
}
}
}
}

View File

@ -0,0 +1,66 @@
// ========================================================================
// Copyright (c) 2009 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.annotations;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* WebServletAnnotationHandler
*
* Process a WebServlet annotation on a class.
*
*/
public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationHandler
{
public WebServletAnnotationHandler (WebAppContext context)
{
super(context);
}
/**
* Handle discovering a WebServlet annotation.
*
*
* @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
*/
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
List<Value> values)
{
if (!"javax.servlet.annotation.WebServlet".equals(annotationName))
return;
WebServletAnnotation annotation = new WebServletAnnotation (_context, className);
addAnnotation(annotation);
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
List<Value> values)
{
Log.warn ("@WebServlet annotation not supported for fields");
}
public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
List<Value> values)
{
Log.warn ("@WebServlet annotation not supported for methods");
}
}

View File

@ -18,16 +18,20 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.security.RunAs;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@WebFilter(filterName="CFilter", dispatcherTypes={DispatcherType.REQUEST}, urlPatterns = {"/*"}, initParams={@WebInitParam(name="a", value="99")}, asyncSupported=false)
@RunAs("admin")
public class FilterC implements Filter
{

View File

@ -14,7 +14,9 @@ package org.eclipse.jetty.annotations;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ListenerC implements ServletContextListener
{

View File

@ -20,6 +20,12 @@ import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RunAs;
import javax.servlet.ServletException;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -27,7 +33,10 @@ import javax.servlet.http.HttpServletResponse;
@DeclareRoles({"alice"})
@WebServlet(urlPatterns = { "/foo/*", "/bah/*" }, name="CServlet", initParams={@WebInitParam(name="x", value="y")}, loadOnStartup=2, asyncSupported=false)
@MultipartConfig(fileSizeThreshold=1000, maxFileSize=2000, maxRequestSize=3000)
@RunAs("admin")
@ServletSecurity(value=@HttpConstraint(rolesAllowed={"fred", "bill", "dorothy"}), httpMethodConstraints={@HttpMethodConstraint(value="GET", rolesAllowed={"bob", "carol", "ted"})})
public class ServletC extends HttpServlet
{
@Resource (mappedName="foo", type=Double.class)

View File

@ -0,0 +1,53 @@
// ========================================================================
// Copyright (c) 2006-2009 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.annotations;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import junit.framework.TestCase;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.FragmentDescriptor;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* TestAnnotationConfiguration
*
*
*/
public class TestAnnotationConfiguration extends TestCase
{
public void testGetFragmentFromJar ()
throws Exception
{
String dir = System.getProperty("basedir", ".");
File file = new File(dir);
file=new File(file.getCanonicalPath());
URL url=file.toURL();
Resource jar1 = Resource.newResource(url+"file.jar");
AnnotationConfiguration config = new AnnotationConfiguration();
WebAppContext wac = new WebAppContext();
List<FragmentDescriptor> frags = new ArrayList<FragmentDescriptor>();
frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file.jar!/fooa.props")));
frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file2.jar!/foob.props")));
assertNotNull(config.getFragmentFromJar(jar1, frags));
}
}

View File

@ -13,20 +13,23 @@
package org.eclipse.jetty.annotations;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
import org.eclipse.jetty.util.MultiMap;
import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/**
*
*/
@ -186,4 +189,40 @@ public class TestAnnotationInheritance
});
assertEquals (1, handler.annotatedClassNames.size());
}
@Test
public void testTypeInheritanceHandling() throws Exception
{
AnnotationParser parser = new AnnotationParser();
ClassInheritanceHandler handler = new ClassInheritanceHandler();
parser.registerClassHandler(handler);
class Foo implements InterfaceD
{
}
classNames.clear();
classNames.add(ClassA.class.getName());
classNames.add(ClassB.class.getName());
classNames.add(InterfaceD.class.getName());
classNames.add(Foo.class.getName());
parser.parse(classNames, null);
MultiMap map = handler.getMap();
assertNotNull(map);
assertFalse(map.isEmpty());
assertEquals(2, map.size());
Map stringArrayMap = map.toStringArrayMap();
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA");
assertEquals(1, classes.length);
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD");
assertEquals(2, classes.length);
assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
assertEquals(Foo.class.getName(), classes[1]);
}
}

View File

@ -0,0 +1,328 @@
// ========================================================================
// Copyright (c) 2009 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.annotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.annotation.HttpConstraint;
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
import javax.servlet.http.HttpServlet;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.webapp.WebAppContext;
import junit.framework.TestCase;
public class TestSecurityAnnotationConversions extends TestCase
{
@ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.DENY))
public static class DenyServlet extends HttpServlet
{}
@ServletSecurity
public static class PermitServlet extends HttpServlet
{}
@ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}))
public static class RolesServlet extends HttpServlet
{}
@ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}),
httpMethodConstraints={@HttpMethodConstraint(value="GET")})
public static class Method1Servlet extends HttpServlet
{}
@ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}),
httpMethodConstraints={@HttpMethodConstraint(value="GET", transportGuarantee=TransportGuarantee.CONFIDENTIAL)})
public static class Method2Servlet extends HttpServlet
{}
public void setUp()
{
}
public void testDenyAllOnClass ()
throws Exception
{
WebAppContext wac = makeWebAppContext(DenyServlet.class.getCanonicalName(), "denyServlet", new String[]{"/foo/*", "*.foo"});
//Assume we found 1 servlet with a @HttpConstraint with value=EmptyRoleSemantic.DENY security annotation
ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
AnnotationIntrospector introspector = new AnnotationIntrospector();
introspector.registerHandler(annotationHandler);
//set up the expected outcomes:
//1 ConstraintMapping per ServletMapping pathSpec
Constraint expectedConstraint = new Constraint();
expectedConstraint.setAuthenticate(true);
expectedConstraint.setDataConstraint(Constraint.DC_NONE);
ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
expectedMappings[0] = new ConstraintMapping();
expectedMappings[0].setConstraint(expectedConstraint);
expectedMappings[0].setPathSpec("/foo/*");
expectedMappings[1] = new ConstraintMapping();
expectedMappings[1].setConstraint(expectedConstraint);
expectedMappings[1].setPathSpec("*.foo");
introspector.introspect(DenyServlet.class);
compareResults(expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
}
public void testPermitAll()
throws Exception
{
//Assume we found 1 servlet with a @ServletSecurity security annotation
WebAppContext wac = makeWebAppContext(PermitServlet.class.getCanonicalName(), "permitServlet", new String[]{"/foo/*", "*.foo"});
ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
AnnotationIntrospector introspector = new AnnotationIntrospector();
introspector.registerHandler(annotationHandler);
//set up the expected outcomes:
//1 ConstraintMapping per ServletMapping pathSpec
Constraint expectedConstraint = new Constraint();
expectedConstraint.setAuthenticate(false);
expectedConstraint.setDataConstraint(Constraint.DC_NONE);
ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
expectedMappings[0] = new ConstraintMapping();
expectedMappings[0].setConstraint(expectedConstraint);
expectedMappings[0].setPathSpec("/foo/*");
expectedMappings[1] = new ConstraintMapping();
expectedMappings[1].setConstraint(expectedConstraint);
expectedMappings[1].setPathSpec("*.foo");
introspector.introspect(PermitServlet.class);
compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
}
public void testRolesAllowedWithTransportGuarantee ()
throws Exception
{
//Assume we found 1 servlet with annotation with roles defined and
//and a TransportGuarantee
WebAppContext wac = makeWebAppContext(RolesServlet.class.getCanonicalName(), "rolesServlet", new String[]{"/foo/*", "*.foo"});
ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
AnnotationIntrospector introspector = new AnnotationIntrospector();
introspector.registerHandler(annotationHandler);
//set up the expected outcomes:compareResults
//1 ConstraintMapping per ServletMapping
Constraint expectedConstraint = new Constraint();
expectedConstraint.setAuthenticate(true);
expectedConstraint.setRoles(new String[]{"tom", "dick", "harry"});
expectedConstraint.setDataConstraint(Constraint.DC_CONFIDENTIAL);
ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
expectedMappings[0] = new ConstraintMapping();
expectedMappings[0].setConstraint(expectedConstraint);
expectedMappings[0].setPathSpec("/foo/*");
expectedMappings[1] = new ConstraintMapping();
expectedMappings[1].setConstraint(expectedConstraint);
expectedMappings[1].setPathSpec("*.foo");
introspector.introspect(RolesServlet.class);
compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
}
public void testMethodAnnotation ()
throws Exception
{
//ServletSecurity annotation with HttpConstraint of TransportGuarantee.CONFIDENTIAL, and a list of rolesAllowed, and
//a HttpMethodConstraint for GET method that permits all and has TransportGuarantee.NONE (ie is default)
WebAppContext wac = makeWebAppContext(Method1Servlet.class.getCanonicalName(), "method1Servlet", new String[]{"/foo/*", "*.foo"});
//set up the expected outcomes: - a Constraint for the RolesAllowed on the class
//with userdata constraint of DC_CONFIDENTIAL
//and mappings for each of the pathSpecs
Constraint expectedConstraint1 = new Constraint();
expectedConstraint1.setAuthenticate(true);
expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"});
expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL);
//a Constraint for the PermitAll on the doGet method with a userdata
//constraint of DC_CONFIDENTIAL inherited from the class
Constraint expectedConstraint2 = new Constraint();
expectedConstraint2.setDataConstraint(Constraint.DC_NONE);
ConstraintMapping[] expectedMappings = new ConstraintMapping[4];
expectedMappings[0] = new ConstraintMapping();
expectedMappings[0].setConstraint(expectedConstraint1);
expectedMappings[0].setPathSpec("/foo/*");
expectedMappings[0].setMethodOmissions(new String[]{"GET"});
expectedMappings[1] = new ConstraintMapping();
expectedMappings[1].setConstraint(expectedConstraint1);
expectedMappings[1].setPathSpec("*.foo");
expectedMappings[1].setMethodOmissions(new String[]{"GET"});
expectedMappings[2] = new ConstraintMapping();
expectedMappings[2].setConstraint(expectedConstraint2);
expectedMappings[2].setPathSpec("/foo/*");
expectedMappings[2].setMethod("GET");
expectedMappings[3] = new ConstraintMapping();
expectedMappings[3].setConstraint(expectedConstraint2);
expectedMappings[3].setPathSpec("*.foo");
expectedMappings[3].setMethod("GET");
AnnotationIntrospector introspector = new AnnotationIntrospector();
ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
introspector.registerHandler(annotationHandler);
introspector.introspect(Method1Servlet.class);
compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
}
public void testMethodAnnotation2 ()
throws Exception
{
//A ServletSecurity annotation that has HttpConstraint of CONFIDENTIAL with defined roles, but a
//HttpMethodConstraint for GET that permits all, but also requires CONFIDENTIAL
WebAppContext wac = makeWebAppContext(Method2Servlet.class.getCanonicalName(), "method2Servlet", new String[]{"/foo/*", "*.foo"});
AnnotationIntrospector introspector = new AnnotationIntrospector();
ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
introspector.registerHandler(annotationHandler);
//set up the expected outcomes: - a Constraint for the RolesAllowed on the class
//with userdata constraint of DC_CONFIDENTIAL
//and mappings for each of the pathSpecs
Constraint expectedConstraint1 = new Constraint();
expectedConstraint1.setAuthenticate(true);
expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"});
expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL);
//a Constraint for the Permit on the GET method with a userdata
//constraint of DC_CONFIDENTIAL
Constraint expectedConstraint2 = new Constraint();
expectedConstraint2.setDataConstraint(Constraint.DC_CONFIDENTIAL);
ConstraintMapping[] expectedMappings = new ConstraintMapping[4];
expectedMappings[0] = new ConstraintMapping();
expectedMappings[0].setConstraint(expectedConstraint1);
expectedMappings[0].setPathSpec("/foo/*");
expectedMappings[0].setMethodOmissions(new String[]{"GET"});
expectedMappings[1] = new ConstraintMapping();
expectedMappings[1].setConstraint(expectedConstraint1);
expectedMappings[1].setPathSpec("*.foo");
expectedMappings[1].setMethodOmissions(new String[]{"GET"});
expectedMappings[2] = new ConstraintMapping();
expectedMappings[2].setConstraint(expectedConstraint2);
expectedMappings[2].setPathSpec("/foo/*");
expectedMappings[2].setMethod("GET");
expectedMappings[3] = new ConstraintMapping();
expectedMappings[3].setConstraint(expectedConstraint2);
expectedMappings[3].setPathSpec("*.foo");
expectedMappings[3].setMethod("GET");
introspector.introspect(Method2Servlet.class);
compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
}
private void compareResults (ConstraintMapping[] expectedMappings, List<ConstraintMapping> actualMappings)
{
assertNotNull(actualMappings);
assertEquals(expectedMappings.length, actualMappings.size());
for (int k=0; k < actualMappings.size(); k++)
{
ConstraintMapping am = actualMappings.get(k);
boolean matched = false;
for (int i=0; i< expectedMappings.length && !matched; i++)
{
ConstraintMapping em = expectedMappings[i];
if (em.getPathSpec().equals(am.getPathSpec()))
{
if ((em.getMethod()==null && am.getMethod() == null) || em.getMethod() != null && em.getMethod().equals(am.getMethod()))
{
matched = true;
assertEquals(em.getConstraint().getAuthenticate(), am.getConstraint().getAuthenticate());
assertEquals(em.getConstraint().getDataConstraint(), am.getConstraint().getDataConstraint());
if (em.getMethodOmissions() == null)
{
assertNull(am.getMethodOmissions());
}
else
{
assertTrue(Arrays.equals(am.getMethodOmissions(), em.getMethodOmissions()));
}
if (em.getConstraint().getRoles() == null)
{
assertNull(am.getConstraint().getRoles());
}
else
{
assertTrue(Arrays.equals(em.getConstraint().getRoles(), am.getConstraint().getRoles()));
}
}
}
}
if (!matched)
fail("No expected ConstraintMapping matching method:"+am.getMethod()+" pathSpec: "+am.getPathSpec());
}
}
private WebAppContext makeWebAppContext (String className, String servletName, String[] paths)
{
WebAppContext wac = new WebAppContext();
ServletHolder[] holders = new ServletHolder[1];
holders[0] = new ServletHolder();
holders[0].setClassName(className);
holders[0].setName(servletName);
holders[0].setServletHandler(wac.getServletHandler());
wac.getServletHandler().setServlets(holders);
wac.setSecurityHandler(new ConstraintSecurityHandler());
ServletMapping[] servletMappings = new ServletMapping[1];
servletMappings[0] = new ServletMapping();
servletMappings[0].setPathSpecs(paths);
servletMappings[0].setServletName(servletName);
wac.getServletHandler().setServletMappings(servletMappings);
return wac;
}
}

View File

@ -1,5 +1,5 @@
// ========================================================================
//Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// Copyright (c) 2006-2009 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
@ -13,12 +13,19 @@
package org.eclipse.jetty.annotations;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Test;
@ -29,8 +36,50 @@ import org.junit.Test;
*/
public class TestServletAnnotations
{
@Test
public void testServletAnnotation() throws Exception
{
List<String> classes = new ArrayList<String>();
classes.add("org.eclipse.jetty.annotations.ServletC");
AnnotationParser parser = new AnnotationParser();
WebAppContext wac = new WebAppContext();
WebServletAnnotationHandler handler = new WebServletAnnotationHandler(wac);
parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", handler);
parser.parse(classes, new ClassNameResolver ()
{
public boolean isExcluded(String name)
{
return false;
}
public boolean shouldOverride(String name)
{
return false;
}
});
assertEquals(1, handler.getAnnotationList().size());
assertTrue(handler.getAnnotationList().get(0) instanceof WebServletAnnotation);
handler.getAnnotationList().get(0).apply();
ServletHolder[] holders = wac.getServletHandler().getServlets();
assertNotNull(holders);
assertEquals(1, holders.length);
assertEquals("CServlet", holders[0].getName());
ServletMapping[] mappings = wac.getServletHandler().getServletMappings();
assertNotNull(mappings);
assertEquals(1, mappings.length);
String[] paths = mappings[0].getPathSpecs();
assertNotNull(paths);
assertEquals(2, paths.length);
assertEquals("y", holders[0].getInitParameter("x"));
assertEquals(2,holders[0].getInitOrder());
assertFalse(holders[0].isAsyncSupported());
}
public void testDeclareRoles ()
throws Exception
{

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -16,11 +16,13 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.ByteArrayBuffer;

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
@ -64,11 +64,11 @@
</build>
<dependencies>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0.20100224</version>
<scope>provided</scope>
</dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<version>${servlet.spec.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-util</artifactId>

View File

@ -36,7 +36,7 @@ public class ContinuationSupport
static
{
boolean servlet3Support=false;
Constructor<? extends Continuation>s3cc=null;
Constructor<?>s3cc=null;
try
{
boolean servlet3=ServletRequest.class.getMethod("startAsync")!=null;
@ -52,11 +52,11 @@ public class ContinuationSupport
finally
{
__servlet3=servlet3Support;
__newServlet3Continuation=s3cc;
__newServlet3Continuation=(Constructor<? extends Continuation>)s3cc;
}
boolean jetty6Support=false;
Constructor<? extends Continuation>j6cc=null;
Constructor<?>j6cc=null;
try
{
Class<?> jetty6ContinuationClass = ContinuationSupport.class.getClassLoader().loadClass("org.mortbay.util.ajax.Continuation");
@ -73,7 +73,7 @@ public class ContinuationSupport
finally
{
__jetty6=jetty6Support;
__newJetty6Continuation=j6cc;
__newJetty6Continuation=(Constructor<? extends Continuation>)j6cc;
}
Class<?> waiting=null;

View File

@ -500,4 +500,4 @@ class FauxContinuation implements FilteredContinuation
throw new IllegalStateException("!suspended");
}
}
}

View File

@ -59,6 +59,7 @@ public class Servlet3Continuation implements Continuation
public void onTimeout(AsyncEvent event) throws IOException
{
_initial=false;
System.err.println("Doing dispatch on timed out continuation for "+_request.getAttribute("FOO"));
event.getAsyncContext().dispatch();
}
});

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -22,7 +22,7 @@
</Set>
<Call name="setContextAttribute">
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
<Arg>.*/jsp-api-[^/]*\.jar$|.*/jsp-[^/]*\.jar$</Arg>
<Arg>.*/servlet-api-[^/]*\.jar$</Arg>
</Call>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@ -12,18 +12,18 @@
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit</jetty-orbit-url>
<assembly-directory>target/distribution</assembly-directory>
<eclipse-ecj-version>3.6</eclipse-ecj-version>
<orbit-javax-activation-version>${javax-activation-version}.0.v201005080500</orbit-javax-activation-version>
<orbit-javax-annotation-version>1.0.0.v20100513-0750</orbit-javax-annotation-version>
<orbit-javax-el-version>2.1.0.v201004190952</orbit-javax-el-version>
<orbit-javax-activation-version>${javax-activation-version}.0.v201105071233</orbit-javax-activation-version>
<orbit-javax-annotation-version>1.1.0.v201105051105</orbit-javax-annotation-version>
<orbit-javax-el-version>2.2.0.v201105051105</orbit-javax-el-version>
<orbit-javax-mail-glassfish-version>${javax-mail-version}.v201005082020</orbit-javax-mail-glassfish-version>
<orbit-javax-servlet-version>2.5.0.v200910301333</orbit-javax-servlet-version>
<orbit-javax-servlet-jsp-version>2.1.0.v201004190952</orbit-javax-servlet-jsp-version>
<orbit-javax-servlet-version>3.0.0.v201103241727</orbit-javax-servlet-version>
<orbit-javax-servlet-jsp-version>2.2.0.v201103241009</orbit-javax-servlet-jsp-version>
<orbit-javax-servlet-jsp-jstl-version>1.2.0.v201004190952</orbit-javax-servlet-jsp-jstl-version>
<orbit-com-sun-el-version>1.0.0.v201004190952</orbit-com-sun-el-version>
<orbit-org-apache-jasper-version>2.1.0.v201007080150</orbit-org-apache-jasper-version>
<orbit-com-sun-el-version>2.2.0.v201105051105</orbit-com-sun-el-version>
<orbit-org-apache-taglibs-standard-version>1.2.0.v201004190952</orbit-org-apache-taglibs-standard-version>
<orbit-org-objectweb-asm-version>3.1.0.v200803061910</orbit-org-objectweb-asm-version>
<orbit-org-objectweb-asm-version>3.3.1.v201101071600</orbit-org-objectweb-asm-version>
<orbit-javax-transaction-version>1.1.1.v201004190952</orbit-javax-transaction-version>
<!-- >orbit-org-apache-jasper-version>2.1.0.v201007080150</orbit-org-apache-jasper-version -->
</properties>
<build>
<plugins>
@ -76,19 +76,17 @@
<url url="${jetty-orbit-url}/javax.servlet.jsp_${orbit-javax-servlet-jsp-version}.jar" />
<url url="${jetty-orbit-url}/javax.servlet.jsp.jstl_${orbit-javax-servlet-jsp-jstl-version}.jar" />
<url url="${jetty-orbit-url}/com.sun.el_${orbit-com-sun-el-version}.jar" />
<url url="${jetty-orbit-url}/org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" />
<!-- url url="${jetty-orbit-url}/org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" / -->
<url url="${jetty-orbit-url}/org.apache.taglibs.standard.glassfish_${orbit-org-apache-taglibs-standard-version}.jar" />
<url url="${jetty-orbit-url}/org.objectweb.asm_${orbit-org-objectweb-asm-version}.jar" />
<url url="${jetty-orbit-url}/javax.transaction_${orbit-javax-transaction-version}.jar" />
<url url="${jetty-orbit-url}/ecj-${eclipse-ecj-version}.jar" />
</get>
<!-- Step 2: copy the orbit artifact from orbit-cache to the appropriate lib directory -->
<!-- ${jetty.home}/lib/ -->
<mkdir dir="${assembly-directory}/lib" />
<copy file="${orbit-cache}/javax.servlet_${orbit-javax-servlet-version}.jar" tofile="${assembly-directory}/lib/servlet-api-2.5.jar" />
<!-- ${jetty.home}/lib/annotations/ -->
<mkdir dir="${assembly-directory}/lib/annotations" />
<copy todir="${assembly-directory}/lib/annotations">
@ -123,12 +121,10 @@
<include name="javax.servlet.jsp_${orbit-javax-servlet-jsp-version}.jar" />
<include name="javax.servlet.jsp.jstl_${orbit-javax-servlet-jsp-jstl-version}.jar" />
<include name="com.sun.el_${orbit-com-sun-el-version}.jar" />
<include name="org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" />
<include name="org.apache.taglibs.standard.glassfish_${orbit-org-apache-taglibs-standard-version}.jar" />
<include name="ecj-${eclipse-ecj-version}.jar" />
<!-- include name="org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" / -->
</fileset>
</copy>
<copy file="../VERSION.txt" todir="${assembly-directory}" />
<chmod dir="${assembly-directory}/bin" perm="755" includes="**/*.sh" />
</tasks>
@ -489,9 +485,19 @@
<outputDirectory>${assembly-directory}</outputDirectory>
<destFileName>start.jar</destFileName>
</artifactItem>
<artifactItem>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<version>${servlet.spec.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
<destFileName>servlet-api-3.0.jar</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
@ -509,11 +515,20 @@
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-impl</artifactId>
<version>2.2.2.b05.0</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**/**</includes>
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</artifactItem>
</artifactItems>
@ -620,9 +635,14 @@
<artifactId>jetty-policy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
<version>${servlet.spec.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@ -632,8 +652,13 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-impl</artifactId>
<version>2.2.2.b05.0</version>
</dependency>
</dependencies>
</project>

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>

View File

@ -18,10 +18,12 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -311,6 +313,23 @@ public class HttpFields
_maxCookieVersion=maxCookieVersion;
}
/* -------------------------------------------------------------- */
/**
* Get Collection of header names.
*/
public Collection<String> getFieldNamesCollection()
{
final List<String> list = new ArrayList<String>(_fields.size());
final int revision=_revision;
for (Field f : _fields)
{
if (f!=null && f._prev==null && f._revision==revision)
list.add(BufferUtil.to8859_1_String(f._name));
}
return list;
}
/* -------------------------------------------------------------- */
/**
* Get enumeration of header _names. Returns an enumeration of strings representing the header
@ -442,6 +461,32 @@ public class HttpFields
return null;
}
/* -------------------------------------------------------------- */
/**
* Get multi headers
*
* @return Enumeration of the values, or null if no such header.
* @param name the case-insensitive field name
*/
public Collection<String> getValuesCollection(String name)
{
Field field = getField(name);
if (field==null)
return null;
final int revision=_revision;
final List<String> list = new ArrayList<String>();
while(field!=null)
{
if (field._revision==revision)
list.add(field.getValue());
field=field._next;
}
return list;
}
/* -------------------------------------------------------------- */
/**
* Get multi headers
@ -1532,5 +1577,4 @@ public class HttpFields
return ("[" + (_prev == null ? "" : "<-") + getName() + "="+_revision+"=" + _value + (_next == null ? "" : "->") + "]");
}
}
}

View File

@ -49,7 +49,7 @@ public class HttpGeneratorClientTest
generator.completeHeader(fields,false);
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true);
generator.addContent(new ByteArrayBuffer(content),true);
generator.flushBuffer();
generator.complete();
generator.flushBuffer();
@ -74,7 +74,7 @@ public class HttpGeneratorClientTest
String content = "The quick brown fox jumped over the lazy dog";
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),true);
generator.addContent(new ByteArrayBuffer(content),true);
generator.completeHeader(fields,true);
generator.flushBuffer();
@ -103,7 +103,7 @@ public class HttpGeneratorClientTest
generator.completeHeader(fields,false);
generator.addContent(new ByteArrayBuffer(content).asMutableBuffer(),false);
generator.addContent(new ByteArrayBuffer(content),false);
generator.flushBuffer();
generator.complete();
generator.flushBuffer();

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>

View File

@ -26,8 +26,6 @@ import org.eclipse.jetty.util.log.Log;
*/
public abstract class AbstractBuffer implements Buffer
{
private final static boolean __boundsChecking = Boolean.getBoolean("org.eclipse.jetty.io.AbstractBuffer.boundsChecking");
protected final static String
__IMMUTABLE = "IMMUTABLE",
__READONLY = "READONLY",
@ -497,43 +495,37 @@ public abstract class AbstractBuffer implements Buffer
public void setGetIndex(int getIndex)
{
/* bounds checking */
if (__boundsChecking)
{
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (getIndex < 0)
throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0");
if (getIndex > putIndex())
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex());
}
/* bounds checking
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (getIndex < 0)
throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0");
if (getIndex > putIndex())
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex());
*/
_get = getIndex;
_hash=0;
}
public void setMarkIndex(int index)
{
/*
if (index>=0 && isImmutable())
throw new IllegalStateException(__IMMUTABLE);
*/
_mark = index;
}
public void setPutIndex(int putIndex)
{
if (__boundsChecking)
{
/* bounds checking */
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (putIndex > capacity())
/* bounds checking
if (isImmutable())
throw new IllegalStateException(__IMMUTABLE);
if (putIndex > capacity())
throw new IllegalArgumentException("putIndex>capacity: " + putIndex + ">" + capacity());
if (getIndex() > putIndex)
if (getIndex() > putIndex)
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex() + ">" + putIndex);
}
*/
_put = putIndex;
_hash=0;
}

View File

@ -370,8 +370,7 @@ public class ByteArrayBuffer extends AbstractBuffer
throws IOException
{
out.write(_bytes,getIndex(),length());
if (!isImmutable())
clear();
clear();
}
/* ------------------------------------------------------------ */

View File

@ -246,8 +246,7 @@ public class ByteArrayEndPoint implements ConnectedEndPoint
}
}
int len = _out.put(buffer);
if (!buffer.isImmutable())
buffer.skip(len);
buffer.skip(len);
return len;
}

View File

@ -0,0 +1,43 @@
// ========================================================================
// Copyright (c) 2009-2009 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.io;
/* ------------------------------------------------------------ */
/**
* Subclass of {@link java.lang.RuntimeException} used to signal that there
* was an {@link java.io.IOException} thrown by underlying {@link UncheckedPrintWriter}
*/
public class UncheckedIOException extends RuntimeException
{
public UncheckedIOException()
{
super();
}
public UncheckedIOException(String message)
{
super(message);
}
public UncheckedIOException(Throwable cause)
{
super(cause);
}
public UncheckedIOException(String message, Throwable cause)
{
super(message,cause);
}
}

View File

@ -104,7 +104,7 @@ public class UncheckedPrintWriter extends PrintWriter
{
setError();
if (_throwUnchecked)
throw new RuntimeIOException(th);
throw new UncheckedIOException(th);
Log.debug(th);
}

View File

@ -149,8 +149,7 @@ public class StreamEndPoint implements EndPoint
int length=buffer.length();
if (length>0)
buffer.writeTo(_out);
if (!buffer.isImmutable())
buffer.clear();
buffer.clear();
return length;
}

View File

@ -348,6 +348,12 @@ public class ChannelEndPoint implements EndPoint
}
finally
{
// adjust buffer 0 and 1
if (!header.isImmutable())
header.setGetIndex(bbuf0.position());
if (!buffer.isImmutable())
buffer.setGetIndex(bbuf1.position());
bbuf0.position(0);
bbuf1.position(0);
bbuf0.limit(bbuf0.capacity());

View File

@ -37,10 +37,8 @@ public class IndirectNIOBuffer extends ByteArrayBuffer implements NIOBuffer
if (buffer.isDirect())
throw new IllegalArgumentException();
_buf = buffer;
_get=buffer.position();
_put=buffer.limit();
buffer.position(0);
buffer.limit(buffer.capacity());
setGetIndex(buffer.position());
setPutIndex(buffer.limit());
_bytes=_buf.array();
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>
@ -46,20 +46,6 @@
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>repository.apache.org</id>
<name>Apache Snapshot Repository</name>
<layout>default</layout>
<url>http://repository.apache.org/content/groups/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
<dependencies>
<dependency>

View File

@ -65,7 +65,7 @@ public class SimpleAuthConfig implements ServerAuthConfig
return true;
}
public void refresh()
public void refresh()
{
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>

View File

@ -1,87 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp-2.1</artifactId>
<name>Jetty :: Jetty JSP Additions</name>
<description>Additions to Jasper implementation from Glassfish</description>
<properties>
<bundle-symbolic-name>${project.groupId}.jsp-2.1</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Import-Package>
com.sun.org.apache.commons.logging;version="[2.1,3)";glassfish="split",
*
</Import-Package>
<Export-Package>org.eclipse.jetty*;version="${parsedVersion.osgiVersion}"</Export-Package>
<Fragment-Host>org.apache.jasper.glassfish</Fragment-Host>
<!-- disable the uses directive: we don't want to fore eeryone that uses us to
have to depend on com.sun.org.apache.commons.logging provided by jasper-glassfish. -->
<_nouses>true</_nouses>
</instructions>
</configuration>
</plugin>
<plugin>
<!--
Required for OSGI
-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.jsp.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-glassfish</artifactId>
<version>${javax-servlet-jsp-version}</version>
<exclusions>
<exclusion>
<groupId>org.mortbay.jetty</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
</exclusions>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -1,102 +0,0 @@
package org.eclipse.jetty.jsp;
import com.sun.org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* @version $Revision$ $Date$
*/
public class JettyLog implements com.sun.org.apache.commons.logging.Log
{
private static volatile boolean __initialized;
/**
* Called via reflection from WebXmlProcessor
*/
public static synchronized void init()
{
if (!__initialized)
{
__initialized = true;
LogFactory.setLogImplClassName(JettyLog.class.getName());
}
}
private final Logger _logger;
public JettyLog(String name)
{
_logger = Log.getLogger(name);
}
public void fatal(Object o)
{
error(o);
}
public void fatal(Object o, Throwable throwable)
{
error(o, throwable);
}
public boolean isErrorEnabled()
{
return true;
}
public void error(Object o)
{
warn(o);
}
public void error(Object o, Throwable throwable)
{
_logger.warn(String.valueOf(o), throwable);
}
public boolean isWarnEnabled()
{
return true;
}
public void warn(Object o)
{
_logger.warn(String.valueOf(o));
}
public boolean isInfoEnabled()
{
return true;
}
public void info(Object o)
{
_logger.info(String.valueOf(o));
}
public boolean isDebugEnabled()
{
return _logger.isDebugEnabled();
}
public void debug(Object o)
{
_logger.debug(String.valueOf(o));
}
public void debug(Object o, Throwable throwable)
{
_logger.debug(String.valueOf(o), throwable);
}
public boolean isTraceEnabled()
{
return isDebugEnabled();
}
public void trace(Object o)
{
debug(o);
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
</parent>
<artifactId>jetty-nested</artifactId>
<name>Jetty :: Nested</name>

View File

@ -15,7 +15,7 @@ package org.eclipse.jetty.nested;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
@ -24,11 +24,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
public class NestedConnection extends HttpConnection

View File

@ -3,34 +3,20 @@ Bundle-ManifestVersion: 2
Bundle-Name: Jetty-OSGi-Jasper integration
Fragment-Host: org.eclipse.jetty.osgi.boot
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.jsp
Bundle-Version: 7.4.1.qualifier
Bundle-Version: 8.0.0.qualifier
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: com.sun.el;resolution:=optional,
com.sun.el.lang;resolution:=optional,
com.sun.el.parser;resolution:=optional,
com.sun.el.util;resolution:=optional,
com.sun.org.apache.commons.logging;split=glassfish;version="[2.1,3)";resolution:=optional,
javax.el;version="1.0.0";resolution:=optional,
javax.servlet;version="2.5.0",
javax.servlet.jsp;version="2.1.0",
javax.servlet.jsp.el;version="2.1.0",
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: com.sun.el;version="2.2.0";resolution:=optional,
javax.el;version="2.2.0";resolution:=optional,
javax.servlet.jsp;version="2.2.0",
javax.servlet.jsp.el;version="2.2.0",
javax.servlet.jsp.jstl.core;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.fmt;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.sql;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.tlv;version="1.2.0";resolution:=optional,
javax.servlet.jsp.resources;version="2.1.0",
javax.servlet.jsp.tagext;version="2.1.0",
javax.servlet.resources;version="2.5.0",
org.apache.jasper;version="2.0.0";resolution:=optional,
org.apache.jasper.compiler;version="2.0.0";resolution:=optional,
org.apache.jasper.compiler.tagplugin;version="2.0.0";resolution:=optional,
org.apache.jasper.runtime;version="2.0.0";resolution:=optional,
org.apache.jasper.security;version="2.0.0";resolution:=optional,
org.apache.jasper.servlet;version="2.0.0";resolution:=optional,
org.apache.jasper.tagplugins.jstl;version="2.0.0";resolution:=optional,
org.apache.jasper.util;version="2.0.0";resolution:=optional,
org.apache.jasper.xmlparser;version="2.0.0";resolution:=optional,
org.apache.jasper;version="2.1.0";resolution:=optional,
org.apache.jasper.compiler;version="2.1.0";resolution:=optional,
org.apache.jasper.xmlparser;version="2.1.0";resolution:=optional,
org.apache.taglibs.standard;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.extra.spath;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.functions;version="1.2.0";resolution:=optional,
@ -54,4 +40,6 @@ Import-Package: com.sun.el;resolution:=optional,
org.apache.taglibs.standard.tag.rt.xml;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.tei;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.tlv;version="1.2.0";resolution:=optional,
org.eclipse.jetty.jsp;version="[7.0,8.0)";resolution:=optional
org.glassfish.jsp.api;version="2.2.2";resolution:=optional
DynamicImport-Package: org.apache.jasper.*;version="2.1.0"

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -32,19 +32,41 @@
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
<!-- switch to 2.2 once it works in OSGi for us
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jsp-impl</artifactId>
<version>2.2</version>
</dependency> -->
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1-glassfish</artifactId>
<version>2.1.v20100127</version>
</dependency>
<!--dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency-->
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-api-2.1-glassfish</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</dependency>
</dependencies>
<!-- can't find the jsp-2.2 jars on maven central.
adding glassifish maven repo for now. -->
<repositories>
<repository>
<id>sun</id>
<url>http://download.java.net/maven/2/</url>
</repository>
</repositories>
<build>
<plugins>
@ -55,7 +77,7 @@
<phase>process-resources</phase>
<configuration>
<tasks>
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 7.4.1.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 8.0.0.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
</tasks>
</configuration>
<goals>

View File

@ -122,7 +122,6 @@ public class WebappRegistrationCustomizerImpl implements WebappRegistrationCusto
*/
public URL[] getJarsWithTlds(OSGiAppProvider provider, BundleFileLocatorHelper locatorHelper) throws Exception
{
HashSet<Class<?>> classesToAddToTheTldBundles = new HashSet<Class<?>>();
//Look for the jstl bundle

View File

@ -36,6 +36,7 @@ public class FragmentActivator implements BundleActivator
*
*/
public void start(BundleContext context) throws Exception {
System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
}

View File

@ -1,20 +0,0 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Jetty-OSGi-Logback integration
Fragment-Host: org.eclipse.jetty.osgi.boot
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.logback;singleton:=true
Bundle-Version: 7.3.1.qualifier
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: ch.qos.logback.classic,
ch.qos.logback.classic.joran,
ch.qos.logback.core,
ch.qos.logback.core.joran,
ch.qos.logback.core.joran.spi,
ch.qos.logback.core.spi,
ch.qos.logback.core.util,
ch.qos.logback.access.jetty.v7;resolution:=optional,
org.apache.commons.logging;resolution:=optional,
org.apache.log4j;resolution:=optional,
org.osgi.framework,
org.slf4j

View File

@ -1,12 +0,0 @@
This bundle is made to inject the logback dependencies along with the slf4j dependencies to support log4j and commons-logging.
It will read the configuration in the jettyhome/resources/logback-test.xml or jettyhome/resources/logback.xml folder.
It was tested with these bundles:
#this provides lg4j and commons-logging via slf4j
SLF4J = group("com.springsource.slf4j.api", "com.springsource.slf4j.org.apache.log4j", "com.springsource.slf4j.org.apache.commons.logging",
:under=>"org.slf4j", :version=>"1.5.6")
#logback is not exporting enough packages for us to be able to configure logback classic programatically.. on the springsource version they are fine...
LOGBACK = group("com.springsource.ch.qos.logback.core", "com.springsource.ch.qos.logback.classic",
:under=>"ch.qos.logback", :version=>"0.9.15")

View File

@ -1,5 +0,0 @@
source.. = src/main/java/
output.. = target/classes/
bin.includes = META-INF/,\
.
src.includes = META-INF/

View File

@ -1,109 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-logback</artifactId>
<name>Jetty :: OSGi :: Boot Logback</name>
<description>Jetty OSGi Boot Logback bundle</description>
<properties>
<bundle-symbolic-name>${project.groupId}.boot.logback</bundle-symbolic-name>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 7.3.0.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>artifact-jar</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>test-jar</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.osgi.boot.logback.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -1,86 +0,0 @@
// ========================================================================
// Copyright (c) 2009 Intalio, Inc.
// ------------------------------------------------------------------------
// 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.osgi.boot.logback;
import java.io.File;
import java.util.Map;
import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper.IFilesInJettyHomeResourcesProcessor;
import org.eclipse.jetty.osgi.boot.logback.internal.LogbackInitializer;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
/**
* Pseudo fragment activator.
* Called by the main org.eclipse.jetty.osgi.boot bundle.
* Please note: this is not a real BundleActivator. Simply something called back by
* the host bundle.
* The fragment is in charge of placing a hook to configure logback
* when the files inside jettyhome/resources are parsed.
*/
public class FragmentActivator implements BundleActivator, IFilesInJettyHomeResourcesProcessor
{
/**
*
*/
public void start(BundleContext context) throws Exception
{
LibExtClassLoaderHelper.registeredFilesInJettyHomeResourcesProcessors.add(this);
//now let's make sure no log4j, no slf4j and no commons.logging
//get inserted as a library that is not an osgi library
OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.apache.commons.logging.Log");
OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.apache.log4j.Logger");
OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.slf4j.Logger");
//OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected(java.util.logging.Logger.class);
}
/**
* Called when this bundle is stopped so the Framework can perform the
* bundle-specific activities necessary to stop the bundle. In general, this
* method should undo the work that the <code>BundleActivator.start</code>
* method started. There should be no active threads that were started by
* this bundle when this bundle returns. A stopped bundle must not call any
* Framework objects.
*
* <p>
* This method must complete and return to its caller in a timely manner.
*
* @param context The execution context of the bundle being stopped.
* @throws Exception If this method throws an exception, the
* bundle is still marked as stopped, and the Framework will remove
* the bundle's listeners, unregister all services registered by the
* bundle, and release all services used by the bundle.
*/
public void stop(BundleContext context) throws Exception
{
LibExtClassLoaderHelper.registeredFilesInJettyHomeResourcesProcessors.remove(this);
}
public void processFilesInResourcesFolder(File jettyHome, Map<String,File> files)
{
try
{
LogbackInitializer.processFilesInResourcesFolder(jettyHome, files);
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}

View File

@ -1,98 +0,0 @@
// ========================================================================
// Copyright (c) 2009 Intalio, Inc.
// ------------------------------------------------------------------------
// 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.
// Contributors:
// Hugues Malphettes - initial API and implementation
// ========================================================================
package org.eclipse.jetty.osgi.boot.logback.internal;
import java.io.File;
import java.util.Map;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.core.joran.JoranConfiguratorBase;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
/**
* Setup logback eventually located in the config file inside jettyhome/resources
* All logback related code is done in this separate class for better debug
* and isolation when it does not load.
*/
public class LogbackInitializer {
/**
* @return true when we are currently being run by the pde in development mode.
*/
private static boolean isPDEDevelopment()
{
String eclipseCommands = System.getProperty("eclipse.commands");
// detect if we are being run from the pde: ie during development.
return eclipseCommands != null && eclipseCommands.indexOf("-dev") != -1
&& (eclipseCommands.indexOf("-dev\n") != -1
|| eclipseCommands.indexOf("-dev\r") != -1
|| eclipseCommands.indexOf("-dev ") != -1);
}
/**
* Follow the configuration for logback.
* unless the system propery was set in which case it
* was assume it was already setup.
*/
public static void processFilesInResourcesFolder(File jettyHome, Map<String,File> files)
{
String logbackConf = System.getProperty("logback.configurationFile");
if (logbackConf != null)
{
File confFile = new File(logbackConf);
if (confFile.exists())
{
//assume logback was configured by this one?
return;
}
}
File logConf = isPDEDevelopment() ? files.get("logback-dev.xml") : null;
if (logConf == null)
{
logConf = files.get("logback-test.xml");
}
if (logConf == null)
{
logConf = files.get("logback.xml");
}
if (logConf == null)
{
return;
}
// assume SLF4J is bound to logback in the current environment
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
try
{
JoranConfiguratorBase configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();
configurator.doConfigure(logConf.getAbsoluteFile().getAbsolutePath());
}
catch (JoranException je)
{
je.printStackTrace();
}
StatusPrinter.printIfErrorsOccured(lc);
}
}

View File

@ -2,10 +2,10 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Support for rfc66 war url scheme
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot.warurl;singleton:=true
Bundle-Version: 7.3.0.qualifier
Bundle-Version: 8.0.0.qualifier
Bundle-Activator: org.eclipse.jetty.osgi.boot.warurl.WarUrlActivator
Bundle-Vendor: Mort Bay Consulting
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Import-Package: org.eclipse.jetty.util,
org.osgi.framework,
org.osgi.service.url

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -33,7 +33,7 @@
<phase>process-resources</phase>
<configuration>
<tasks>
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 7.3.0.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 8.0.0.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
</tasks>
</configuration>
<goals>

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>jetty-osgi</artifactId>
<version>7.0.1-SNAPSHOT</version>
<groupId>org.eclipse.jetty.osgi</groupId>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>org.eclipse.jetty.osgi.boot.warurl</artifactId>
<version>7.0.1.qualifier</version>
<packaging>eclipse-plugin</packaging>
</project>

View File

@ -1,19 +1,21 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Jetty OSGi bootstrap
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot;singleton:=true
Bundle-SymbolicName: org.eclipse.jetty.osgi.boot
Bundle-Vendor: Mort Bay Consulting
Bundle-Version: 7.4.1.qualifier
Bundle-Version: 8.0.0.qualifier
Bundle-Activator: org.eclipse.jetty.osgi.boot.JettyBootstrapActivator
Import-Package: javax.mail;version="1.4.0";resolution:=optional,
javax.mail.event;version="1.4.0";resolution:=optional,
javax.mail.internet;version="1.4.0";resolution:=optional,
javax.mail.search;version="1.4.0";resolution:=optional,
javax.mail.util;version="1.4.0";resolution:=optional,
javax.servlet;version="2.5.0",
javax.servlet.http;version="2.5.0",
javax.servlet;version="3.0",
javax.servlet.http;version="3.0",
javax.transaction;version="1.1.0";resolution:=optional,
javax.transaction.xa;version="1.1.0";resolution:=optional,
org.eclipse.jetty.nested;version="8.0.0";resolution:=optional,
org.eclipse.jetty.annotations;version="8.0.0";resolution:=optional,
org.osgi.framework,
org.osgi.service.cm;version="1.2.0",
org.osgi.service.packageadmin,
@ -25,28 +27,27 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
org.slf4j.spi;resolution:=optional,
org.xml.sax,
org.xml.sax.helpers
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-Classpath: .
Require-Bundle: org.eclipse.jetty.ajp;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.annotations;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.client;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.continuation;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.deploy;bundle-version="[7.0,8)",
org.eclipse.jetty.http;bundle-version="[7.0,8)",
org.eclipse.jetty.io;bundle-version="[7.0,8)",
org.eclipse.jetty.jmx;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.jndi;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.nested;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.plus;bundle-version="[7.0,8.0)";resolution:=optional,
org.eclipse.jetty.rewrite;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.security;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.server;bundle-version="[7.0,8)",
org.eclipse.jetty.servlet;bundle-version="[7.0,8)",
org.eclipse.jetty.servlets;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.util;bundle-version="[7.0,8)",
org.eclipse.jetty.webapp;bundle-version="[7.0,8)",
org.eclipse.jetty.websocket;bundle-version="[7.0,8)";resolution:=optional,
org.eclipse.jetty.xml;bundle-version="[7.0,8)"
Export-Package: org.eclipse.jetty.osgi.boot;version="7.4.0",
org.eclipse.jetty.osgi.nested;version="7.4.0",
org.eclipse.jetty.osgi.boot.utils;version="7.4.0"
Require-Bundle: org.eclipse.jetty.ajp;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.annotations;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.client;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.continuation;bundle-version="[7.0,9)";resolution:=optional,
org.eclipse.jetty.deploy;bundle-version="[8.0,9)",
org.eclipse.jetty.http;bundle-version="[8.0,9)",
org.eclipse.jetty.io;bundle-version="[8.0,9)",
org.eclipse.jetty.jmx;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.jndi;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.plus;bundle-version="[8.0,9.0)";resolution:=optional,
org.eclipse.jetty.rewrite;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.security;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.server;bundle-version="[8.0,9)",
org.eclipse.jetty.servlet;bundle-version="[8.0,9)",
org.eclipse.jetty.servlets;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.util;bundle-version="[8.0,9)",
org.eclipse.jetty.webapp;bundle-version="[8.0,9)",
org.eclipse.jetty.websocket;bundle-version="[8.0,9)";resolution:=optional,
org.eclipse.jetty.xml;bundle-version="[8.0,9)"
Export-Package: org.eclipse.jetty.osgi.boot;version="8.0.0",
org.eclipse.jetty.osgi.boot.utils;version="8.0.0",
org.eclipse.jetty.osgi.annotations;version="8.0.0"

View File

@ -123,7 +123,6 @@
</New>
</Arg>
</Call>
</New>
</Arg>
</Call>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.4.3-SNAPSHOT</version>
<version>8.0.0.RC0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -14,6 +14,10 @@
<bundle-symbolic-name>${project.groupId}.boot</bundle-symbolic-name>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
@ -40,62 +44,6 @@
</dependency>
</dependencies>
<!--build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<replace file="target/classes/META-INF/MANIFEST.MF" token="Bundle-Version: 7.3.0.qualifier" value="Bundle-Version: ${parsedVersion.osgiVersion}" />
<copy todir="target/classes/jettyhome">
<fileset dir="jettyhome">
<exclude name="**/*.log" />
</fileset>
</copy>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>artifact-jar</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
<execution>
<id>test-jar</id>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.osgi.boot.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build-->
<build>
<plugins>
<plugin>
@ -173,6 +121,8 @@
javax.servlet.http;version="2.5.0",
javax.transaction;version="1.1.0";resolution:=optional,
javax.transaction.xa;version="1.1.0";resolution:=optional,
org.eclipse.jetty.nested;version="8.0.0";resolution:=optional,
org.eclipse.jetty.annotations;version="8.0.0";resolution:=optional,
org.osgi.framework,
org.osgi.service.cm;version="1.2.0",
org.osgi.service.packageadmin,
@ -184,12 +134,11 @@
org.slf4j.helpers;resolution:=optional,
org.xml.sax,
org.xml.sax.helpers,
org.eclipse.jetty.nested;resolution:=optional,
*
</Import-Package>
<DynamicImport-Package>org.eclipse.jetty.*;version="[7.3,8)"</DynamicImport-Package>
<DynamicImport-Package>org.eclipse.jetty.*;version="[8.0.0,9.0.0)"</DynamicImport-Package>
<!--Require-Bundle/-->
<Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment>
<Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment>
</instructions>
</configuration>
</plugin>

View File

@ -0,0 +1,197 @@
// ========================================================================
// Copyright (c) 2006-2011 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.osgi.annotations;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
/**
* Extend the AnnotationConfiguration to support OSGi:
* Look for annotations inside WEB-INF/lib and also in the fragments and required bundles.
* Discover them using a scanner adapted to OSGi instead of the jarscanner.
*/
public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration
{
/**
* This parser scans the bundles using the OSGi APIs instead of assuming a jar.
*/
@Override
protected org.eclipse.jetty.annotations.AnnotationParser createAnnotationParser()
{
return new AnnotationParser();
}
/**
* Here is the order in which jars and osgi artifacts are scanned for discoverable annotations.
* <ol>
* <li>The container jars are scanned.</li>
* <li>The WEB-INF/classes are scanned</li>
* <li>The osgi fragment to the web bundle are parsed.</li>
* <li>The WEB-INF/lib are scanned</li>
* <li>The required bundles are parsed</li>
* </ol>
*/
@Override
public void parseWebInfLib (WebAppContext context, org.eclipse.jetty.annotations.AnnotationParser parser)
throws Exception
{
AnnotationParser oparser = (AnnotationParser)parser;
Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle);
if (fragAndRequiredBundles != null)
{
//index:
for (Bundle bundle : fragAndRequiredBundles)
{
Resource bundleRes = oparser.indexBundle(bundle);
if (!context.getMetaData().getWebInfJars().contains(bundleRes))
{
context.getMetaData().addWebInfJar(bundleRes);
}
}
//scan the fragments
for (Bundle fragmentBundle : fragAndRequiredBundles)
{
if (fragmentBundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
{
//a fragment indeed:
parseFragmentBundle(context,oparser,webbundle,fragmentBundle);
}
}
}
//scan ourselves
parseWebBundle(context,oparser,webbundle);
//scan the WEB-INF/lib
super.parseWebInfLib(context,parser);
if (fragAndRequiredBundles != null)
{
//scan the required bundles
for (Bundle requiredBundle : fragAndRequiredBundles)
{
if (requiredBundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
{
//a bundle indeed:
parseRequiredBundle(context,oparser,webbundle,requiredBundle);
}
}
}
}
/**
* Scan a fragment bundle for servlet annotations
* @param context The webapp context
* @param parser The parser
* @param webbundle The current webbundle
* @param fragmentBundle The OSGi fragment bundle to scan
* @throws Exception
*/
protected void parseFragmentBundle(WebAppContext context, AnnotationParser parser,
Bundle webbundle, Bundle fragmentBundle) throws Exception
{
parseBundle(context,parser,webbundle,fragmentBundle);
}
/**
* Scan a bundle required by the webbundle for servlet annotations
* @param context The webapp context
* @param parser The parser
* @param webbundle The current webbundle
* @param fragmentBundle The OSGi required bundle to scan
* @throws Exception
*/
protected void parseWebBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle)
throws Exception
{
parseBundle(context,parser,webbundle,webbundle);
}
/**
* Scan a bundle required by the webbundle for servlet annotations
* @param context The webapp context
* @param parser The parser
* @param webbundle The current webbundle
* @param fragmentBundle The OSGi required bundle to scan
* @throws Exception
*/
protected void parseRequiredBundle(WebAppContext context, AnnotationParser parser,
Bundle webbundle, Bundle requiredBundle) throws Exception
{
parseBundle(context,parser,webbundle,requiredBundle);
}
protected void parseBundle(WebAppContext context, AnnotationParser parser,
Bundle webbundle, Bundle bundle) throws Exception
{
Resource bundleRes = parser.getResource(bundle);
parser.parse(bundle,createClassNameResolver(context));
List<DiscoveredAnnotation> annotations = new ArrayList<DiscoveredAnnotation>();
gatherAnnotations(annotations, parser.getAnnotationHandlers());
if (webbundle == bundle)
{
//just like the super with its question about annotations in WEB-INF/classes:
//"TODO - where to set the annotations discovered from WEB-INF/classes?"
context.getMetaData().addDiscoveredAnnotations(annotations);
}
else
{
context.getMetaData().addDiscoveredAnnotations(bundleRes, annotations);
}
}
/**
* Returns the same classname resolver than for the webInfjar scanner
* @param context
* @return
*/
protected ClassNameResolver createClassNameResolver(final WebAppContext context)
{
return createClassNameResolver(context,true,false,false,false);
}
protected ClassNameResolver createClassNameResolver(final WebAppContext context,
final boolean excludeSysClass, final boolean excludeServerClass, final boolean excludeEverythingElse,
final boolean overrideIsParenLoaderIsPriority)
{
return new ClassNameResolver ()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return excludeSysClass;
if (context.isServerClass(name)) return excludeServerClass;
return excludeEverythingElse;
}
public boolean shouldOverride (String name)
{
//looking at system classpath
if (context.isParentLoaderPriority())
return overrideIsParenLoaderIsPriority;
return !overrideIsParenLoaderIsPriority;
}
};
}
}

View File

@ -0,0 +1,192 @@
// ========================================================================
// Copyright (c) 2006-2009 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.osgi.annotations;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.util.resource.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
/**
*
*/
public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser
{
private Set<URI> _alreadyParsed = new HashSet<URI>();
private Map<URI,Bundle> _uriToBundle = new HashMap<URI, Bundle>();
private Map<Bundle,Resource> _resourceToBundle = new HashMap<Bundle,Resource>();
private Map<Bundle,URI> _bundleToUri = new HashMap<Bundle, URI>();
/**
* Keep track of a jetty URI Resource and its associated OSGi bundle.
* @param uri
* @param bundle
* @throws Exception
*/
protected Resource indexBundle(Bundle bundle) throws Exception
{
File bundleFile = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation(bundle);
Resource resource = Resource.newResource(bundleFile.toURI());
URI uri = resource.getURI();
_uriToBundle.put(uri,bundle);
_bundleToUri.put(bundle,uri);
_resourceToBundle.put(bundle,resource);
return resource;
}
protected URI getURI(Bundle bundle)
{
return _bundleToUri.get(bundle);
}
protected Resource getResource(Bundle bundle)
{
return _resourceToBundle.get(bundle);
}
/**
*
*/
@Override
public void parse (URI[] uris, ClassNameResolver resolver)
throws Exception
{
for (URI uri : uris)
{
Bundle associatedBundle = _uriToBundle.get(uri);
if (associatedBundle == null)
{
if (!_alreadyParsed.add(uri))
{
continue;
}
//a jar in WEB-INF/lib or the WEB-INF/classes
//use the behavior of the super class for a standard jar.
super.parse(new URI[] {uri},resolver);
}
else
{
parse(associatedBundle,resolver);
}
}
}
protected void parse(Bundle bundle, ClassNameResolver resolver)
throws Exception
{
URI uri = _bundleToUri.get(bundle);
if (!_alreadyParsed.add(uri))
{
return;
}
String bundleClasspath = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
if (bundleClasspath == null)
{
bundleClasspath = ".";
}
//order the paths first by the number of tokens in the path second alphabetically.
TreeSet<String> paths = new TreeSet<String>(
new Comparator<String>()
{
public int compare(String o1, String o2)
{
int paths1 = new StringTokenizer(o1,"/",false).countTokens();
int paths2 = new StringTokenizer(o2,"/",false).countTokens();
if (paths1 == paths2)
{
return o1.compareTo(o2);
}
return paths2 - paths1;
}
});
boolean hasDotPath = false;
StringTokenizer tokenizer = new StringTokenizer(bundleClasspath, ",;", false);
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken().trim();
if (!token.startsWith("/"))
{
token = "/" + token;
}
if (token.equals("/."))
{
hasDotPath = true;
}
else if (!token.endsWith(".jar") && !token.endsWith("/"))
{
paths.add(token+"/");
}
else
{
paths.add(token);
}
}
//support the development environment: maybe the classes are inside bin or target/classes
//this is certainly not useful in production.
//however it makes our life so much easier during development.
if (bundle.getEntry("/.classpath") != null)
{
if (bundle.getEntry("/bin/") != null)
{
paths.add("/bin/");
}
else if (bundle.getEntry("/target/classes/") != null)
{
paths.add("/target/classes/");
}
}
Enumeration classes = bundle.findEntries("/","*.class",true);
if (classes == null)
{
return;
}
while (classes.hasMoreElements())
{
URL classUrl = (URL) classes.nextElement();
String path = classUrl.getPath();
//remove the longest path possible:
String name = null;
for (String prefixPath : paths)
{
if (path.startsWith(prefixPath))
{
name = path.substring(prefixPath.length());
break;
}
}
if (name == null && hasDotPath)
{
//remove the starting '/'
name = path.substring(1);
}
//transform into a classname to pass to the resolver
String shortName = name.replace('/', '.').substring(0,name.length()-6);
if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
scanClass(classUrl.openStream());
}
}
}

View File

@ -50,6 +50,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
private boolean _parentLoaderPriority = false;
private String _defaultsDescriptor;
private String _tldBundles;
private String[] _configurationClasses;
/**
* When a context file corresponds to a deployed bundle and is changed we
@ -144,15 +145,20 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
public ContextHandler createContextHandler(App app) throws Exception
{
// return pre-created Context
if (app.getContextHandler() != null)
ContextHandler wah = app.getContextHandler();
if (wah == null)
{
return app.getContextHandler();
// for some reason it was not defined when the App was constructed.
// we don't support this situation at this point.
// once the WebAppRegistrationHelper is refactored, the code
// that creates the ContextHandler will actually be here.
throw new IllegalStateException("The App must be passed the " + "instance of the ContextHandler when it is construsted");
}
// for some reason it was not defined when the App was constructed.
// we don't support this situation at this point.
// once the WebAppRegistrationHelper is refactored, the code
// that creates the ContextHandler will actually be here.
throw new IllegalStateException("The App must be passed the " + "instance of the ContextHandler when it is construsted");
if (_configurationClasses != null && wah instanceof WebAppContext)
{
((WebAppContext)wah).setConfigurationClasses(_configurationClasses);
}
return app.getContextHandler();
}
/**
@ -187,7 +193,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
// TODO apply configuration specific to this provider
if (context instanceof WebAppContext)
{
((WebAppContext)context).setExtractWAR(isExtract());
((WebAppContext)context).setExtractWAR(isExtract());
}
// wrap context as an App
@ -381,5 +387,23 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
{
return _tldBundles;
}
/**
* @param configurations The configuration class names.
*/
public void setConfigurationClasses(String[] configurations)
{
_configurationClasses = configurations==null?null:(String[])configurations.clone();
}
/* ------------------------------------------------------------ */
/**
*
*/
public String[] getConfigurationClasses()
{
return _configurationClasses;
}
}

View File

@ -500,6 +500,13 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
//can pick it up.
wah.setAttribute(OSGiWebappConstants.REQUIRE_TLD_BUNDLE, requireTldBundle);
if (wah instanceof WebAppContext)
{
if (_wrapper.getOSGiAppProvider().getConfigurationClasses() != null)
{
((WebAppContext)wah).setConfigurationClasses(_wrapper.getOSGiAppProvider().getConfigurationClasses());
}
}
Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(contributor);
if (fragments != null && fragments.length != 0)
@ -803,3 +810,4 @@ public class WebBundleDeployerHelper implements IWebBundleDeployerHelper
}

View File

@ -17,7 +17,6 @@ import java.util.Dictionary;
import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.util.log.Log;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.util.tracker.BundleTracker;
@ -149,7 +148,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
String warFolderRelativePath = (String)dic.get(OSGiWebappConstants.JETTY_WAR_FOLDER_PATH);
if (warFolderRelativePath != null)
{
String contextPath = getWebContextPath(bundle, dic, false);//(String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
String contextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
if (contextPath == null || !contextPath.startsWith("/"))
{
throw new IllegalArgumentException();
@ -210,7 +209,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
// pointing to files and folders inside WEB-INF. We should
// filter-out
// META-INF too
String rfc66ContextPath = getWebContextPath(bundle,dic,rfc66Webxml==null);
String rfc66ContextPath = getWebContextPath(bundle,dic);
try
{
JettyBootstrapActivator.registerWebapplication(bundle,".",rfc66ContextPath);
@ -225,14 +224,11 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
}
}
private String getWebContextPath(Bundle bundle, Dictionary<?, ?> dic, boolean webinfWebxmlExists)
private String getWebContextPath(Bundle bundle, Dictionary<?, ?> dic)
{
String rfc66ContextPath = (String)dic.get(OSGiWebappConstants.RFC66_WEB_CONTEXTPATH);
if (rfc66ContextPath == null)
{
if (!webinfWebxmlExists) {
return null;
}
// extract from the last token of the bundle's location:
// (really ?
// could consider processing the symbolic name as an alternative
@ -245,7 +241,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
int lastDot = rfc66ContextPath.lastIndexOf('.');
if (lastDot != -1)
{
rfc66ContextPath = rfc66ContextPath.substring(0,lastDot);
rfc66ContextPath = rfc66ContextPath.substring(0,lastDot);
}
}
if (!rfc66ContextPath.startsWith("/"))
@ -254,7 +250,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer {
}
return rfc66ContextPath;
}
private void unregister(Bundle bundle)
{
// nothing to do: when the bundle is stopped, each one of its service

View File

@ -72,7 +72,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
{
// some osgi frameworks do use the file protocole directly in some
// situations. Do use the FileResource to transform the URL into a File: URL#toURI is broken
return new FileResource(url).getFile().getParentFile().getParentFile();
return new FileResource(url).getFile().getParentFile().getParentFile();
}
else if (url.getProtocol().equals("bundleentry"))
{

View File

@ -275,3 +275,4 @@ public class PackageAdminServiceTracker implements ServiceListener
}
}

Some files were not shown because too many files have changed in this diff Show More