diff --git a/.gitignore b/.gitignore index a07b178..6109265 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ *.class - +.classpath +.project +.settings # Package Files # *.jar *.war diff --git a/pom.xml b/pom.xml index 9602d04..506fbb0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,9 @@ - + 4.0.0 de.latlon j2ep - 1.0.0-SNAPSHOT - war + jar + 1.2-securityproxy-master j2ep Fork of jEasy Extensible Proxy - svn://svn.code.sf.net/p/j2ep/code/trunk @@ -17,7 +16,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.15 + 2.22.1 **/PostTest* @@ -31,14 +30,22 @@ - + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + commons-digester commons-digester - 1.7 + 1.8.1 commons-logging @@ -49,12 +56,12 @@ commons-codec commons-codec - 1.3 + 1.11 commons-beanutils commons-beanutils - 1.5 + 1.9.3 commons-logging @@ -80,20 +87,26 @@ commons-logging commons-logging - 1.0.3 + 1.1.3 javax.servlet servlet-api - 2.4 + 2.5 provided junit junit - 3.8.1 + 3.8.2 test + + org.mockito + mockito-core + 1.9.5 + test + cactus cactus @@ -101,9 +114,9 @@ test - aspectj + org.aspectj aspectjrt - 1.2.1 + 1.5.4 test @@ -111,4 +124,43 @@ http://localhost:8080 - \ No newline at end of file + + + scm:git:git@github.com:lat-lon/j2ep.git + scm:git:git@github.com:lat-lon/j2ep.git + https://github.com/lat-lon/j2ep.git + + + + + latlon-repo + http://repo.lat-lon/nexus/content/groups/public/ + + + j2ep-releases + http://repo.lat-lon/nexus/content/repositories/j2ep-release/ + + + j2ep-snapshots + http://repo.lat-lon/nexus/content/repositories/j2ep-snapshots/ + + + + + + j2ep-releases + http://repo.lat-lon/nexus/content/repositories/j2ep-release/ + + + j2ep-snapshots + http://repo.lat-lon/nexus/content/repositories/j2ep-snapshots/ + + + + + + latlon-repo + http://repo.lat-lon/nexus/content/groups/public/ + + + diff --git a/src/main/java/net/sf/j2ep/ConfigParser.java b/src/main/java/net/sf/j2ep/ConfigParser.java index 9aa2e31..555ee8d 100644 --- a/src/main/java/net/sf/j2ep/ConfigParser.java +++ b/src/main/java/net/sf/j2ep/ConfigParser.java @@ -17,6 +17,10 @@ package net.sf.j2ep; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.util.Iterator; import java.util.LinkedList; @@ -53,11 +57,45 @@ public class ConfigParser { * mappings included. * * @param data The config file containing the XML data structure + * @throws FileNotFoundException */ - public ConfigParser(File data) { + public ConfigParser( File data ) { + createServerChain( data ); + } + + /** + * Standard constructor only specifying the input file. The constructor will + * parse the config and build a corresponding rule chain with the server + * mappings included. + * + * @param data The config file containing the XML data structure + */ + public ConfigParser(InputStream data) { + createServerChain( data ); + } + + + private void createServerChain( File data ) { + log = LogFactory.getLog( ConfigParser.class ); + FileInputStream fileInputStream = null; + try { + fileInputStream = new FileInputStream( data ); + createServerChain( fileInputStream ); + } catch ( Exception e ) { + throw new RuntimeException( e ); + } finally { + if ( fileInputStream != null ) + try { + fileInputStream.close(); + } catch ( IOException e ) { + } + } + } + + private void createServerChain( InputStream data ) { log = LogFactory.getLog(ConfigParser.class); try { - LinkedList serverContainer = createServerList(data); + LinkedList serverContainer = createServerList(data); if (log.isDebugEnabled()) { debugServers(serverContainer); } @@ -66,7 +104,6 @@ public ConfigParser(File data) { throw new RuntimeException(e); } } - /** * Returns the parsed server chain. * @@ -81,7 +118,7 @@ public ServerChain getServerChain() { * * @return The rules all put into a rule chain */ - private LinkedList createServerList(File data) throws Exception { + private LinkedList createServerList(InputStream data) throws Exception { Digester digester = new Digester(); digester.setUseContextClassLoader(true); @@ -133,7 +170,7 @@ private LinkedList createServerList(File data) throws Exception { // Add server to list digester.addSetNext("config/cluster-server", "add"); - return (LinkedList) digester.parse(data); + return (LinkedList) digester.parse(data); } /** @@ -142,8 +179,8 @@ private LinkedList createServerList(File data) throws Exception { * * @param servers The server to debug */ - private void debugServers(LinkedList servers) { - Iterator itr = servers.iterator(); + private void debugServers(LinkedList servers) { + Iterator itr = servers.iterator(); while (itr.hasNext()) { ServerContainer container = (ServerContainer) itr.next(); diff --git a/src/main/java/net/sf/j2ep/ProxyFilter.java b/src/main/java/net/sf/j2ep/ProxyFilter.java index 8d57642..964bbed 100644 --- a/src/main/java/net/sf/j2ep/ProxyFilter.java +++ b/src/main/java/net/sf/j2ep/ProxyFilter.java @@ -18,9 +18,15 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.UnknownHostException; -import javax.servlet.*; +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.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -31,8 +37,14 @@ import net.sf.j2ep.model.RequestHandler; import net.sf.j2ep.model.ResponseHandler; import net.sf.j2ep.model.Server; +import net.sf.j2ep.servers.BaseServerFromUrlCreator; -import org.apache.commons.httpclient.*; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpMethodBase; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.params.HttpClientParams; import org.apache.commons.logging.Log; @@ -41,178 +53,233 @@ /** * A reverse proxy using a set of Rules to identify which resource to proxy. * - * At first the rule chain is traversed trying to find a matching rule. - * When the rule is found it is given the option to rewrite the URL. - * The rewritten URL is then sent to a Server creating a Response Handler - * that can be used to process the response with streams and headers. + * At first the rule chain is traversed trying to find a matching rule. When the rule is found it is given the option to + * rewrite the URL. The rewritten URL is then sent to a Server creating a Response Handler that can be used to process + * the response with streams and headers. * - * The rules and servers are created dynamically and are specified in the - * XML data file. This allows the proxy to be easily extended by creating - * new rules and new servers. + * The rules and servers are created dynamically and are specified in the XML data file. This allows the proxy to be + * easily extended by creating new rules and new servers. * * @author Anders Nyman */ public class ProxyFilter implements Filter { - /** + private static final String CONFIG_XML = "/config.xml"; + + private static final String DEFAULT_PATH = "/WEB-INF/config/data.xml"; + + private static final String REQUEST_ATTRIBUTE_SERVICE_URL = "net.sf.j2ep.serviceurl"; + + /** * The server chain, will be traversed to find a matching server. */ private ServerChain serverChain; - - /** + + /** * Logging element supplied by commons-logging. */ private static Log log; - - /** + + /** * The httpclient used to make all connections with, supplied by commons-httpclient. */ private HttpClient httpClient; /** - * Implementation of a reverse-proxy. All request go through here. This is - * the main class where are handling starts. + * Implementation of a reverse-proxy. All request go through here. This is the main class where are handling starts. * - * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, - * javax.servlet.ServletResponse, javax.servlet.FilterChain) + * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, + * javax.servlet.FilterChain) */ - public void doFilter(ServletRequest request, ServletResponse response, - FilterChain filterChain) throws IOException, ServletException { + public void doFilter( ServletRequest request, ServletResponse response, FilterChain filterChain ) + throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) response; HttpServletRequest httpRequest = (HttpServletRequest) request; - Server server = (Server) httpRequest.getAttribute("proxyServer"); - if (server == null) { - server = serverChain.evaluate(httpRequest); + Server server = (Server) httpRequest.getAttribute( "proxyServer" ); + if ( server == null ) { + Object requestAttributeServiceUrl = request.getAttribute( REQUEST_ATTRIBUTE_SERVICE_URL ); + if ( requestAttributeServiceUrl != null ) { + BaseServerFromUrlCreator baseServerCreator = new BaseServerFromUrlCreator(); + server = baseServerCreator.createServer( requestAttributeServiceUrl.toString(), request ); + } else { + server = serverChain.evaluate( httpRequest ); + } } - - if (server == null) { - filterChain.doFilter(request, response); + + if ( server == null ) { + filterChain.doFilter( request, response ); } else { - String uri = server.getRule().process(getURI(httpRequest)); + String uri = server.getRule().process( getURI( httpRequest ) ); String url = request.getScheme() + "://" + server.getDomainName() + server.getPath() + uri; - log.debug("Connecting to " + url); - + log.debug( "Connecting to " + url ); + ResponseHandler responseHandler = null; - + try { - httpRequest = server.preExecute(httpRequest); - responseHandler = executeRequest(httpRequest, url); - httpResponse = server.postExecute(httpResponse); - - responseHandler.process(httpResponse); - } catch (HttpException e) { - log.error("Problem while connecting to server", e); - httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - server.setConnectionExceptionRecieved(e); - } catch (UnknownHostException e) { - log.error("Could not connection to the host specified", e); - httpResponse.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT); - server.setConnectionExceptionRecieved(e); - } catch (IOException e) { - log.error( "Problem probably with the input being send, either with a Header or the Stream", e); - httpResponse .setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); - } catch (MethodNotAllowedException e) { - log.error("Incoming method could not be handled", e); - httpResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); - httpResponse.setHeader("Allow", e.getAllowedMethods()); + httpRequest = server.preExecute( httpRequest ); + responseHandler = executeRequest( httpRequest, url ); + httpResponse = server.postExecute( httpResponse ); + + responseHandler.process( httpResponse ); + } catch ( HttpException e ) { + log.error( "Problem while connecting to server", e ); + httpResponse.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); + server.setConnectionExceptionRecieved( e ); + } catch ( UnknownHostException e ) { + log.error( "Could not connection to the host specified", e ); + httpResponse.setStatus( HttpServletResponse.SC_GATEWAY_TIMEOUT ); + server.setConnectionExceptionRecieved( e ); + } catch ( IOException e ) { + log.error( "Problem probably with the input being send, either with a Header or the Stream", e ); + httpResponse.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ); + } catch ( MethodNotAllowedException e ) { + log.error( "Incoming method could not be handled", e ); + httpResponse.setStatus( HttpServletResponse.SC_METHOD_NOT_ALLOWED ); + httpResponse.setHeader( "Allow", e.getAllowedMethods() ); } finally { - if (responseHandler != null) { + if ( responseHandler != null ) { responseHandler.close(); } } } } - + /** - * Will build a URI but including the Query String. That means that it really - * isn't a URI, but quite near. + * Will build a URI but including the Query String. That means that it really isn't a URI, but quite near. * - * @param httpRequest Request to get the URI and query string from + * @param httpRequest + * Request to get the URI and query string from * @return The URI for this request including the query string */ - private String getURI(HttpServletRequest httpRequest) { + private String getURI( HttpServletRequest httpRequest ) { String contextPath = httpRequest.getContextPath(); - String uri = httpRequest.getRequestURI().substring(contextPath.length()); - if (httpRequest.getQueryString() != null) { + String uri = httpRequest.getRequestURI().substring( contextPath.length() ); + if ( httpRequest.getQueryString() != null ) { uri += "?" + httpRequest.getQueryString(); } return uri; } /** - * Will create the method and execute it. After this the method - * is sent to a ResponseHandler that is returned. + * Will create the method and execute it. After this the method is sent to a ResponseHandler that is returned. * - * @param httpRequest Request we are receiving from the client - * @param url The location we are proxying to + * @param httpRequest + * Request we are receiving from the client + * @param url + * The location we are proxying to * @return A ResponseHandler that can be used to write the response - * @throws MethodNotAllowedException If the method specified by the request isn't handled - * @throws IOException When there is a problem with the streams - * @throws HttpException The httpclient can throw HttpExcetion when executing the method + * @throws MethodNotAllowedException + * If the method specified by the request isn't handled + * @throws IOException + * When there is a problem with the streams + * @throws HttpException + * The httpclient can throw HttpExcetion when executing the method */ - private ResponseHandler executeRequest(HttpServletRequest httpRequest, - String url) throws MethodNotAllowedException, IOException, - HttpException { - RequestHandler requestHandler = RequestHandlerFactory - .createRequestMethod(httpRequest.getMethod()); + private ResponseHandler executeRequest( HttpServletRequest httpRequest, String url ) + throws MethodNotAllowedException, IOException, HttpException { + RequestHandler requestHandler = RequestHandlerFactory.createRequestMethod( httpRequest.getMethod() ); - HttpMethod method = requestHandler.process(httpRequest, url); - method.setFollowRedirects(false); + HttpMethod method = requestHandler.process( httpRequest, url ); + method.setFollowRedirects( false ); /* - * Why does method.validate() return true when the method has been - * aborted? I mean, if validate returns true the API says that means - * that the method is ready to be executed. - * TODO I don't like doing type casting here, see above. + * Why does method.validate() return true when the method has been aborted? I mean, if validate returns true the + * API says that means that the method is ready to be executed. TODO I don't like doing type casting here, see + * above. */ - if (!((HttpMethodBase) method).isAborted()) { - httpClient.executeMethod(method); + if ( !( (HttpMethodBase) method ).isAborted() ) { + httpClient.executeMethod( method ); - if (method.getStatusCode() == 405) { - Header allow = method.getResponseHeader("allow"); + if ( method.getStatusCode() == 405 ) { + Header allow = method.getResponseHeader( "allow" ); String value = allow.getValue(); - throw new MethodNotAllowedException( - "Status code 405 from server", AllowedMethodHandler - .processAllowHeader(value)); + throw new MethodNotAllowedException( "Status code 405 from server", + AllowedMethodHandler.processAllowHeader( value ) ); } } - return ResponseHandlerFactory.createResponseHandler(method); + return ResponseHandlerFactory.createResponseHandler( method ); } /** - * Called upon initialization, Will create the ConfigParser and get the - * RuleChain back. Will also configure the httpclient. + * Called upon initialization, Will create the ConfigParser and get the RuleChain back. Will also configure the + * httpclient. * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ - public void init(FilterConfig filterConfig) throws ServletException { - log = LogFactory.getLog(ProxyFilter.class); - AllowedMethodHandler.setAllowedMethods("OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE"); - - httpClient = new HttpClient(new MultiThreadedHttpConnectionManager()); - httpClient.getParams().setBooleanParameter(HttpClientParams.USE_EXPECT_CONTINUE, false); - httpClient.getParams().setCookiePolicy(CookiePolicy.IGNORE_COOKIES); - - String data = filterConfig.getInitParameter("dataUrl"); - if (data == null) { - serverChain = null; + public void init( FilterConfig filterConfig ) + throws ServletException { + log = LogFactory.getLog( ProxyFilter.class ); + AllowedMethodHandler.setAllowedMethods( "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE" ); + + httpClient = new HttpClient( new MultiThreadedHttpConnectionManager() ); + httpClient.getParams().setBooleanParameter( HttpClientParams.USE_EXPECT_CONTINUE, false ); + httpClient.getParams().setCookiePolicy( CookiePolicy.IGNORE_COOKIES ); + + String proxyConfigFile = filterConfig.getInitParameter( "proxyConfigResource" ); + String proxyConfigEnv = filterConfig.getInitParameter( "proxyConfigEnv" ); + if ( proxyConfigFile != null ) { + parseConfigFromFileInClasspath( proxyConfigFile ); + } else if ( proxyConfigEnv != null ) { + parseConfigFileFromSystemEnvDirectory( proxyConfigEnv ); } else { - try { - File dataFile = new File(filterConfig.getServletContext().getRealPath(data)); - ConfigParser parser = new ConfigParser(dataFile); - serverChain = parser.getServerChain(); - } catch (Exception e) { - throw new ServletException(e); - } + parseConfigFileFromDefaultPath( filterConfig ); + } + } + + private void parseConfigFromFileInClasspath( String proxyConfigFile ) + throws ServletException { + try { + InputStream resourceAsStream = ProxyFilter.class.getResourceAsStream( proxyConfigFile ); + ConfigParser parser = new ConfigParser( resourceAsStream ); + serverChain = parser.getServerChain(); + } catch ( Exception e ) { + log.error( "j2ep configuration could not be read from classpath resource!", e ); + throw new ServletException( e ); + } + } + + private void parseConfigFileFromSystemEnvDirectory( String proxyConfigEnv ) + throws ServletException { + try { + String path = buildConfigFilePath( proxyConfigEnv ); + processConfiguration( path ); + } catch ( Exception e ) { + log.error( "j2ep configuration could not be read from system environment variable!", e ); + throw new ServletException( e ); } } + private void parseConfigFileFromDefaultPath( FilterConfig filterConfig ) + throws ServletException { + String path = null; + try { + path = filterConfig.getServletContext().getRealPath( DEFAULT_PATH ); + processConfiguration( path ); + } catch ( Exception e ) { + log.error( "j2ep configuration could not be read from default path " + path, e ); + throw new ServletException( e ); + } + } + + private void processConfiguration( String path ) { + File dataFile = new File( path ); + ConfigParser parser = new ConfigParser( dataFile ); + serverChain = parser.getServerChain(); + } + + private String buildConfigFilePath( String proxyConfigEnv ) { + String path = System.getenv( proxyConfigEnv ); + if ( !path.endsWith( "/" ) ) + path += "/"; + path += CONFIG_XML; + return path; + } + /** - * Called when this filter is destroyed. - * Releases the fields. + * Called when this filter is destroyed. Releases the fields. * * @see javax.servlet.Filter#destroy() */ @@ -221,4 +288,4 @@ public void destroy() { httpClient = null; serverChain = null; } -} \ No newline at end of file +} diff --git a/src/main/java/net/sf/j2ep/rules/DirectoryRule.java b/src/main/java/net/sf/j2ep/rules/DirectoryRule.java index c8e80c1..a6833de 100644 --- a/src/main/java/net/sf/j2ep/rules/DirectoryRule.java +++ b/src/main/java/net/sf/j2ep/rules/DirectoryRule.java @@ -19,82 +19,121 @@ import javax.servlet.http.HttpServletRequest; /** - * A rule that will check the start of the URI for a specifed - * starting directory/directories. If the directory is at the start this - * rule matches. The process method will then remove this directory - * from the URI, making it easy to map various servers to directory - * structures. - * If one needs some more advanced types of rewriting use the RewriteRule. - * + * A rule that will check the start of the URI for a specifed starting directory/directories. If the directory is at the + * start this rule matches. The process method will then remove this directory from the URI, making it easy to map + * various servers to directory structures. If one needs some more advanced types of rewriting use the RewriteRule. + * * @author Anders Nyman */ public class DirectoryRule extends BaseRule { - /** + /** * The directory structure. */ private String directory; - + + /** + * The originally set directory structure before appending and prepending slashes + */ + private String originalDirectory; + + private boolean isAppendTrailingSlash = true; + + /** + * Decide whether a trailing slash should be appended to directory settings without a trailing slash. + * + * @param isAppendTrailingSlash + */ + public void setIsAppendTrailingSlash( String isAppendTrailingSlash ) { + if ( isAppendTrailingSlash != null && isAppendTrailingSlash.equals( "false" ) ) { + this.isAppendTrailingSlash = false; + directory = prependSlashIfNeccessary( originalDirectory ); + } + } + + /** + * Return the trailing slash setting + * + * @return true if slashes are appended to directory settings that do not end with a slash, false if not + */ + public boolean getAppendTrailingSlash() { + return isAppendTrailingSlash; + } + /** - * Sets the directory structure that will - * be mapped to a specified server. - * - * @param directory The directory string + * Sets the directory structure that will be mapped to a specified server. + * + * @param directory + * The directory string */ - public void setDirectory(String directory) { - if (directory == null) { - throw new IllegalArgumentException( - "The directory string cannot be null."); + public void setDirectory( String directory ) { + if ( directory == null ) { + throw new IllegalArgumentException( "The directory string cannot be null." ); } else { - if (!directory.startsWith("/")) { + if ( !directory.startsWith( "/" ) ) { directory = "/" + directory; } - if (!directory.endsWith(("/"))) { - directory += "/"; - } + originalDirectory = directory; + directory = prependSlashIfNeccessary( directory ); + directory = appendSlashIfNeccessary( directory ); this.directory = directory; } } + private String appendSlashIfNeccessary( String directory ) { + if ( !directory.endsWith( ( "/" ) ) && isAppendTrailingSlash ) { + directory += "/"; + } + return directory; + } + + private String prependSlashIfNeccessary( String directory ) { + if ( !directory.startsWith( "/" ) ) { + directory = "/" + directory; + } + return directory; + } + /** - * Returns the directory structure that - * this rule will match on. - * + * Returns the directory structure that this rule will match on. + * * @return The directory string */ public String getDirectory() { return directory; } - + /** - * Will see if the directory for the incoming URI is the same - * as this rule is set to match on. + * Will see if the directory for the incoming URI is the same as this rule is set to match on. * * @see net.sf.j2ep.model.Rule#matches(javax.servlet.http.HttpServletRequest) */ - public boolean matches(HttpServletRequest request) { + public boolean matches( HttpServletRequest request ) { String uri = request.getServletPath(); - return (uri.startsWith(directory)); + return ( uri.startsWith( directory ) ); } - + /** * Removes the specified mapping directory from the URI. * * @see net.sf.j2ep.model.Rule#process(java.lang.String) */ - public String process(String uri) { - return uri.substring(directory.length()-1); + public String process( String uri ) { + if ( !isAppendTrailingSlash ) + return uri.substring( directory.length() ); + else + return uri.substring( directory.length() - 1 ); } - + /** - * Does the opposite of process. revert(String URI) will add the directory - * specified to the start of the incoming URI. + * Does the opposite of process. revert(String URI) will add the directory specified to the start of the incoming + * URI. * * @see net.sf.j2ep.model.Rule#revert(java.lang.String) */ - public String revert(String uri) { - if (uri.startsWith("/")) { - return directory + uri.substring(1); + public String revert( String uri ) { + if ( uri.startsWith( "/" ) ) { + return directory + uri.substring( 1 ); } else { return uri; } diff --git a/src/main/java/net/sf/j2ep/servers/BaseServerFromUrlCreator.java b/src/main/java/net/sf/j2ep/servers/BaseServerFromUrlCreator.java new file mode 100644 index 0000000..9070e5d --- /dev/null +++ b/src/main/java/net/sf/j2ep/servers/BaseServerFromUrlCreator.java @@ -0,0 +1,94 @@ +package net.sf.j2ep.servers; + +import net.sf.j2ep.model.Server; +import net.sf.j2ep.rules.DirectoryRule; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + +/** + * Creates a BaseServer-object from passed url. + * + * @author Dirk Stenger + * @author last edited by: $Author: stenger $ + * @version $Revision: $, $Date: $ + */ +public class BaseServerFromUrlCreator { + + private static final String BASE_SERVER_IS_REWRITING = "true"; + + private static final String DIRECTORY_RULE_IS_APPENDING_TRAILING_SLASH = "false"; + + /** + * Create a BaseServer-object from url and request. + * + * @param url, never null + * @param request, never null + * @return Server + */ + public Server createServer( String url, ServletRequest request ) { + checkRequiredParameters( url, request ); + String urlWithoutProtocol = retrieveUrlWithoutProtocol( url ); + int divideDomainNameAndPathIndex = urlWithoutProtocol.indexOf( "/" ); + String domainName = urlWithoutProtocol.substring( 0, divideDomainNameAndPathIndex ); + String path = retrievePath( urlWithoutProtocol, divideDomainNameAndPathIndex ); + String directoryPath = retrieveDirectoryPath( request ); + return createServer( domainName, path, directoryPath ); + } + + private String retrieveUrlWithoutProtocol( String url ) { + if ( url.contains( "//" ) ) { + int protocolIndex = url.indexOf( "//" ); + return url.substring( protocolIndex + 2 ); + } else { + return url; + } + } + + private String retrievePath( String urlWithoutProtocol, int divideDomainNameAndPathIndex ) { + String path = urlWithoutProtocol.substring( divideDomainNameAndPathIndex ); + if ( path.endsWith( "?" ) ) + return path.substring( 0, path.length() - 1 ); + else + return path; + } + + private String retrieveDirectoryPath( ServletRequest request ) { + String directoryPath = ( (HttpServletRequest) request ).getServletPath(); + if ( directoryPath.contains( "/" ) ) { + int directoryPathIndex = directoryPath.lastIndexOf( "/" ); + return directoryPath.substring( directoryPathIndex ); + } else { + return directoryPath; + } + } + + private Server createServer( String domainName, String path, String directoryPath ) { + BaseServer baseServer = createBaseServer( domainName, path ); + DirectoryRule directoryRule = createDirectoryRule( directoryPath ); + baseServer.setRule( directoryRule ); + return baseServer; + } + + private BaseServer createBaseServer( String domainName, String path ) { + BaseServer baseServer = new BaseServer(); + baseServer.setDomainName( domainName ); + baseServer.setPath( path ); + baseServer.setIsRewriting( BASE_SERVER_IS_REWRITING ); + return baseServer; + } + + private DirectoryRule createDirectoryRule( String directoryPath ) { + DirectoryRule directoryRule = new DirectoryRule(); + directoryRule.setDirectory( directoryPath ); + directoryRule.setIsAppendTrailingSlash( DIRECTORY_RULE_IS_APPENDING_TRAILING_SLASH ); + return directoryRule; + } + + private void checkRequiredParameters( String url, ServletRequest request ) { + if ( url == null ) + throw new IllegalArgumentException( "Url must not be null!" ); + if ( request == null ) + throw new IllegalArgumentException( "Request must not be null!" ); + } +} diff --git a/src/main/resources/logging.properties b/src/main/resources/logging.properties index f732ee5..393446e 100644 --- a/src/main/resources/logging.properties +++ b/src/main/resources/logging.properties @@ -1,14 +1,8 @@ -handlers = org.apache.juli.FileHandler - ############################################################ # Handler specific properties. # Describes specific configuration info for Handlers. ############################################################ -org.apache.juli.FileHandler.level = FINEST -org.apache.juli.FileHandler.directory = /logs -org.apache.juli.FileHandler.prefix = j2ep. - .level=INFO httpclient.wire.header.level=INFO diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index 20dbb1a..5cf3c17 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -14,8 +14,8 @@ Proxy net.sf.j2ep.ProxyFilter - dataUrl - /WEB-INF/config/data.xml + proxyConfigEnv + PROXY_CONFIG diff --git a/src/test/java/net/sf/j2ep/servers/BaseServerFromUrlCreatorTest.java b/src/test/java/net/sf/j2ep/servers/BaseServerFromUrlCreatorTest.java new file mode 100644 index 0000000..cb7d7c4 --- /dev/null +++ b/src/test/java/net/sf/j2ep/servers/BaseServerFromUrlCreatorTest.java @@ -0,0 +1,98 @@ +package net.sf.j2ep.servers; + +import junit.framework.TestCase; +import net.sf.j2ep.model.Server; +import net.sf.j2ep.rules.DirectoryRule; + +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +/** + * Tests for BaseServerFromUrlCreator. + * + * @author Dirk Stenger + * @author last edited by: $Author: stenger $ + * @version $Revision: $, $Date: $ + */ +public class BaseServerFromUrlCreatorTest extends TestCase { + + private static final String URL = "http://www.test.de/url/j2ep?"; + + private static final String URL_WITHOUT_PROTOCOL = "www.test.de/url/j2ep?"; + + private static final String URL_WITHOUT_QUESTION_MARK = "http://www.test.de/url/j2ep"; + + private static final String REQUEST_SERVLET_PATH = "/path"; + + private static final String EXPECTED_DOMAIN_NAME = "www.test.de"; + + private static final String EXPECTED_PATH = "/url/j2ep"; + + private static final String EXPECTED_DIRECTORY = "/path"; + + private final BaseServerFromUrlCreator serverCreator = new BaseServerFromUrlCreator(); + + public void testCreateServer() { + ServletRequest request = mockServletRequest(); + Server server = serverCreator.createServer( URL, request ); + + assertEquals( EXPECTED_DOMAIN_NAME, server.getDomainName() ); + assertEquals( EXPECTED_PATH, server.getPath() ); + DirectoryRule rule = (DirectoryRule) server.getRule(); + assertEquals( EXPECTED_DIRECTORY, rule.getDirectory() ); + } + + public void testCreateServerWithoutProtocol() { + ServletRequest request = mockServletRequest(); + Server server = serverCreator.createServer( URL_WITHOUT_PROTOCOL, request ); + + assertEquals( EXPECTED_DOMAIN_NAME, server.getDomainName() ); + assertEquals( EXPECTED_PATH, server.getPath() ); + DirectoryRule rule = (DirectoryRule) server.getRule(); + assertEquals( EXPECTED_DIRECTORY, rule.getDirectory() ); + } + + public void testCreateServerWithoutQuestionMark() { + ServletRequest request = mockServletRequest(); + Server server = serverCreator.createServer( URL_WITHOUT_QUESTION_MARK, request ); + + assertEquals( EXPECTED_DOMAIN_NAME, server.getDomainName() ); + assertEquals( EXPECTED_PATH, server.getPath() ); + DirectoryRule rule = (DirectoryRule) server.getRule(); + assertEquals( EXPECTED_DIRECTORY, rule.getDirectory() ); + } + + public void testCreateServerWithNullValues() { + try { + serverCreator.createServer( null, null ); + fail( "Expected an IllegalArugmentException to be thrown" ); + } catch ( IllegalArgumentException exception ) { + } + } + + public void testCreateServerWithUrlNullValue() { + ServletRequest request = mockServletRequest(); + try { + serverCreator.createServer( null, request ); + fail( "Expected an IllegalArugmentException to be thrown" ); + } catch ( IllegalArgumentException exception ) { + } + } + + public void testCreateServerWithRequestNullValue() { + try { + serverCreator.createServer( URL, null ); + fail( "Expected an IllegalArugmentException to be thrown" ); + } catch ( IllegalArgumentException exception ) { + } + } + + private ServletRequest mockServletRequest() { + HttpServletRequest request = mock( HttpServletRequest.class ); + doReturn( REQUEST_SERVLET_PATH ).when( request ).getServletPath(); + return request; + } +}