This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-servlet-helpers.git
commit a08abd816388ffb30c7797bb04a42ce05f97d8fb Author: Stefan Seifert <[email protected]> AuthorDate: Wed Jan 13 23:07:09 2016 +0000 SLING-5428 Move MockSlingHttpServletRequest+Response to org.apache.sling.servlet-helpers git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1724523 13f79535-47bb-0310-9956-ffa450edef68 --- README.txt | 29 + pom.xml | 106 +++ .../apache/sling/servlethelpers/CookieSupport.java | 53 ++ .../apache/sling/servlethelpers/HeaderSupport.java | 175 +++++ .../sling/servlethelpers/MockHttpSession.java | 169 +++++ .../MockRequestDispatcherFactory.java | 51 ++ .../sling/servlethelpers/MockRequestParameter.java | 105 +++ .../servlethelpers/MockRequestParameterMap.java | 101 +++ .../sling/servlethelpers/MockRequestPathInfo.java | 89 +++ .../sling/servlethelpers/MockServletContext.java | 304 ++++++++ .../MockSlingHttpServletRequest.java | 805 +++++++++++++++++++++ .../MockSlingHttpServletResponse.java | 282 ++++++++ .../sling/servlethelpers/ResponseBodySupport.java | 100 +++ .../apache/sling/servlethelpers/package-info.java | 23 + .../sling/servlethelpers/MockHttpSessionTest.java | 103 +++ .../servlethelpers/MockRequestPathInfoTest.java | 69 ++ .../servlethelpers/MockServletContextTest.java | 43 ++ .../MockSlingHttpServletRequestTest.java | 328 +++++++++ .../MockSlingHttpServletResponseTest.java | 177 +++++ 19 files changed, 3112 insertions(+) diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..64e9bb4 --- /dev/null +++ b/README.txt @@ -0,0 +1,29 @@ +Apache Sling Servlet Helpers + +Mock implementations of SlingHttpServletRequest, SlingHttpServletRepsonse and related classes. + +These are used by sling-mock, but can be used standalone and deployed to an OSGi container as well. + + +Getting Started +=============== + +This component uses a Maven 2 (http://maven.apache.org/) build +environment. It requires a Java 5 JDK (or higher) and Maven (http://maven.apache.org/) +2.0.7 or later. We recommend to use the latest Maven version. + +If you have Maven 2 installed, you can compile and +package the jar using the following command: + + mvn package + +See the Maven 2 documentation for other build features. + +The latest source code for this component is available in the +Subversion (http://subversion.tigris.org/) source repository of +the Apache Software Foundation. If you have Subversion installed, +you can checkout the latest source using the following command: + + svn checkout http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/servlet-helpers + +See the Subversion documentation for other source control features. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..56f63db --- /dev/null +++ b/pom.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> +<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"> + + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.sling</groupId> + <artifactId>sling</artifactId> + <version>26</version> + <relativePath/> + </parent> + + <artifactId>org.apache.sling.servlet-helpers</artifactId> + <packaging>bundle</packaging> + <version>1.0.0-SNAPSHOT</version> + + <name>Apache Sling Servlet Helpers</name> + <description>Mock implementations of SlingHttpServletRequest, SlingHttpServletRepsonse and related classes.</description> + + <scm> + <connection> + scm:svn:http://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/servlet-helpers + </connection> + <developerConnection> + scm:svn:https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/servlet-helpers + </developerConnection> + <url> + http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/servlet-helpers + </url> + </scm> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + </plugin> + </plugins> + </build> + + <dependencies> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.api</artifactId> + <version>2.4.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.0.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + <version>3.2.1</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + + </dependencies> + +</project> diff --git a/src/main/java/org/apache/sling/servlethelpers/CookieSupport.java b/src/main/java/org/apache/sling/servlethelpers/CookieSupport.java new file mode 100644 index 0000000..ffdde3c --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/CookieSupport.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.http.Cookie; + +/** + * Manages cookies for request and response. + */ +class CookieSupport { + + private Map<String, Cookie> cookies = new LinkedHashMap<String, Cookie>(); + + public void addCookie(Cookie cookie) { + cookies.put(cookie.getName(), cookie); + } + + public Cookie getCookie(String name) { + return cookies.get(name); + } + + public Cookie[] getCookies() { + if (cookies.isEmpty()) { + return null; + } else { + return cookies.values().toArray(new Cookie[cookies.size()]); + } + } + + public void reset() { + cookies.clear(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/HeaderSupport.java b/src/main/java/org/apache/sling/servlethelpers/HeaderSupport.java new file mode 100644 index 0000000..48a5f39 --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/HeaderSupport.java @@ -0,0 +1,175 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.TimeZone; +import java.util.Vector; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; + +/** + * Manage HTTP headers for request and response. + */ +class HeaderSupport { + + private static final String RFC_1123_DATE_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; + private static final DateFormat RFC1123_DATE_FORMAT = new SimpleDateFormat(RFC_1123_DATE_PATTERN, Locale.US); + private static final TimeZone TIMEZONE_GMT = TimeZone.getTimeZone("GMT"); + static { + RFC1123_DATE_FORMAT.setTimeZone(TIMEZONE_GMT); + } + + private List<HeaderValue> headers = new ArrayList<HeaderValue>(); + + private static class HeaderValue { + + private String key; + private String value; + + public HeaderValue(String key, String value) { + this.key = key; + this.value = value; + } + + public String getKey() { + return this.key; + } + + public String getValue() { + return this.value; + } + + } + + public void addHeader(String name, String value) { + headers.add(new HeaderValue(name, value)); + } + + public void addIntHeader(String name, int value) { + headers.add(new HeaderValue(name, Integer.toString(value))); + } + + public void addDateHeader(String name, long date) { + Calendar calendar = Calendar.getInstance(TIMEZONE_GMT, Locale.US); + calendar.setTimeInMillis(date); + headers.add(new HeaderValue(name, formatDate(calendar))); + } + + public void setHeader(String name, String value) { + removeHeaders(name); + addHeader(name, value); + } + + public void setIntHeader(String name, int value) { + removeHeaders(name); + addIntHeader(name, value); + } + + public void setDateHeader(String name, long date) { + removeHeaders(name); + addDateHeader(name, date); + } + + private void removeHeaders(String name) { + for (int i = this.headers.size() - 1; i >= 0; i--) { + if (StringUtils.equals(this.headers.get(i).getKey(), name)) { + headers.remove(i); + } + } + } + + public boolean containsHeader(String name) { + return !getHeaders(name).isEmpty(); + } + + public String getHeader(String name) { + Collection<String> values = getHeaders(name); + if (!values.isEmpty()) { + return values.iterator().next(); + } else { + return null; + } + } + + public int getIntHeader(String name) { + String value = getHeader(name); + return NumberUtils.toInt(value); + } + + public long getDateHeader(String name) { + String value = getHeader(name); + if (StringUtils.isEmpty(value)) { + return 0L; + } else { + try { + return parseDate(value).getTimeInMillis(); + } catch (ParseException ex) { + return 0L; + } + } + } + + public Collection<String> getHeaders(String name) { + List<String> values = new ArrayList<String>(); + for (HeaderValue entry : headers) { + if (StringUtils.equals(entry.getKey(), name)) { + values.add(entry.getValue()); + } + } + return values; + } + + public Collection<String> getHeaderNames() { + Set<String> values = new HashSet<String>(); + for (HeaderValue entry : headers) { + values.add(entry.getKey()); + } + return values; + } + + public void reset() { + headers.clear(); + } + + public static Enumeration<String> toEnumeration(Collection<String> collection) { + return new Vector<String>(collection).elements(); + } + + private static synchronized String formatDate(Calendar date) { + return RFC1123_DATE_FORMAT.format(date.getTime()); + } + + private static synchronized Calendar parseDate(String dateString) throws ParseException { + RFC1123_DATE_FORMAT.parse(dateString); + return RFC1123_DATE_FORMAT.getCalendar(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockHttpSession.java b/src/main/java/org/apache/sling/servlethelpers/MockHttpSession.java new file mode 100644 index 0000000..31d672b --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockHttpSession.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSession; + +import org.apache.commons.collections.IteratorUtils; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Mock {@link HttpSession} implementation. + */ +@ConsumerType +public class MockHttpSession implements HttpSession { + + private final ServletContext servletContext; + private final Map<String, Object> attributeMap = new HashMap<String, Object>(); + private final String sessionID = UUID.randomUUID().toString(); + private final long creationTime = System.currentTimeMillis(); + private boolean invalidated = false; + private boolean isNew = true; + private int maxActiveInterval = 1800; + + public MockHttpSession() { + this.servletContext = newMockServletContext(); + } + + protected MockServletContext newMockServletContext() { + return new MockServletContext(); + } + + @Override + public ServletContext getServletContext() { + return this.servletContext; + } + + @Override + public Object getAttribute(final String name) { + checkInvalidatedState(); + return this.attributeMap.get(name); + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration<String> getAttributeNames() { + checkInvalidatedState(); + return IteratorUtils.asEnumeration(this.attributeMap.keySet().iterator()); + } + + @Override + public String getId() { + return this.sessionID; + } + + @Override + public long getCreationTime() { + checkInvalidatedState(); + return this.creationTime; + } + + @Override + public Object getValue(final String name) { + checkInvalidatedState(); + return getAttribute(name); + } + + @Override + public String[] getValueNames() { + checkInvalidatedState(); + return this.attributeMap.keySet().toArray(new String[this.attributeMap.keySet().size()]); + } + + @Override + public void putValue(final String name, final Object value) { + checkInvalidatedState(); + setAttribute(name, value); + } + + @Override + public void removeAttribute(final String name) { + checkInvalidatedState(); + this.attributeMap.remove(name); + } + + @Override + public void removeValue(final String name) { + checkInvalidatedState(); + this.attributeMap.remove(name); + } + + @Override + public void setAttribute(final String name, final Object value) { + checkInvalidatedState(); + this.attributeMap.put(name, value); + } + + @Override + public void invalidate() { + checkInvalidatedState(); + this.invalidated = true; + } + + private void checkInvalidatedState() { + if (invalidated) { + throw new IllegalStateException("Session is already invalidated."); + } + } + + public boolean isInvalidated() { + return invalidated; + } + + @Override + public boolean isNew() { + checkInvalidatedState(); + return isNew; + } + + public void setNew(boolean isNew) { + this.isNew = isNew; + } + + @Override + public long getLastAccessedTime() { + checkInvalidatedState(); + return creationTime; + } + + @Override + public int getMaxInactiveInterval() { + return maxActiveInterval; + } + + @Override + public void setMaxInactiveInterval(final int interval) { + this.maxActiveInterval = interval; + } + + // --- unsupported operations --- + @Override + @SuppressWarnings("deprecation") + public javax.servlet.http.HttpSessionContext getSessionContext() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockRequestDispatcherFactory.java b/src/main/java/org/apache/sling/servlethelpers/MockRequestDispatcherFactory.java new file mode 100644 index 0000000..5664035 --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockRequestDispatcherFactory.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import javax.servlet.RequestDispatcher; + +import org.apache.sling.api.request.RequestDispatcherOptions; +import org.apache.sling.api.resource.Resource; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Interface to create a mock {@link RequestDispatcher} when calling the getRequestDispatcher methods + * on {@link MockSlingHttpServletRequest} instances. + */ +@ConsumerType +public interface MockRequestDispatcherFactory { + + /** + * Get request dispatcher for given path. + * @param path Path + * @param options Options. Null if no options are provided. + * @return Request dispatcher + */ + RequestDispatcher getRequestDispatcher(String path, RequestDispatcherOptions options); + + /** + * Get request dispatcher for given resource. + * @param resource Resource + * @param options Options. Null if no options are provided. + * @return Request dispatcher + */ + RequestDispatcher getRequestDispatcher(Resource resource, RequestDispatcherOptions options); + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockRequestParameter.java b/src/main/java/org/apache/sling/servlethelpers/MockRequestParameter.java new file mode 100644 index 0000000..2c77e3b --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockRequestParameter.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import org.apache.sling.api.request.RequestParameter; + +/** + * Mock implementation of {@link RequestParameter}. + */ +class MockRequestParameter implements RequestParameter { + + private String name; + private String encoding = "UTF-8"; + private String value; + + private byte[] content; + + public MockRequestParameter(String name, String value) { + this.value = value; + this.content = null; + } + void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public String getEncoding() { + return this.encoding; + } + + public byte[] get() { + if (content == null) { + try { + content = getString().getBytes(getEncoding()); + } catch (Exception e) { + // UnsupportedEncodingException, IllegalArgumentException + content = getString().getBytes(); + } + } + return content; + } + + public String getContentType() { + // none known for www-form-encoded parameters + return null; + } + + public InputStream getInputStream() { + return new ByteArrayInputStream(this.get()); + } + + public String getFileName() { + // no original file name + return null; + } + + public long getSize() { + return this.get().length; + } + + public String getString() { + return value; + } + + public String getString(String encoding) throws UnsupportedEncodingException { + return new String(this.get(), encoding); + } + + public boolean isFormField() { + // www-form-encoded are always form fields + return true; + } + + public String toString() { + return this.getString(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockRequestParameterMap.java b/src/main/java/org/apache/sling/servlethelpers/MockRequestParameterMap.java new file mode 100644 index 0000000..93e25de --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockRequestParameterMap.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.apache.sling.api.request.RequestParameter; +import org.apache.sling.api.request.RequestParameterMap; + +/** + * Mock implementation of {@link RequestParameterMap}. + */ +class MockRequestParameterMap implements RequestParameterMap { + + private final Map<String,RequestParameter[]> delegate = new HashMap<String, RequestParameter[]>(); + + public RequestParameter getValue(String name) { + RequestParameter[] params = getValues(name); + return (params != null && params.length > 0) ? params[0] : null; + } + + public RequestParameter[] getValues(String name) { + return delegate.get(name); + } + + public int size() { + return delegate.size(); + } + + public boolean isEmpty() { + return delegate.isEmpty(); + } + + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + public RequestParameter[] get(Object key) { + return delegate.get(key); + } + + public RequestParameter[] put(String key, RequestParameter[] value) { + return delegate.put(key, value); + } + + public RequestParameter[] remove(Object key) { + return delegate.remove(key); + } + + public void putAll(Map<? extends String, ? extends RequestParameter[]> m) { + delegate.putAll(m); + } + + public void clear() { + delegate.clear(); + } + + public Set<String> keySet() { + return delegate.keySet(); + } + + public Collection<RequestParameter[]> values() { + return delegate.values(); + } + + public Set<java.util.Map.Entry<String, RequestParameter[]>> entrySet() { + return delegate.entrySet(); + } + + public boolean equals(Object o) { + return delegate.equals(o); + } + + public int hashCode() { + return delegate.hashCode(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockRequestPathInfo.java b/src/main/java/org/apache/sling/servlethelpers/MockRequestPathInfo.java new file mode 100644 index 0000000..4c6439d --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockRequestPathInfo.java @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.request.RequestPathInfo; +import org.apache.sling.api.resource.Resource; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Mock {@link RequestPathInfo} implementation. + */ +@ConsumerType +public class MockRequestPathInfo implements RequestPathInfo { + + private String extension; + private String resourcePath; + private String selectorString; + private String suffix; + + @Override + public String getExtension() { + return this.extension; + } + + @Override + public String getResourcePath() { + return this.resourcePath; + } + + @Override + public String[] getSelectors() { + if (StringUtils.isEmpty(this.selectorString)) { + return new String[0]; + } else { + return StringUtils.split(this.selectorString, "."); + } + } + + @Override + public String getSelectorString() { + return this.selectorString; + } + + @Override + public String getSuffix() { + return this.suffix; + } + + public void setExtension(final String extension) { + this.extension = extension; + } + + public void setResourcePath(final String resourcePath) { + this.resourcePath = resourcePath; + } + + public void setSelectorString(final String selectorString) { + this.selectorString = selectorString; + } + + public void setSuffix(final String suffix) { + this.suffix = suffix; + } + + // --- unsupported operations --- + @Override + public Resource getSuffixResource() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockServletContext.java b/src/main/java/org/apache/sling/servlethelpers/MockServletContext.java new file mode 100644 index 0000000..4741738 --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockServletContext.java @@ -0,0 +1,304 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.EventListener; +import java.util.Map; +import java.util.Set; + +import javax.servlet.Filter; +import javax.servlet.FilterRegistration; +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; +import javax.servlet.ServletRegistration.Dynamic; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspConfigDescriptor; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Mock {@link ServletContext} implementation. + */ +@ConsumerType +public class MockServletContext implements ServletContext { + + @Override + public String getMimeType(final String file) { + return "application/octet-stream"; + } + + // --- unsupported operations --- + @Override + public Object getAttribute(final String name) { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<String> getAttributeNames() { + throw new UnsupportedOperationException(); + } + + @Override + public ServletContext getContext(final String uriPath) { + throw new UnsupportedOperationException(); + } + + @Override + public String getContextPath() { + throw new UnsupportedOperationException(); + } + + @Override + public String getInitParameter(final String name) { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<String> getInitParameterNames() { + throw new UnsupportedOperationException(); + } + + @Override + public int getMajorVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public int getMinorVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public RequestDispatcher getNamedDispatcher(final String name) { + throw new UnsupportedOperationException(); + } + + @Override + public String getRealPath(final String pPath) { + throw new UnsupportedOperationException(); + } + + @Override + public RequestDispatcher getRequestDispatcher(final String path) { + throw new UnsupportedOperationException(); + } + + @Override + public URL getResource(final String pPath) { + throw new UnsupportedOperationException(); + } + + @Override + public InputStream getResourceAsStream(final String path) { + throw new UnsupportedOperationException(); + } + + @Override + public Set<String> getResourcePaths(final String path) { + throw new UnsupportedOperationException(); + } + + @Override + public String getServerInfo() { + throw new UnsupportedOperationException(); + } + + @Override + public Servlet getServlet(final String name) { + throw new UnsupportedOperationException(); + } + + @Override + public String getServletContextName() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<String> getServletNames() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<Servlet> getServlets() { + throw new UnsupportedOperationException(); + } + + @Override + public void log(final String msg) { + throw new UnsupportedOperationException(); + } + + @Override + public void log(final Exception exception, final String msg) { + throw new UnsupportedOperationException(); + } + + @Override + public void log(final String msg, final Throwable throwable) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeAttribute(final String name) { + throw new UnsupportedOperationException(); + } + + @Override + public void setAttribute(final String name, final Object object) { + throw new UnsupportedOperationException(); + } + + @Override + public int getEffectiveMajorVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public int getEffectiveMinorVersion() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setInitParameter(final String name, final String value) { + throw new UnsupportedOperationException(); + } + + @Override + public Dynamic addServlet(final String servletName, final String className) { + throw new UnsupportedOperationException(); + } + + @Override + public Dynamic addServlet(final String servletName, final Servlet servlet) { + throw new UnsupportedOperationException(); + } + + @Override + public Dynamic addServlet(final String servletName, final Class<? extends Servlet> servletClass) { + throw new UnsupportedOperationException(); + } + + @Override + public <T extends Servlet> T createServlet(final Class<T> clazz) throws ServletException { + throw new UnsupportedOperationException(); + } + + @Override + public ServletRegistration getServletRegistration(final String servletName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map<String, ? extends ServletRegistration> getServletRegistrations() { + throw new UnsupportedOperationException(); + } + + @Override + public FilterRegistration.Dynamic addFilter(final String filterName, final String className) { + throw new UnsupportedOperationException(); + } + + @Override + public FilterRegistration.Dynamic addFilter(final String filterName, final Filter filter) { + throw new UnsupportedOperationException(); + } + + @Override + public FilterRegistration.Dynamic addFilter(final String filterName, final Class<? extends Filter> filterClass) { + throw new UnsupportedOperationException(); + } + + @Override + public <T extends Filter> T createFilter(final Class<T> clazz) throws ServletException { + throw new UnsupportedOperationException(); + } + + @Override + public FilterRegistration getFilterRegistration(final String filterName) { + throw new UnsupportedOperationException(); + } + + @Override + public Map<String, ? extends FilterRegistration> getFilterRegistrations() { + throw new UnsupportedOperationException(); + } + + @Override + public SessionCookieConfig getSessionCookieConfig() { + throw new UnsupportedOperationException(); + } + + @Override + public void setSessionTrackingModes(final Set<SessionTrackingMode> sessionTrackingModes) { + throw new UnsupportedOperationException(); + } + + @Override + public Set<SessionTrackingMode> getDefaultSessionTrackingModes() { + throw new UnsupportedOperationException(); + } + + @Override + public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() { + throw new UnsupportedOperationException(); + } + + @Override + public void addListener(final String pClassName) { + throw new UnsupportedOperationException(); + } + + @Override + public <T extends EventListener> void addListener(final T listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void addListener(final Class<? extends EventListener> listenerClass) { + throw new UnsupportedOperationException(); + } + + @Override + public <T extends EventListener> T createListener(final Class<T> clazz) { + throw new UnsupportedOperationException(); + } + + @Override + public JspConfigDescriptor getJspConfigDescriptor() { + throw new UnsupportedOperationException(); + } + + @Override + public ClassLoader getClassLoader() { + throw new UnsupportedOperationException(); + } + + @Override + public void declareRoles(final String... roleNames) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequest.java b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequest.java new file mode 100644 index 0000000..88404fd --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequest.java @@ -0,0 +1,805 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import static org.apache.sling.servlethelpers.MockSlingHttpServletResponse.CHARSET_SEPARATOR; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListResourceBundle; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.Part; + +import org.apache.commons.collections.IteratorUtils; +import org.apache.commons.lang3.CharEncoding; +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletRequest; +import org.apache.sling.api.adapter.SlingAdaptable; +import org.apache.sling.api.request.RequestDispatcherOptions; +import org.apache.sling.api.request.RequestParameter; +import org.apache.sling.api.request.RequestParameterMap; +import org.apache.sling.api.request.RequestPathInfo; +import org.apache.sling.api.request.RequestProgressTracker; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.servlets.HttpConstants; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Mock {@link SlingHttpServletRequest} implementation. + */ +@ConsumerType +public class MockSlingHttpServletRequest extends SlingAdaptable implements SlingHttpServletRequest { + + private final ResourceResolver resourceResolver; + private final RequestPathInfo requestPathInfo; + private Map<String, Object> attributeMap = new HashMap<String, Object>(); + private Map<String, String[]> parameterMap = new LinkedHashMap<String, String[]>(); + private HttpSession session; + private Resource resource; + private String contextPath; + private String queryString; + private String scheme = "http"; + private String serverName = "localhost"; + private int serverPort = 80; + private String method = HttpConstants.METHOD_GET; + private final HeaderSupport headerSupport = new HeaderSupport(); + private final CookieSupport cookieSupport = new CookieSupport(); + private String contentType; + private String characterEncoding; + private byte[] content; + private String remoteUser; + private String remoteAddr; + private String remoteHost; + private int remotePort; + + private MockRequestDispatcherFactory requestDispatcherFactory; + + protected static final ResourceBundle EMPTY_RESOURCE_BUNDLE = new ListResourceBundle() { + @Override + protected Object[][] getContents() { + return new Object[0][0]; + } + }; + + /** + * @param resourceResolver Resource resolver + */ + public MockSlingHttpServletRequest(ResourceResolver resourceResolver) { + this.resourceResolver = resourceResolver; + this.requestPathInfo = newMockRequestPathInfo(); + } + + protected MockHttpSession newMockHttpSession() { + return new MockHttpSession(); + } + + protected MockRequestPathInfo newMockRequestPathInfo() { + return new MockRequestPathInfo(); + } + + @Override + public ResourceResolver getResourceResolver() { + return this.resourceResolver; + } + + @Override + public HttpSession getSession() { + return getSession(true); + } + + @Override + public HttpSession getSession(boolean create) { + if (this.session == null && create) { + this.session = newMockHttpSession(); + } + return this.session; + } + + @Override + public RequestPathInfo getRequestPathInfo() { + return this.requestPathInfo; + } + + @Override + public Object getAttribute(String name) { + return this.attributeMap.get(name); + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration<String> getAttributeNames() { + return IteratorUtils.asEnumeration(this.attributeMap.keySet().iterator()); + } + + @Override + public void removeAttribute(String name) { + this.attributeMap.remove(name); + } + + @Override + public void setAttribute(String name, Object object) { + this.attributeMap.put(name, object); + } + + @Override + public Resource getResource() { + return this.resource; + } + + public void setResource(Resource resource) { + this.resource = resource; + } + + @Override + public String getParameter(String name) { + Object object = this.parameterMap.get(name); + if (object instanceof String) { + return (String) object; + } else if (object instanceof String[]) { + String[] values = (String[]) object; + if (values.length > 0) { + return values[0]; + } + } + return null; + } + + @Override + public Map<String, String[]> getParameterMap() { + return this.parameterMap; + } + + @SuppressWarnings("unchecked") + @Override + public Enumeration<String> getParameterNames() { + return IteratorUtils.asEnumeration(this.parameterMap.keySet().iterator()); + } + + @Override + public String[] getParameterValues(String name) { // NOPMD + Object object = this.parameterMap.get(name); + if (object instanceof String) { + return new String[] { (String) object }; + } else if (object instanceof String[]) { + return (String[]) object; + } + return null; // NOPMD + } + + /** + * @param parameterMap Map of parameters + */ + public void setParameterMap(Map<String, Object> parameterMap) { + this.parameterMap.clear(); + for (Map.Entry<String, Object> entry : parameterMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof String[]) { + this.parameterMap.put(key, (String[]) value); + } else if (value != null) { + this.parameterMap.put(key, new String[] { value.toString() }); + } else { + this.parameterMap.put(key, null); + } + } + try { + this.queryString = formatQueryString(this.parameterMap); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } + } + + private String formatQueryString(Map<String, String[]> map) throws UnsupportedEncodingException { + StringBuilder querystring = new StringBuilder(); + for (Map.Entry<String, String[]> entry : this.parameterMap.entrySet()) { + if (entry.getValue() != null) { + for (String value : entry.getValue()) { + if (querystring.length() != 0) { + querystring.append('&'); + } + querystring.append(URLEncoder.encode(entry.getKey(), CharEncoding.UTF_8)); + querystring.append('='); + if (value != null) { + querystring.append(URLEncoder.encode(value, CharEncoding.UTF_8)); + } + } + } + } + if (querystring.length() > 0) { + return querystring.toString(); + } else { + return null; + } + } + + @Override + public Locale getLocale() { + return Locale.US; + } + + @Override + public String getContextPath() { + return this.contextPath; + } + + /** + * @param contextPath Webapp context path + */ + public void setContextPath(String contextPath) { + this.contextPath = contextPath; + } + + /** + * @param queryString Query string (with proper URL encoding) + */ + public void setQueryString(String queryString) { + this.queryString = queryString; + try { + parseQueryString(this.parameterMap, this.queryString); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException(ex); + } + } + + private void parseQueryString(Map<String, String[]> map, String query) throws UnsupportedEncodingException { + Map<String, List<String>> queryPairs = new LinkedHashMap<String, List<String>>(); + String[] pairs = query.split("&"); + for (String pair : pairs) { + int idx = pair.indexOf('='); + String key = idx > 0 ? URLDecoder.decode(pair.substring(0, idx), CharEncoding.UTF_8) : pair; + if (!queryPairs.containsKey(key)) { + queryPairs.put(key, new ArrayList<String>()); + } + String value = idx > 0 && pair.length() > idx + 1 ? URLDecoder.decode(pair.substring(idx + 1), + CharEncoding.UTF_8) : null; + queryPairs.get(key).add(value); + } + map.clear(); + for (Map.Entry<String, List<String>> entry : queryPairs.entrySet()) { + map.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()])); + } + } + + @Override + public String getQueryString() { + return this.queryString; + } + + @Override + public String getScheme() { + return this.scheme; + } + + public void setScheme(String scheme) { + this.scheme = scheme; + } + + @Override + public String getServerName() { + return this.serverName; + } + + public void setServerName(String serverName) { + this.serverName = serverName; + } + + @Override + public int getServerPort() { + return this.serverPort; + } + + public void setServerPort(int serverPort) { + this.serverPort = serverPort; + } + + @Override + public boolean isSecure() { + return StringUtils.equals("https", getScheme()); + } + + @Override + public String getMethod() { + return this.method; + } + + public void setMethod(String method) { + this.method = method; + } + + @Override + public long getDateHeader(String name) { + return headerSupport.getDateHeader(name); + } + + @Override + public String getHeader(String name) { + return headerSupport.getHeader(name); + } + + @Override + public Enumeration<String> getHeaderNames() { + return HeaderSupport.toEnumeration(headerSupport.getHeaderNames()); + } + + @Override + public Enumeration<String> getHeaders(String name) { + return HeaderSupport.toEnumeration(headerSupport.getHeaders(name)); + } + + @Override + public int getIntHeader(String name) { + return headerSupport.getIntHeader(name); + } + + /** + * Add header, keep existing ones with same name. + * @param name Header name + * @param value Header value + */ + public void addHeader(String name, String value) { + headerSupport.addHeader(name, value); + } + + /** + * Add header, keep existing ones with same name. + * @param name Header name + * @param value Header value + */ + public void addIntHeader(String name, int value) { + headerSupport.addIntHeader(name, value); + } + + /** + * Add header, keep existing ones with same name. + * @param name Header name + * @param date Header value + */ + public void addDateHeader(String name, long date) { + headerSupport.addDateHeader(name, date); + } + + /** + * Set header, overwrite existing ones with same name. + * @param name Header name + * @param value Header value + */ + public void setHeader(String name, String value) { + headerSupport.setHeader(name, value); + } + + /** + * Set header, overwrite existing ones with same name. + * @param name Header name + * @param value Header value + */ + public void setIntHeader(String name, int value) { + headerSupport.setIntHeader(name, value); + } + + /** + * Set header, overwrite existing ones with same name. + * @param name Header name + * @param date Header value + */ + public void setDateHeader(String name, long date) { + headerSupport.setDateHeader(name, date); + } + + @Override + public Cookie getCookie(String name) { + return cookieSupport.getCookie(name); + } + + @Override + public Cookie[] getCookies() { + return cookieSupport.getCookies(); + } + + /** + * Set cookie + * @param cookie Cookie + */ + public void addCookie(Cookie cookie) { + cookieSupport.addCookie(cookie); + } + + @Override + public ResourceBundle getResourceBundle(Locale locale) { + return getResourceBundle(null, locale); + } + + @Override + public ResourceBundle getResourceBundle(String baseName, Locale locale) { + return EMPTY_RESOURCE_BUNDLE; + } + + @Override + public RequestParameter getRequestParameter(String name) { + String value = getParameter(name); + if (value != null) { + return new MockRequestParameter(name, value); + } + return null; + } + + @Override + public RequestParameterMap getRequestParameterMap() { + MockRequestParameterMap map = new MockRequestParameterMap(); + for (Map.Entry<String,String[]> entry : getParameterMap().entrySet()) { + map.put(entry.getKey(), getRequestParameters(entry.getKey())); + } + return map; + } + + @Override + public RequestParameter[] getRequestParameters(String name) { + String[] values = getParameterValues(name); + if (values == null) { + return null; + } + RequestParameter[] requestParameters = new RequestParameter[values.length]; + for (int i = 0; i < values.length; i++) { + requestParameters[i] = new MockRequestParameter(name, values[i]); + } + return requestParameters; + } + + // part of Sling API 2.7 + public List<RequestParameter> getRequestParameterList() { + List<RequestParameter> params = new ArrayList<RequestParameter>(); + for (RequestParameter[] requestParameters : getRequestParameterMap().values()) { + params.addAll(Arrays.asList(requestParameters)); + } + return params; + } + + @Override + public String getCharacterEncoding() { + return this.characterEncoding; + } + + @Override + public void setCharacterEncoding(String charset) { + this.characterEncoding = charset; + } + + @Override + public String getContentType() { + if (this.contentType == null) { + return null; + } else { + return this.contentType + + (StringUtils.isNotBlank(characterEncoding) ? CHARSET_SEPARATOR + characterEncoding : ""); + } + } + + public void setContentType(String type) { + this.contentType = type; + if (StringUtils.contains(this.contentType, CHARSET_SEPARATOR)) { + this.characterEncoding = StringUtils.substringAfter(this.contentType, CHARSET_SEPARATOR); + this.contentType = StringUtils.substringBefore(this.contentType, CHARSET_SEPARATOR); + } + } + + @Override + public ServletInputStream getInputStream() { + if (content == null) { + return null; + } + return new ServletInputStream() { + private final InputStream is = new ByteArrayInputStream(content); + @Override + public int read() throws IOException { + return is.read(); + } + }; + } + + @Override + public int getContentLength() { + if (content == null) { + return 0; + } + return content.length; + } + + public void setContent(byte[] content) { + this.content = content; + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + if (requestDispatcherFactory == null) { + throw new IllegalStateException("Please provdide a MockRequestDispatcherFactory (setRequestDispatcherFactory)."); + } + return requestDispatcherFactory.getRequestDispatcher(path, null); + } + + @Override + public RequestDispatcher getRequestDispatcher(String path, RequestDispatcherOptions options) { + if (requestDispatcherFactory == null) { + throw new IllegalStateException("Please provdide a MockRequestDispatcherFactory (setRequestDispatcherFactory)."); + } + return requestDispatcherFactory.getRequestDispatcher(path, options); + } + + @Override + public RequestDispatcher getRequestDispatcher(Resource resource) { + if (requestDispatcherFactory == null) { + throw new IllegalStateException("Please provdide a MockRequestDispatcherFactory (setRequestDispatcherFactory)."); + } + return requestDispatcherFactory.getRequestDispatcher(resource, null); + } + + @Override + public RequestDispatcher getRequestDispatcher(Resource resource, RequestDispatcherOptions options) { + if (requestDispatcherFactory == null) { + throw new IllegalStateException("Please provdide a MockRequestDispatcherFactory (setRequestDispatcherFactory)."); + } + return requestDispatcherFactory.getRequestDispatcher(resource, options); + } + + public void setRequestDispatcherFactory(MockRequestDispatcherFactory requestDispatcherFactory) { + this.requestDispatcherFactory = requestDispatcherFactory; + } + + @Override + public String getRemoteUser() { + return remoteUser; + } + + public void setRemoteUser(String remoteUser) { + this.remoteUser = remoteUser; + } + + @Override + public String getRemoteAddr() { + return remoteAddr; + } + + public void setRemoteAddr(String remoteAddr) { + this.remoteAddr = remoteAddr; + } + + @Override + public String getRemoteHost() { + return remoteHost; + } + + public void setRemoteHost(String remoteHost) { + this.remoteHost = remoteHost; + } + + @Override + public int getRemotePort() { + return remotePort; + } + + public void setRemotePort(int remotePort) { + this.remotePort = remotePort; + } + + + // --- unsupported operations --- + + @Override + public RequestProgressTracker getRequestProgressTracker() { + throw new UnsupportedOperationException(); + } + + @Override + public String getResponseContentType() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<String> getResponseContentTypes() { + throw new UnsupportedOperationException(); + } + + @Override + public String getAuthType() { + throw new UnsupportedOperationException(); + } + + @Override + public String getPathInfo() { + throw new UnsupportedOperationException(); + } + + @Override + public String getPathTranslated() { + throw new UnsupportedOperationException(); + } + + @Override + public String getRequestURI() { + throw new UnsupportedOperationException(); + } + + @Override + public StringBuffer getRequestURL() { + throw new UnsupportedOperationException(); + } + + @Override + public String getRequestedSessionId() { + throw new UnsupportedOperationException(); + } + + @Override + public String getServletPath() { + throw new UnsupportedOperationException(); + } + + @Override + public Principal getUserPrincipal() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isRequestedSessionIdFromURL() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isRequestedSessionIdValid() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isUserInRole(String role) { + throw new UnsupportedOperationException(); + } + + @Override + public String getLocalAddr() { + throw new UnsupportedOperationException(); + } + + @Override + public String getLocalName() { + throw new UnsupportedOperationException(); + } + + @Override + public int getLocalPort() { + throw new UnsupportedOperationException(); + } + + @Override + public Enumeration<Locale> getLocales() { + throw new UnsupportedOperationException(); + } + + @Override + public String getProtocol() { + throw new UnsupportedOperationException(); + } + + @Override + public BufferedReader getReader() { + throw new UnsupportedOperationException(); + } + + @Override + public String getRealPath(String path) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean authenticate(HttpServletResponse response) { + throw new UnsupportedOperationException(); + } + + @Override + public void login(String pUsername, String password) { + throw new UnsupportedOperationException(); + } + + @Override + public void logout() throws ServletException { + throw new UnsupportedOperationException(); + } + + @Override + public Collection<Part> getParts() { + throw new UnsupportedOperationException(); + } + + @Override + public Part getPart(String name) { + throw new UnsupportedOperationException(); + } + + @Override + public ServletContext getServletContext() { + throw new UnsupportedOperationException(); + } + + @Override + public AsyncContext startAsync() { + throw new UnsupportedOperationException(); + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAsyncStarted() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isAsyncSupported() { + throw new UnsupportedOperationException(); + } + + @Override + public AsyncContext getAsyncContext() { + throw new UnsupportedOperationException(); + } + + @Override + public DispatcherType getDispatcherType() { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java new file mode 100644 index 0000000..6acfb7c --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponse.java @@ -0,0 +1,282 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.io.PrintWriter; +import java.util.Collection; +import java.util.Locale; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.apache.sling.api.SlingHttpServletResponse; +import org.apache.sling.api.adapter.SlingAdaptable; + +import aQute.bnd.annotation.ConsumerType; + +/** + * Mock {@link SlingHttpServletResponse} implementation. + */ +@ConsumerType +public class MockSlingHttpServletResponse extends SlingAdaptable implements SlingHttpServletResponse { + + static final String CHARSET_SEPARATOR = ";charset="; + + private String contentType; + private String characterEncoding; + private int contentLength; + private int status = HttpServletResponse.SC_OK; + private int bufferSize = 1024 * 8; + private boolean isCommitted; + private final HeaderSupport headerSupport = new HeaderSupport(); + private final ResponseBodySupport bodySupport = new ResponseBodySupport(); + private final CookieSupport cookieSupport = new CookieSupport(); + + @Override + public String getContentType() { + if (this.contentType == null) { + return null; + } else { + return this.contentType + + (StringUtils.isNotBlank(characterEncoding) ? CHARSET_SEPARATOR + characterEncoding : ""); + } + } + + @Override + public void setContentType(String type) { + this.contentType = type; + if (StringUtils.contains(this.contentType, CHARSET_SEPARATOR)) { + this.characterEncoding = StringUtils.substringAfter(this.contentType, CHARSET_SEPARATOR); + this.contentType = StringUtils.substringBefore(this.contentType, CHARSET_SEPARATOR); + } + } + + @Override + public void setCharacterEncoding(String charset) { + this.characterEncoding = charset; + } + + @Override + public String getCharacterEncoding() { + return this.characterEncoding; + } + + @Override + public void setContentLength(int len) { + this.contentLength = len; + } + + public int getContentLength() { + return this.contentLength; + } + + @Override + public void setStatus(int sc, String sm) { + setStatus(sc); + } + + @Override + public void setStatus(int sc) { + this.status = sc; + } + + @Override + public int getStatus() { + return this.status; + } + + @Override + public void sendError(int sc, String msg) { + setStatus(sc); + } + + @Override + public void sendError(int sc) { + setStatus(sc); + } + + @Override + public void sendRedirect(String location) { + setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); + setHeader("Location", location); + } + + @Override + public void addHeader(String name, String value) { + headerSupport.addHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + headerSupport.addIntHeader(name, value); + } + + @Override + public void addDateHeader(String name, long date) { + headerSupport.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + headerSupport.setHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + headerSupport.setIntHeader(name, value); + } + + @Override + public void setDateHeader(String name, long date) { + headerSupport.setDateHeader(name, date); + } + + @Override + public boolean containsHeader(String name) { + return headerSupport.containsHeader(name); + } + + @Override + public String getHeader(String name) { + return headerSupport.getHeader(name); + } + + @Override + public Collection<String> getHeaders(String name) { + return headerSupport.getHeaders(name); + } + + @Override + public Collection<String> getHeaderNames() { + return headerSupport.getHeaderNames(); + } + + @Override + public PrintWriter getWriter() { + return bodySupport.getWriter(getCharacterEncoding()); + } + + @Override + public ServletOutputStream getOutputStream() { + return bodySupport.getOutputStream(); + } + + @Override + public void reset() { + if (isCommitted()) { + throw new IllegalStateException("Response already committed."); + } + bodySupport.reset(); + headerSupport.reset(); + cookieSupport.reset(); + status = HttpServletResponse.SC_OK; + contentLength = 0; + } + + @Override + public void resetBuffer() { + if (isCommitted()) { + throw new IllegalStateException("Response already committed."); + } + bodySupport.reset(); + } + + @Override + public int getBufferSize() { + return this.bufferSize; + } + + @Override + public void setBufferSize(int size) { + this.bufferSize = size; + } + + @Override + public void flushBuffer() { + isCommitted = true; + } + + @Override + public boolean isCommitted() { + return isCommitted; + } + + public byte[] getOutput() { + return bodySupport.getOutput(); + } + + public String getOutputAsString() { + return bodySupport.getOutputAsString(getCharacterEncoding()); + } + + @Override + public void addCookie(Cookie cookie) { + cookieSupport.addCookie(cookie); + } + + /** + * Get cookie + * @param name Cookie name + * @return Cookie or null + */ + public Cookie getCookie(String name) { + return cookieSupport.getCookie(name); + } + + /** + * Get cookies + * @return Cookies array or null if no cookie defined + */ + public Cookie[] getCookies() { + return cookieSupport.getCookies(); + } + + // --- unsupported operations --- + @Override + public Locale getLocale() { + throw new UnsupportedOperationException(); + } + + @Override + public void setLocale(Locale loc) { + throw new UnsupportedOperationException(); + } + + @Override + public String encodeRedirectUrl(String url) { + throw new UnsupportedOperationException(); + } + + @Override + public String encodeRedirectURL(String url) { + throw new UnsupportedOperationException(); + } + + @Override + public String encodeUrl(String url) { + throw new UnsupportedOperationException(); + } + + @Override + public String encodeURL(String url) { + throw new UnsupportedOperationException(); + } +} diff --git a/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java b/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java new file mode 100644 index 0000000..c19f2c2 --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/ResponseBodySupport.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; + +import javax.servlet.ServletOutputStream; + +import org.apache.commons.lang3.CharEncoding; +import org.apache.commons.lang3.StringUtils; + +/** + * Manage response body content. + */ +class ResponseBodySupport { + + private ByteArrayOutputStream outputStream; + private ServletOutputStream servletOutputStream; + private PrintWriter printWriter; + + public ResponseBodySupport() { + reset(); + } + + public void reset() { + outputStream = new ByteArrayOutputStream(); + servletOutputStream = null; + printWriter = null; + } + + public ServletOutputStream getOutputStream() { + if (servletOutputStream == null) { + servletOutputStream = new ServletOutputStream() { + @Override + public void write(int b) throws IOException { + outputStream.write(b); + } + }; + } + return servletOutputStream; + } + + public PrintWriter getWriter(String charset) { + if (printWriter == null) { + try { + printWriter = new PrintWriter(new OutputStreamWriter(getOutputStream(), defaultCharset(charset))); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException("Unsupported encoding: " + defaultCharset(charset), ex); + } + } + return printWriter; + } + + public byte[] getOutput() { + if (servletOutputStream != null) { + try { + servletOutputStream.flush(); + } catch (IOException ex) { + // ignore + } + } + return outputStream.toByteArray(); + } + + public String getOutputAsString(String charset) { + if (printWriter != null) { + printWriter.flush(); + } + try { + return new String(getOutput(), defaultCharset(charset)); + } catch (UnsupportedEncodingException ex) { + throw new RuntimeException("Unsupported encoding: " + defaultCharset(charset), ex); + } + } + + private String defaultCharset(String charset) { + return StringUtils.defaultString(charset, CharEncoding.UTF_8); + } + +} diff --git a/src/main/java/org/apache/sling/servlethelpers/package-info.java b/src/main/java/org/apache/sling/servlethelpers/package-info.java new file mode 100644 index 0000000..1497ab6 --- /dev/null +++ b/src/main/java/org/apache/sling/servlethelpers/package-info.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +/** + * Mock implementation of selected Servlet-related Sling APIs. + */ [email protected]("1.0") +package org.apache.sling.servlethelpers; diff --git a/src/test/java/org/apache/sling/servlethelpers/MockHttpSessionTest.java b/src/test/java/org/apache/sling/servlethelpers/MockHttpSessionTest.java new file mode 100644 index 0000000..980253c --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/MockHttpSessionTest.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +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 org.apache.sling.servlethelpers.MockHttpSession; +import org.junit.Before; +import org.junit.Test; + +public class MockHttpSessionTest { + + private MockHttpSession httpSession; + + @Before + public void setUp() throws Exception { + httpSession = new MockHttpSession(); + } + + @Test + public void testServletContext() { + assertNotNull(httpSession.getServletContext()); + } + + @Test + public void testId() { + assertNotNull(httpSession.getId()); + } + + @Test + public void testCreationTime() { + assertNotNull(httpSession.getCreationTime()); + } + + @Test + public void testAttributes() { + httpSession.setAttribute("attr1", "value1"); + assertTrue(httpSession.getAttributeNames().hasMoreElements()); + assertEquals("value1", httpSession.getAttribute("attr1")); + httpSession.removeAttribute("attr1"); + assertFalse(httpSession.getAttributeNames().hasMoreElements()); + } + + @Test + public void testValues() { + httpSession.putValue("attr1", "value1"); + assertEquals(1, httpSession.getValueNames().length); + assertEquals("value1", httpSession.getValue("attr1")); + httpSession.removeValue("attr1"); + assertEquals(0, httpSession.getValueNames().length); + } + + @Test + public void testInvalidate() { + httpSession.invalidate(); + assertTrue(httpSession.isInvalidated()); + } + + @Test(expected = IllegalStateException.class) + public void testInvalidateStateCheck() { + httpSession.invalidate(); + httpSession.getAttribute("attr1"); + } + + @Test + public void testIsNew() { + assertTrue(httpSession.isNew()); + httpSession.setNew(false); + assertFalse(httpSession.isNew()); + } + + @Test + public void testGetLastAccessedTime() { + assertNotNull(httpSession.getLastAccessedTime()); + } + + @Test + public void testGetMaxInactiveInterval() { + assertTrue(httpSession.getMaxInactiveInterval() > 0); + httpSession.setMaxInactiveInterval(123); + assertEquals(123, httpSession.getMaxInactiveInterval()); + } + +} diff --git a/src/test/java/org/apache/sling/servlethelpers/MockRequestPathInfoTest.java b/src/test/java/org/apache/sling/servlethelpers/MockRequestPathInfoTest.java new file mode 100644 index 0000000..f94c380 --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/MockRequestPathInfoTest.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.apache.sling.servlethelpers.MockRequestPathInfo; +import org.junit.Before; +import org.junit.Test; + +public class MockRequestPathInfoTest { + + private MockRequestPathInfo requestPathInfo; + + @Before + public void setUp() throws Exception { + this.requestPathInfo = new MockRequestPathInfo(); + } + + @Test + public void testExtension() { + assertNull(this.requestPathInfo.getExtension()); + this.requestPathInfo.setExtension("ext"); + assertEquals("ext", this.requestPathInfo.getExtension()); + } + + @Test + public void testResourcePath() { + assertNull(this.requestPathInfo.getResourcePath()); + this.requestPathInfo.setResourcePath("/path"); + assertEquals("/path", this.requestPathInfo.getResourcePath()); + } + + @Test + public void testSelector() { + assertNull(this.requestPathInfo.getSelectorString()); + assertEquals(0, this.requestPathInfo.getSelectors().length); + this.requestPathInfo.setSelectorString("aa.bb"); + assertEquals("aa.bb", this.requestPathInfo.getSelectorString()); + assertEquals(2, this.requestPathInfo.getSelectors().length); + assertArrayEquals(new String[] { "aa", "bb" }, this.requestPathInfo.getSelectors()); + } + + @Test + public void testSuffix() { + assertNull(this.requestPathInfo.getSuffix()); + this.requestPathInfo.setSuffix("/suffix"); + assertEquals("/suffix", this.requestPathInfo.getSuffix()); + } + +} diff --git a/src/test/java/org/apache/sling/servlethelpers/MockServletContextTest.java b/src/test/java/org/apache/sling/servlethelpers/MockServletContextTest.java new file mode 100644 index 0000000..131b531 --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/MockServletContextTest.java @@ -0,0 +1,43 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import static org.junit.Assert.assertEquals; + +import javax.servlet.ServletContext; + +import org.apache.sling.servlethelpers.MockServletContext; +import org.junit.Before; +import org.junit.Test; + +public class MockServletContextTest { + + private ServletContext servletContext; + + @Before + public void setUp() throws Exception { + this.servletContext = new MockServletContext(); + } + + @Test + public void testGetMimeType() { + assertEquals("application/octet-stream", this.servletContext.getMimeType("any")); + } + +} diff --git a/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequestTest.java b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequestTest.java new file mode 100644 index 0000000..28d6b50 --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletRequestTest.java @@ -0,0 +1,328 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +import javax.servlet.RequestDispatcher; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpSession; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.CharEncoding; +import org.apache.sling.api.request.RequestDispatcherOptions; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.servlets.HttpConstants; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class MockSlingHttpServletRequestTest { + + @Mock + private ResourceResolver resourceResolver; + @Mock + private Resource resource; + + private MockSlingHttpServletRequest request; + + @Before + public void setUp() throws Exception { + request = new MockSlingHttpServletRequest(resourceResolver); + } + + @Test + public void testResourceResolver() { + assertSame(resourceResolver, request.getResourceResolver()); + } + + @Test + public void testDefaultResourceResolver() { + assertNotNull(request.getResourceResolver()); + } + + @Test + public void testSession() { + HttpSession session = request.getSession(false); + assertNull(session); + session = request.getSession(); + assertNotNull(session); + } + + @Test + public void testRequestPathInfo() { + assertNotNull(request.getRequestPathInfo()); + } + + @Test + public void testAttributes() { + request.setAttribute("attr1", "value1"); + assertTrue(request.getAttributeNames().hasMoreElements()); + assertEquals("value1", request.getAttribute("attr1")); + request.removeAttribute("attr1"); + assertFalse(request.getAttributeNames().hasMoreElements()); + } + + @Test + public void testResource() { + assertNull(request.getResource()); + request.setResource(resource); + assertSame(resource, request.getResource()); + } + + @Test + public void testContextPath() { + assertNull(request.getContextPath()); + request.setContextPath("/ctx"); + assertEquals("/ctx", request.getContextPath()); + } + + @Test + public void testLocale() { + assertEquals(Locale.US, request.getLocale()); + } + + @Test + public void testQueryString() throws UnsupportedEncodingException { + assertNull(request.getQueryString()); + assertEquals(0, request.getParameterMap().size()); + assertFalse(request.getParameterNames().hasMoreElements()); + + request.setQueryString("param1=123¶m2=" + URLEncoder.encode("äöü߀!:!", CharEncoding.UTF_8) + + "¶m3=a¶m3=b"); + + assertNotNull(request.getQueryString()); + assertEquals(3, request.getParameterMap().size()); + assertTrue(request.getParameterNames().hasMoreElements()); + assertEquals("123", request.getParameter("param1")); + assertEquals("äöü߀!:!", request.getParameter("param2")); + assertArrayEquals(new String[] { "a", "b" }, request.getParameterValues("param3")); + + Map<String, Object> paramMap = new LinkedHashMap<String, Object>(); + paramMap.put("p1", "a"); + paramMap.put("p2", new String[] { "b", "c" }); + paramMap.put("p3", null); + paramMap.put("p4", new String[] { null }); + paramMap.put("p5", 22); + request.setParameterMap(paramMap); + + assertEquals("p1=a&p2=b&p2=c&p4=&p5=22", request.getQueryString()); + } + + @Test + public void testSchemeSecure() { + assertEquals("http", request.getScheme()); + assertFalse(request.isSecure()); + + request.setScheme("https"); + assertEquals("https", request.getScheme()); + assertTrue(request.isSecure()); + } + + @Test + public void testServerNamePort() { + assertEquals("localhost", request.getServerName()); + assertEquals(80, request.getServerPort()); + + request.setServerName("myhost"); + request.setServerPort(12345); + assertEquals("myhost", request.getServerName()); + assertEquals(12345, request.getServerPort()); + } + + @Test + public void testMethod() { + assertEquals(HttpConstants.METHOD_GET, request.getMethod()); + + request.setMethod(HttpConstants.METHOD_POST); + assertEquals(HttpConstants.METHOD_POST, request.getMethod()); + } + + @Test + public void testHeaders() { + assertFalse(request.getHeaderNames().hasMoreElements()); + + Calendar calendar = Calendar.getInstance(); + calendar.set(Calendar.MILLISECOND, 0); + long dateValue = calendar.getTimeInMillis(); + + request.addHeader("header1", "value1"); + request.addIntHeader("header2", 5); + request.addDateHeader("header3", dateValue); + + assertEquals("value1", request.getHeader("header1")); + assertEquals(5, request.getIntHeader("header2")); + assertEquals(dateValue, request.getDateHeader("header3")); + + request.setHeader("header1", "value2"); + request.addIntHeader("header2", 10); + + Enumeration<String> header1Values = request.getHeaders("header1"); + assertEquals("value2", header1Values.nextElement()); + assertFalse(header1Values.hasMoreElements()); + + Enumeration<String> header2Values = request.getHeaders("header2"); + assertEquals("5", header2Values.nextElement()); + assertEquals("10", header2Values.nextElement()); + assertFalse(header2Values.hasMoreElements()); + } + + @Test + public void testCookies() { + assertNull(request.getCookies()); + + request.addCookie(new Cookie("cookie1", "value1")); + request.addCookie(new Cookie("cookie2", "value2")); + + assertEquals("value1", request.getCookie("cookie1").getValue()); + + Cookie[] cookies = request.getCookies(); + assertEquals(2, cookies.length); + assertEquals("value1", cookies[0].getValue()); + assertEquals("value2", cookies[1].getValue()); + } + + @Test + public void testDefaultResourceBundle() { + ResourceBundle bundle = request.getResourceBundle(Locale.US); + assertNotNull(bundle); + assertFalse(bundle.getKeys().hasMoreElements()); + } + + @Test + public void testRequestParameter() throws Exception { + request.setQueryString("param1=123¶m2=" + URLEncoder.encode("äöü߀!:!", CharEncoding.UTF_8) + + "¶m3=a¶m3=b"); + + assertEquals(3, request.getRequestParameterMap().size()); + assertEquals(4, request.getRequestParameterList().size()); + assertEquals("123", request.getRequestParameter("param1").getString()); + assertEquals("äöü߀!:!", request.getRequestParameter("param2").getString()); + assertEquals("a",request.getRequestParameters("param3")[0].getString()); + assertEquals("b",request.getRequestParameters("param3")[1].getString()); + + assertNull(request.getRequestParameter("unknown")); + assertNull(request.getRequestParameters("unknown")); + } + + @Test + public void testContentTypeCharset() throws Exception { + assertNull(request.getContentType()); + assertNull(request.getCharacterEncoding()); + + request.setContentType("image/gif"); + assertEquals("image/gif", request.getContentType()); + assertNull(request.getCharacterEncoding()); + + request.setContentType("text/plain;charset=UTF-8"); + assertEquals("text/plain;charset=UTF-8", request.getContentType()); + assertEquals(CharEncoding.UTF_8, request.getCharacterEncoding()); + + request.setCharacterEncoding(CharEncoding.ISO_8859_1); + assertEquals("text/plain;charset=ISO-8859-1", request.getContentType()); + assertEquals(CharEncoding.ISO_8859_1, request.getCharacterEncoding()); + } + + @Test + public void testContent() throws Exception { + assertEquals(0, request.getContentLength()); + assertNull(request.getInputStream()); + + byte[] data = new byte[] { 0x01,0x02,0x03 }; + request.setContent(data); + + assertEquals(data.length, request.getContentLength()); + assertArrayEquals(data, IOUtils.toByteArray(request.getInputStream())); + } + + @Test + public void testGetRequestDispatcher() { + MockRequestDispatcherFactory requestDispatcherFactory = mock(MockRequestDispatcherFactory.class); + RequestDispatcher requestDispatcher = mock(RequestDispatcher.class); + when(requestDispatcherFactory.getRequestDispatcher(any(Resource.class), any(RequestDispatcherOptions.class))).thenReturn(requestDispatcher); + when(requestDispatcherFactory.getRequestDispatcher(any(String.class), any(RequestDispatcherOptions.class))).thenReturn(requestDispatcher); + + request.setRequestDispatcherFactory(requestDispatcherFactory); + + assertSame(requestDispatcher, request.getRequestDispatcher("/path")); + assertSame(requestDispatcher, request.getRequestDispatcher("/path", new RequestDispatcherOptions())); + assertSame(requestDispatcher, request.getRequestDispatcher(resource)); + assertSame(requestDispatcher, request.getRequestDispatcher(resource, new RequestDispatcherOptions())); + } + + @Test(expected = IllegalStateException.class) + public void testGetRequestDispatcherWithoutFactory() { + request.getRequestDispatcher("/path"); + } + + @Test + public void testGetRemoteUser() { + assertNull(null, request.getRemoteUser()); + + request.setRemoteUser("admin"); + assertEquals("admin", request.getRemoteUser()); + } + + @Test + public void testGetRemoteAddr() throws Exception { + assertNull(null, request.getRemoteAddr()); + + request.setRemoteAddr("1.2.3.4"); + assertEquals("1.2.3.4", request.getRemoteAddr()); + } + + @Test + public void testGetRemoteHost() throws Exception { + assertNull(null, request.getRemoteHost()); + + request.setRemoteHost("host1"); + assertEquals("host1", request.getRemoteHost()); + } + + @Test + public void testGetRemotePort() throws Exception { + assertEquals(0, request.getRemotePort()); + + request.setRemotePort(1234); + assertEquals(1234, request.getRemotePort()); + } + +} diff --git a/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java new file mode 100644 index 0000000..54dae46 --- /dev/null +++ b/src/test/java/org/apache/sling/servlethelpers/MockSlingHttpServletResponseTest.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.sling.servlethelpers; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; +import java.util.Iterator; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.CharEncoding; +import org.apache.sling.servlethelpers.MockSlingHttpServletResponse; +import org.junit.Before; +import org.junit.Test; + +public class MockSlingHttpServletResponseTest { + + private MockSlingHttpServletResponse response; + + @Before + public void setUp() throws Exception { + this.response = new MockSlingHttpServletResponse(); + } + + @Test + public void testContentTypeCharset() throws Exception { + assertNull(response.getContentType()); + assertNull(response.getCharacterEncoding()); + + response.setContentType("image/gif"); + assertEquals("image/gif", response.getContentType()); + assertNull(response.getCharacterEncoding()); + + response.setContentType("text/plain;charset=UTF-8"); + assertEquals("text/plain;charset=UTF-8", response.getContentType()); + assertEquals(CharEncoding.UTF_8, response.getCharacterEncoding()); + + response.setCharacterEncoding(CharEncoding.ISO_8859_1); + assertEquals("text/plain;charset=ISO-8859-1", response.getContentType()); + assertEquals(CharEncoding.ISO_8859_1, response.getCharacterEncoding()); + } + + @Test + public void testContentLength() throws Exception { + assertEquals(0, response.getContentLength()); + + response.setContentLength(55); + assertEquals(55, response.getContentLength()); + } + + @Test + public void testHeaders() throws Exception { + assertEquals(0, response.getHeaderNames().size()); + + response.addHeader("header1", "value1"); + response.addIntHeader("header2", 5); + response.addDateHeader("header3", System.currentTimeMillis()); + + assertEquals(3, response.getHeaderNames().size()); + assertTrue(response.containsHeader("header1")); + assertEquals("value1", response.getHeader("header1")); + assertEquals("5", response.getHeader("header2")); + assertNotNull(response.getHeader("header3")); + + response.setHeader("header1", "value2"); + response.addIntHeader("header2", 10); + + assertEquals(3, response.getHeaderNames().size()); + + Collection<String> header1Values = response.getHeaders("header1"); + assertEquals(1, header1Values.size()); + assertEquals("value2", header1Values.iterator().next()); + + Collection<String> header2Values = response.getHeaders("header2"); + assertEquals(2, header2Values.size()); + Iterator<String> header2Iterator = header2Values.iterator(); + assertEquals("5", header2Iterator.next()); + assertEquals("10", header2Iterator.next()); + + response.reset(); + assertEquals(0, response.getHeaderNames().size()); + } + + @Test + public void testRedirect() throws Exception { + response.sendRedirect("/location.html"); + assertEquals(HttpServletResponse.SC_MOVED_TEMPORARILY, response.getStatus()); + assertEquals("/location.html", response.getHeader("Location")); + } + + @Test + public void testSendError() throws Exception { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatus()); + } + + @Test + public void testSetStatus() throws Exception { + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + + response.setStatus(HttpServletResponse.SC_BAD_GATEWAY); + assertEquals(HttpServletResponse.SC_BAD_GATEWAY, response.getStatus()); + + response.reset(); + assertEquals(HttpServletResponse.SC_OK, response.getStatus()); + } + + @Test + public void testWriteStringContent() throws Exception { + final String TEST_CONTENT = "Der Jodelkaiser äöü߀ ᚠᛇᚻ"; + response.setCharacterEncoding(CharEncoding.UTF_8); + response.getWriter().write(TEST_CONTENT); + assertEquals(TEST_CONTENT, response.getOutputAsString()); + + response.resetBuffer(); + assertEquals(0, response.getOutputAsString().length()); + } + + @Test + public void testWriteBinaryContent() throws Exception { + final byte[] TEST_DATA = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05 }; + response.getOutputStream().write(TEST_DATA); + assertArrayEquals(TEST_DATA, response.getOutput()); + + response.resetBuffer(); + assertEquals(0, response.getOutput().length); + } + + @Test + public void testIsCommitted() throws Exception { + assertFalse(response.isCommitted()); + response.flushBuffer(); + assertTrue(response.isCommitted()); + } + + @Test + public void testCookies() { + assertNull(response.getCookies()); + + response.addCookie(new Cookie("cookie1", "value1")); + response.addCookie(new Cookie("cookie2", "value2")); + + assertEquals("value1", response.getCookie("cookie1").getValue()); + + Cookie[] cookies = response.getCookies(); + assertEquals(2, cookies.length); + assertEquals("value1", cookies[0].getValue()); + assertEquals("value2", cookies[1].getValue()); + + response.reset(); + assertNull(response.getCookies()); + } + +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
