diff --git a/plugin/META-INF/MANIFEST.MF b/plugin/META-INF/MANIFEST.MF index 703d758..abf8316 100644 --- a/plugin/META-INF/MANIFEST.MF +++ b/plugin/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Base Bundle-SymbolicName: com.siemens.bt.jazz.services.base;singleton:=true -Bundle-Version: 3.0.3.qualifier +Bundle-Version: 4.0.0.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Export-Package: com.siemens.bt.jazz.services.base, com.siemens.bt.jazz.services.base.rest, diff --git a/plugin/pom.xml b/plugin/pom.xml index 6f96f16..b5d73f2 100644 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -6,7 +6,7 @@ com.siemens.bt.jazz.services.base com.siemens.bt.jazz.services.base.parent - 3.0.3-SNAPSHOT + 4.0.0-SNAPSHOT ../ diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/BaseService.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/BaseService.java index 4e3dbb5..35e8f4a 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/BaseService.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/BaseService.java @@ -4,7 +4,6 @@ import com.ibm.team.repository.service.TeamRawService; import com.siemens.bt.jazz.services.base.rest.RestAction; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.router.Router; import com.siemens.bt.jazz.services.base.router.map.MapRouter; import java.io.IOException; @@ -22,11 +21,7 @@ public abstract class BaseService extends TeamRawService { protected final Router router = new MapRouter(); - /** - * Constructs a new ClearQuestService - * - *

This constructor is only called by the Jazz class loader. - */ + /** This constructor is only called by the Jazz class loader. */ public BaseService() { super(); } @@ -79,16 +74,16 @@ protected void performAction(String uri, HttpServletRequest request, HttpServlet try { RestActionBuilder builder = prepareRequest(uri, request, response); RestAction action = builder.create(); + action.prepare(); action.execute(); + action.cleanUp(); } catch (IOException e) { throw e; } catch (Exception e) { // catch everything and log. Makes sure that there is no checked exception from our service - // back - // to jazz, except for the expected IOException when the response isn't writable. We need to - // make - // sure that our plug-in conforms to the contract that no exceptions bubble out into the - // system. + // back to jazz, except for the expected IOException when the response isn't writable. We need + // to make sure that our plug-in conforms to the contract that no exceptions bubble out into + // the system. super.getLog().error(e); this.http500return(request, response, e); } @@ -97,8 +92,6 @@ protected void performAction(String uri, HttpServletRequest request, HttpServlet protected final RestActionBuilder prepareRequest( String uri, HttpServletRequest request, HttpServletResponse response) { HttpMethod method = HttpMethod.fromString(request.getMethod()); - @SuppressWarnings("unchecked") - RestRequest restRequest = new RestRequest(method, uri, request.getParameterMap()); - return router.prepareAction(this, this.getLog(), request, response, restRequest); + return router.prepareAction(uri, this, this.getLog(), request, response); } } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/Configuration.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/Configuration.java new file mode 100644 index 0000000..317ebbe --- /dev/null +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/Configuration.java @@ -0,0 +1,38 @@ +package com.siemens.bt.jazz.services.base.configuration; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; + +public class Configuration { + // make sure every configurator is added exactly once + protected Collection configurations = new HashSet<>(); + + public Configuration() {} + + public Configuration(ServiceConfigurator... configurators) { + configurations.addAll(Arrays.asList(configurators)); + } + + public Configuration(Configuration... configurations) { + for (Configuration c : configurations) { + this.configurations.addAll(c.get()); + } + } + + public Collection get() { + return configurations; + } + + public void add(ServiceConfigurator configurator) { + configurations.add(configurator); + } + + public void add(Collection configurators) { + configurations.addAll(configurators); + } + + public void merge(Configuration other) { + this.configurations.addAll(other.get()); + } +} diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/ServiceConfigurator.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/ServiceConfigurator.java new file mode 100644 index 0000000..b0d5da3 --- /dev/null +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/ServiceConfigurator.java @@ -0,0 +1,14 @@ +package com.siemens.bt.jazz.services.base.configuration; + +import com.ibm.team.repository.service.TeamRawService; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; + +public interface ServiceConfigurator { + void configure( + Log log, + HttpServletRequest request, + HttpServletResponse response, + TeamRawService parentService); +} diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/ContentConfigurator.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/ContentConfigurator.java new file mode 100644 index 0000000..a10370b --- /dev/null +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/ContentConfigurator.java @@ -0,0 +1,25 @@ +package com.siemens.bt.jazz.services.base.configuration.preset; + +import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.ServiceConfigurator; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; + +public class ContentConfigurator implements ServiceConfigurator { + + private final String contentType; + + public ContentConfigurator(String contentType) { + this.contentType = contentType; + } + + @Override + public void configure( + Log log, + HttpServletRequest request, + HttpServletResponse response, + TeamRawService parentService) { + response.setContentType(contentType); + } +} diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/EncodingConfigurator.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/EncodingConfigurator.java new file mode 100644 index 0000000..b098290 --- /dev/null +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/configuration/preset/EncodingConfigurator.java @@ -0,0 +1,25 @@ +package com.siemens.bt.jazz.services.base.configuration.preset; + +import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.ServiceConfigurator; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.commons.logging.Log; + +public class EncodingConfigurator implements ServiceConfigurator { + + private final String encoding; + + public EncodingConfigurator(String encoding) { + this.encoding = encoding; + } + + @Override + public void configure( + Log log, + HttpServletRequest request, + HttpServletResponse response, + TeamRawService parentService) { + response.setCharacterEncoding(encoding); + } +} diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestAction.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestAction.java index 37979a1..8e7d949 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestAction.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestAction.java @@ -8,10 +8,19 @@ * @see Wikipedia: Command Pattern */ public interface RestAction { + /** + * Calls the preparation hook of the service. This step is called before execute and provides a + * hook where optional configurations can be applied to an action before executing it. + */ + void prepare(); + /** * Executes the implemented action. * * @throws Exception Any exception that occurs while executing a service action. */ void execute() throws Exception; + + /** Optional post-execution hook for actions that are run after the execute phase. */ + void cleanUp(); } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestActionBuilder.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestActionBuilder.java index 1128b5b..bfe5474 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestActionBuilder.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/RestActionBuilder.java @@ -1,8 +1,8 @@ package com.siemens.bt.jazz.services.base.rest; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.parameters.PathParameters; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -25,15 +25,29 @@ public class RestActionBuilder { protected final Class serviceClass; protected final String path; + protected String uri; protected HttpServletRequest request; protected HttpServletResponse response; + protected Configuration configuration; protected Log log; - protected RestRequest restRequest; protected TeamRawService parentService; - public RestActionBuilder(String path, Class serviceClass) { + public RestActionBuilder( + String path, Class serviceClass, Configuration configuration) { this.path = path; this.serviceClass = serviceClass; + this.configuration = configuration; + } + + /** + * Sets the URI passed in from the calling servlet + * + * @param uri String representation of the URI resolving this service + * @return RestActionBuilder in construction + */ + public RestActionBuilder setUri(String uri) { + this.uri = uri; + return this; } /** @@ -70,13 +84,13 @@ public RestActionBuilder setResponse(HttpServletResponse response) { } /** - * Set a RestRequest. + * Add a configuration wrapper to this RestAction * - * @param restRequest Summary of REST call information + * @param configuration Zero or more configurators that are applied before this action is executed * @return RestActionBuilder in construction */ - public RestActionBuilder setRestRequest(RestRequest restRequest) { - this.restRequest = restRequest; + public RestActionBuilder setConfiguration(Configuration configuration) { + this.configuration = configuration; return this; } @@ -103,19 +117,15 @@ public RestAction create() InstantiationException { Constructor constructor = serviceClass.getConstructor( + String.class, Log.class, HttpServletRequest.class, HttpServletResponse.class, - RestRequest.class, + Configuration.class, TeamRawService.class, PathParameters.class); return constructor.newInstance( - log, - request, - response, - restRequest, - parentService, - new PathParameters(path, restRequest.toString())); + uri, log, request, response, configuration, parentService, new PathParameters(path, uri)); } } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/parameters/RestRequest.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/parameters/RestRequest.java deleted file mode 100644 index cd4271f..0000000 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/parameters/RestRequest.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.siemens.bt.jazz.services.base.rest.parameters; - -import com.ibm.team.jfs.app.http.util.HttpConstants.HttpMethod; -import java.util.*; - -/** - * Class for condensing the most frequently used request information sent to the service. - * - *

Just a class that's easier to handle and cheap to build compared to HttServletRequest. Adds - * the path navigation facility required for efficient routing. - * - *

All functions that handle parameters could be extracted to a separate RequestParameters class. - */ -public final class RestRequest implements Iterable { - private final Deque uriQueue; - private final String originalUri; - private final Map parameters; - private final HttpMethod method; - - /** - * Constructs a RestRequest from a method and a uri. - * - * @param method The HTTP method with which the request was made - * @param uri Destination URI of the request - */ - public RestRequest(HttpMethod method, String uri) { - this(method, uri, null); - } - - /** - * Constructs a RestRequest including optional parameters. - * - * @param method The HTTP method with which the request was made - * @param uri Destination URI of the request - * @param map Parameters passed to the service in the form of ?paramName=paramValue - */ - public RestRequest(HttpMethod method, String uri, Map map) { - this.method = method; - this.originalUri = uri; - this.parameters = map; - - String[] pathFragments = uri.split("/"); - this.uriQueue = new ArrayDeque<>(Arrays.asList(pathFragments)); - } - - /** - * Check if a given parameter was passed to the request. - * - * @param key Parameter name to check for - * @return True if a parameter corresponding to key was found, false otherwise - */ - public boolean hasParameter(String key) { - return this.parameters.containsKey(key); - } - - /** - * Returns the parameter value of a given key. - * - * @param key Key to look for - * @return Parameter value corresponding to key, null if it doesn't exist - */ - public String getParameterValue(String key) { - // This is a nice place for Optional - if (this.parameters.size() > 0 && this.hasParameter(key)) { - return this.parameters.get(key)[0]; - } - - return null; - } - - /** - * Checks if there is a next path fragment of the current URL. - * - *

A path fragment is a part of a slash separated URL: {@code /these/are/fragments} Required - * for navigating the path efficiently. - * - * @return True if there are more fragments, false otherwise - */ - public boolean hasNextpath() { - return !this.uriQueue.isEmpty(); - } - - /** - * Next path fragment of the URL, starting at the front of the URL; removes the fragment. - * - *

A path fragment is a part of a slash separated URL: {@code /these/are/fragments} Required - * for navigating the path efficiently. - * - * @return The next path fragment - */ - public String nextPath() { - return this.uriQueue.pop(); - } - - /** - * Next path fragment, without removing it from the path. - * - *

This function is a candidate for removal in a future release. - * - * @return The next path fragment - */ - public String peekNextPath() { - return this.uriQueue.peek(); - } - - /** - * Returns the HTTP method the request was made with. - * - * @return the method - */ - public HttpMethod getMethod() { - return this.method; - } - - /** - * String representation of the original request, returns the URL in standard format. - * {@inheritDoc} - */ - @Override - public String toString() { - return this.originalUri; - } - - /** Iterator for looping over the rest-path. {@inheritDoc} */ - public Iterator iterator() { - return this.uriQueue.iterator(); - } -} diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/AbstractRestService.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/AbstractRestService.java index d8eb1f1..8bd4674 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/AbstractRestService.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/AbstractRestService.java @@ -1,34 +1,50 @@ package com.siemens.bt.jazz.services.base.rest.service; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; +import com.siemens.bt.jazz.services.base.configuration.ServiceConfigurator; import com.siemens.bt.jazz.services.base.rest.RestAction; import com.siemens.bt.jazz.services.base.rest.parameters.PathParameters; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; /** Abstract class that represents a REST service. */ public abstract class AbstractRestService implements RestAction { + + protected String uri; protected Log log; protected HttpServletRequest request; protected HttpServletResponse response; - protected RestRequest restRequest; protected TeamRawService parentService; protected PathParameters pathParameters; + protected Configuration configuration; public AbstractRestService( + String uri, Log log, HttpServletRequest request, HttpServletResponse response, - RestRequest restRequest, + Configuration configuration, TeamRawService parentService, PathParameters pathParameters) { + this.uri = uri; this.log = log; this.request = request; this.response = response; - this.restRequest = restRequest; + this.configuration = configuration; this.parentService = parentService; this.pathParameters = pathParameters; } + + /** The default implementation applies all provided configurations in no pre-defined order */ + @Override + public void prepare() { + for (ServiceConfigurator configurator : configuration.get()) { + configurator.configure(log, request, response, parentService); + } + } + + @Override + public void cleanUp() {} } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/DefaultRestService.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/DefaultRestService.java index 85c366f..396645f 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/DefaultRestService.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/rest/service/DefaultRestService.java @@ -1,8 +1,8 @@ package com.siemens.bt.jazz.services.base.rest.service; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.parameters.PathParameters; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import java.io.IOException; import java.io.Writer; import java.net.URISyntaxException; @@ -25,13 +25,14 @@ public final class DefaultRestService extends AbstractRestService { public DefaultRestService( + String uri, Log log, HttpServletRequest request, HttpServletResponse response, - RestRequest restRequest, + Configuration configuration, TeamRawService parentService, PathParameters pathParameters) { - super(log, request, response, restRequest, parentService, pathParameters); + super(uri, log, request, response, configuration, parentService, pathParameters); } /** @@ -48,7 +49,7 @@ public void execute() throws IOException, URISyntaxException { String answer = String.format( "The requested service \"%s\" doesn't exist for method \"%s\".", - restRequest, request.getMethod()); + uri, request.getMethod()); writer.write(answer); } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/Router.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/Router.java index cfb611c..1e99ff6 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/Router.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/Router.java @@ -2,8 +2,9 @@ import com.ibm.team.jfs.app.http.util.HttpConstants.HttpMethod; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; +import com.siemens.bt.jazz.services.base.configuration.ServiceConfigurator; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; import com.siemens.bt.jazz.services.base.router.factory.ServiceFactory; import javax.servlet.http.HttpServletRequest; @@ -27,12 +28,41 @@ public interface Router { void get(String path, Class service); + void get(String path, Class service, Configuration configuration); + + void get( + String path, + Class service, + ServiceConfigurator... configurators); + void put(String path, Class service); + void put(String path, Class service, Configuration configuration); + + void put( + String path, + Class service, + ServiceConfigurator... configurators); + void post(String path, Class service); + void post(String path, Class service, Configuration configuration); + + void post( + String path, + Class service, + ServiceConfigurator... configurators); + void delete(String path, Class service); + void delete( + String path, Class service, Configuration configuration); + + void delete( + String path, + Class service, + ServiceConfigurator... configurators); + void get(ServiceFactory factory); void put(ServiceFactory factory); @@ -48,13 +78,12 @@ public interface Router { * @param log Log object * @param request The original HTTP Request * @param response The response object for writing back responses to the client - * @param restRequest A summary of the HTTP request, mainly used for navigation * @return A rest action that can be executed */ RestActionBuilder prepareAction( + String uri, TeamRawService parentService, Log log, HttpServletRequest request, - HttpServletResponse response, - RestRequest restRequest); + HttpServletResponse response); } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/factory/RestFactory.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/factory/RestFactory.java index e661349..fe0db69 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/factory/RestFactory.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/factory/RestFactory.java @@ -1,20 +1,28 @@ package com.siemens.bt.jazz.services.base.router.factory; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; public class RestFactory implements ServiceFactory { protected final Class serviceClass; protected final String path; + protected final Configuration configuration; - public RestFactory(String path, Class serviceClass) { + public RestFactory( + String path, Class serviceClass, Configuration configuration) { this.serviceClass = serviceClass; this.path = path; + this.configuration = configuration; + } + + public RestFactory(String path, Class serviceClass) { + this(path, serviceClass, new Configuration()); } @Override public RestActionBuilder getBuilder() { - return new RestActionBuilder(path, serviceClass); + return new RestActionBuilder(path, serviceClass, configuration); } @Override diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/map/MapRouter.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/map/MapRouter.java index 0ec1318..057733e 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/map/MapRouter.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/router/map/MapRouter.java @@ -2,8 +2,9 @@ import com.ibm.team.jfs.app.http.util.HttpConstants; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; +import com.siemens.bt.jazz.services.base.configuration.ServiceConfigurator; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; import com.siemens.bt.jazz.services.base.router.Router; import com.siemens.bt.jazz.services.base.router.factory.RestFactory; @@ -25,21 +26,81 @@ public void get(String path, Class service) { get(new RestFactory(path, service)); } + @Override + public void get( + String path, Class service, Configuration configuration) { + get(new RestFactory(path, service, configuration)); + } + + @Override + public void get( + String path, + Class service, + ServiceConfigurator... configurators) { + Configuration configuration = new Configuration(configurators); + get(new RestFactory(path, service, configuration)); + } + @Override public void put(String path, Class service) { put(new RestFactory(path, service)); } + @Override + public void put( + String path, Class service, Configuration configuration) { + put(new RestFactory(path, service, configuration)); + } + + @Override + public void put( + String path, + Class service, + ServiceConfigurator... configurators) { + Configuration configuration = new Configuration(configurators); + put(new RestFactory(path, service, configuration)); + } + @Override public void post(String path, Class service) { post(new RestFactory(path, service)); } + @Override + public void post( + String path, Class service, Configuration configuration) { + post(new RestFactory(path, service, configuration)); + } + + @Override + public void post( + String path, + Class service, + ServiceConfigurator... configurators) { + Configuration configuration = new Configuration(configurators); + post(new RestFactory(path, service, configuration)); + } + @Override public void delete(String path, Class service) { delete(new RestFactory(path, service)); } + @Override + public void delete( + String path, Class service, Configuration configuration) { + delete(new RestFactory(path, service, configuration)); + } + + @Override + public void delete( + String path, + Class service, + ServiceConfigurator... configurators) { + Configuration configuration = new Configuration(configurators); + delete(new RestFactory(path, service, configuration)); + } + @Override public void get(ServiceFactory factory) { addService(HttpConstants.HttpMethod.GET, factory); @@ -62,18 +123,18 @@ public void delete(ServiceFactory factory) { @Override public RestActionBuilder prepareAction( + String uri, TeamRawService parentService, Log log, HttpServletRequest request, - HttpServletResponse response, - RestRequest restRequest) { + HttpServletResponse response) { return services - .getFactory(request, restRequest.toString()) + .getFactory(request, uri) .getBuilder() + .setUri(uri) .setParentService(parentService) .setLog(log) .setRequest(request) - .setResponse(response) - .setRestRequest(restRequest); + .setResponse(response); } } diff --git a/plugin/src/main/java/com/siemens/bt/jazz/services/base/utils/RequestReader.java b/plugin/src/main/java/com/siemens/bt/jazz/services/base/utils/RequestReader.java index 75d071a..d0e647a 100644 --- a/plugin/src/main/java/com/siemens/bt/jazz/services/base/utils/RequestReader.java +++ b/plugin/src/main/java/com/siemens/bt/jazz/services/base/utils/RequestReader.java @@ -34,8 +34,9 @@ private RequestReader() {} * @return Content of request as string * @throws IOException If input stream is invalid */ - public static String readAsString(HttpServletRequest request) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream())); + public static String readAsString(HttpServletRequest request, String charset) throws IOException { + BufferedReader reader = + new BufferedReader(new InputStreamReader(request.getInputStream(), charset)); StringBuilder builder = new StringBuilder(request.getContentLength()); @@ -46,6 +47,10 @@ public static String readAsString(HttpServletRequest request) throws IOException return builder.toString(); } + public static String readAsString(HttpServletRequest request) throws IOException { + return readAsString(request, request.getCharacterEncoding()); + } + /** * Reads the body of a request and parses it as JSON. * @@ -57,8 +62,17 @@ public static String readAsString(HttpServletRequest request) throws IOException * @throws IOException If input stream is invalid */ public static JsonObject readAsJson(HttpServletRequest request) throws IOException { - String content = RequestReader.readAsString(request); - return new Gson().fromJson(content, JsonObject.class); + return readAsJson(request, request.getCharacterEncoding(), JsonObject.class); + } + + public static JsonObject readAsJson(HttpServletRequest request, String charset) + throws IOException { + return readAsJson(request, charset, JsonObject.class); + } + + public static T readAsJson(HttpServletRequest request, String charset, Class type) + throws IOException { + return new Gson().fromJson(new InputStreamReader(request.getInputStream(), charset), type); } /** @@ -72,7 +86,11 @@ public static JsonObject readAsJson(HttpServletRequest request) throws IOExcepti * @throws IOException If input stream is invalid */ public static JsonArray readAsArray(HttpServletRequest request) throws IOException { - String content = RequestReader.readAsString(request); + return readAsArray(request, request.getCharacterEncoding()); + } + + public static JsonArray readAsArray(HttpServletRequest request, String charset) throws IOException { + String content = RequestReader.readAsString(request, charset); return new Gson().fromJson(content, JsonArray.class); } diff --git a/pom.xml b/pom.xml index 2362b4c..3c0d84c 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.siemens.bt.jazz.services.base com.siemens.bt.jazz.services.base.parent pom - 3.0.3-SNAPSHOT + 4.0.0-SNAPSHOT com.google.code.gson diff --git a/test/META-INF/MANIFEST.MF b/test/META-INF/MANIFEST.MF index 420c3a1..af64948 100644 --- a/test/META-INF/MANIFEST.MF +++ b/test/META-INF/MANIFEST.MF @@ -2,13 +2,13 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: com.siemens.bt.jazz.services.base Bundle-SymbolicName: com.siemens.bt.jazz.services.base.test;singleton:=true -Bundle-Version: 3.0.3.qualifier +Bundle-Version: 4.0.0.qualifier Bundle-Vendor: VENDOR Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Bundle-ClassPath: target/dependency/junit-4.12.jar, target/dependency/hamcrest-core-1.3.jar, target/dependency/gson-2.8.5.jar, - target/dependency/com.siemens.bt.jazz.services.base-3.0.3-SNAPSHOT.jar, + target/dependency/com.siemens.bt.jazz.services.base-4.0.0-SNAPSHOT.jar, . Require-Bundle: com.ibm.team.repository.common, com.ibm.team.repository.service, diff --git a/test/pom.xml b/test/pom.xml index 309c408..c568dec 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -6,7 +6,7 @@ com.siemens.bt.jazz.services.base com.siemens.bt.jazz.services.base.parent - 3.0.3-SNAPSHOT + 4.0.0-SNAPSHOT ../ @@ -19,7 +19,7 @@ com.siemens.bt.jazz.services.base com.siemens.bt.jazz.services.base - 3.0.3-SNAPSHOT + 4.0.0-SNAPSHOT diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/DefaultServiceTest.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/DefaultServiceTest.java index dc5e3d9..92f0217 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/DefaultServiceTest.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/DefaultServiceTest.java @@ -2,9 +2,8 @@ import static org.junit.Assert.assertEquals; -import com.ibm.team.jfs.app.http.util.HttpConstants; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.parameters.PathParameters; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.DefaultRestService; import com.siemens.bt.jazz.services.base.test.helper.MockRequestFactory; import com.siemens.bt.jazz.services.base.test.helper.TestLogger; @@ -30,10 +29,11 @@ public void Runs_CorrectResponse() throws Exception { DefaultRestService service = new DefaultRestService( + "get_default_service", new TestLogger(), MockRequestFactory.httpGetRequest(), mockResponse, - new RestRequest(HttpConstants.HttpMethod.GET, "get_default_service"), + new Configuration(), new MockTeamService(), new PathParameters("", "")); diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/RestActionBuilderTest.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/RestActionBuilderTest.java index 6090e1e..c6ce62d 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/RestActionBuilderTest.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/RestActionBuilderTest.java @@ -2,10 +2,9 @@ import static org.junit.Assert.*; -import com.ibm.team.jfs.app.http.util.HttpConstants; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.RestAction; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; import com.siemens.bt.jazz.services.base.test.helper.MockRequestFactory; import com.siemens.bt.jazz.services.base.test.helper.TestLogger; @@ -32,14 +31,15 @@ public void Constructor_Creates() throws Exception { MockTeamService mockParent = new MockTeamService(); MockRequest mockRequest = MockRequestFactory.httpGetRequest(); MockResponse mockResponse = new MockResponse(); - RestRequest restRequest = new RestRequest(HttpConstants.HttpMethod.GET, "doesn't matter"); + String uri = "doesn't matter"; testBuilder + .setUri(uri) .setLog(log) .setParentService(mockParent) .setRequest(mockRequest) .setResponse(mockResponse) - .setRestRequest(restRequest); + .setConfiguration(new Configuration()); RestAction service = testBuilder.create(); @@ -74,13 +74,13 @@ public void Constructor_Creates() throws Exception { responseField.setAccessible(true); assertSame(mockResponse, responseField.get(service)); - Field restField = superClass.getDeclaredField("restRequest"); - restField.setAccessible(true); - assertSame(restRequest, restField.get(service)); + Field uriField = superClass.getDeclaredField("uri"); + uriField.setAccessible(true); + assertSame(uri, uriField.get(service)); } @Before public void setUp() throws Exception { - this.testBuilder = new RestActionBuilder("/", TestService.class); + this.testBuilder = new RestActionBuilder("/", TestService.class, new Configuration()); } } diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/RouterTest.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/RouterTest.java index 09eed0e..baf3c73 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/RouterTest.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/RouterTest.java @@ -6,7 +6,6 @@ import com.ibm.team.jfs.app.http.util.HttpConstants; import com.siemens.bt.jazz.services.base.rest.RestAction; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.DefaultRestService; import com.siemens.bt.jazz.services.base.router.Router; import com.siemens.bt.jazz.services.base.router.map.MapRouter; @@ -36,11 +35,11 @@ public void ServicePath_Root() throws Exception { RestActionBuilder builder = router.prepareAction( + "/", new MockTeamService(), new TestLogger(), MockRequestFactory.httpGetRequest(), - response, - new RestRequest(HttpConstants.HttpMethod.GET, "/")); + response); RestAction action = builder.create(); assertEquals(TestService.class, action.getClass()); @@ -57,11 +56,11 @@ public void ServicePath_NotExists() throws Exception { RestActionBuilder builder = router.prepareAction( + "no_service_here", new MockTeamService(), new TestLogger(), MockRequestFactory.httpGetRequest(), - response, - new RestRequest(HttpConstants.HttpMethod.GET, "no_service_here")); + response); RestAction action = builder.create(); @@ -80,11 +79,11 @@ public void ServicePath_Exists() throws Exception { RestActionBuilder builder = router.prepareAction( + "test/service/path", new MockTeamService(), new TestLogger(), MockRequestFactory.httpGetRequest(), - new MockResponse(), - new RestRequest(HttpConstants.HttpMethod.GET, "test/service/path")); + new MockResponse()); RestAction action = builder.create(); diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/helper/TestService.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/helper/TestService.java index 09dd56e..7f3b55a 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/helper/TestService.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/helper/TestService.java @@ -1,22 +1,24 @@ package com.siemens.bt.jazz.services.base.test.helper; import com.ibm.team.repository.service.TeamRawService; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.parameters.PathParameters; -import com.siemens.bt.jazz.services.base.rest.parameters.RestRequest; import com.siemens.bt.jazz.services.base.rest.service.AbstractRestService; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; public class TestService extends AbstractRestService { + public TestService( + String uri, Log log, HttpServletRequest request, HttpServletResponse response, - RestRequest restRequest, + Configuration configuration, TeamRawService parentService, PathParameters pathParameters) { - super(log, request, response, restRequest, parentService, pathParameters); + super(uri, log, request, response, configuration, parentService, pathParameters); } @Override diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockFactory.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockFactory.java index 1455e01..d4d7f36 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockFactory.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockFactory.java @@ -1,5 +1,6 @@ package com.siemens.bt.jazz.services.base.test.mock; +import com.siemens.bt.jazz.services.base.configuration.Configuration; import com.siemens.bt.jazz.services.base.rest.RestActionBuilder; import com.siemens.bt.jazz.services.base.router.factory.ServiceFactory; import com.siemens.bt.jazz.services.base.test.helper.TestService; @@ -17,7 +18,7 @@ public MockFactory(String path) { @Override public RestActionBuilder getBuilder() { - return new RestActionBuilder(path, TestService.class); + return new RestActionBuilder(path, TestService.class, new Configuration()); } @Override diff --git a/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockRequest.java b/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockRequest.java index 846f41b..982ada2 100644 --- a/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockRequest.java +++ b/test/src/test/java/com/siemens/bt/jazz/services/base/test/mock/MockRequest.java @@ -3,6 +3,7 @@ import com.siemens.bt.jazz.services.base.test.helper.TestInputStream; import java.io.BufferedReader; import java.io.IOException; +import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.security.Principal; import java.util.Collection; @@ -189,7 +190,7 @@ public Enumeration getAttributeNames() { @Override public String getCharacterEncoding() { - throw new RuntimeException("Not implemented in Mock."); + return "UTF-8"; } @Override @@ -254,7 +255,8 @@ public int getServerPort() { @Override public BufferedReader getReader() throws IOException { - throw new RuntimeException("Not implemented in Mock."); + StringReader stringReader = new StringReader(body); + return new BufferedReader(stringReader); } @Override