diff --git a/src/main/java/org/takes/facets/previous/RsPrevious.java b/src/main/java/org/takes/facets/previous/RsPrevious.java new file mode 100644 index 000000000..723f45d74 --- /dev/null +++ b/src/main/java/org/takes/facets/previous/RsPrevious.java @@ -0,0 +1,60 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.takes.facets.previous; + +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.takes.Response; +import org.takes.rs.RsWithCookie; +import org.takes.rs.RsWrap; + +/** + * Response decorator, with a link to previous page. + * + *

The class is immutable and thread-safe. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 1.10 + */ +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public final class RsPrevious extends RsWrap { + + /** + * Ctor. + * @param rsp Response to decorate + * @param location The location user is trying to access + */ + public RsPrevious(final Response rsp, final String location) { + super( + new RsWithCookie( + rsp, + TkPrevious.class.getName(), + location + ) + ); + } + +} diff --git a/src/main/java/org/takes/facets/previous/TkPrevious.java b/src/main/java/org/takes/facets/previous/TkPrevious.java new file mode 100644 index 000000000..1841dbaf0 --- /dev/null +++ b/src/main/java/org/takes/facets/previous/TkPrevious.java @@ -0,0 +1,81 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.takes.facets.previous; + +import java.io.IOException; +import java.util.Iterator; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; +import org.takes.rq.RqCookies; +import org.takes.rs.RsRedirect; +import org.takes.rs.RsWithCookie; + +/** + * Take that redirects to previous URL + * + *

The class is immutable and thread-safe. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 1.10 + */ +@ToString +@EqualsAndHashCode +public final class TkPrevious implements Take { + + /** + * Original take. + */ + private final Take origin; + + /** + * Ctor. + * @param take Original take + */ + public TkPrevious(final Take take) { + this.origin = take; + } + + @Override + public Response act(final Request req) throws IOException { + final Iterator cookies = new RqCookies.Base(req) + .cookie(TkPrevious.class.getName()) + .iterator(); + final Response response; + if (cookies.hasNext()) { + response = new RsWithCookie( + new RsRedirect(cookies.next()), + TkPrevious.class.getName(), + "" + ); + } else { + response = this.origin.act(req); + } + return response; + } + +} diff --git a/src/main/java/org/takes/facets/previous/package-info.java b/src/main/java/org/takes/facets/previous/package-info.java new file mode 100644 index 000000000..3f1d5ce15 --- /dev/null +++ b/src/main/java/org/takes/facets/previous/package-info.java @@ -0,0 +1,50 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * Previous. + * + *

These classes may be useful when you want to redirect your user + * to some location and remember what he/she wanted to see before. This + * is especially useful during login. When the user is trying to open + * some page, where access credentials are required, you throw + * {@link org.takes.facets.forward.RsForward} to the home page, + * with this class inside, with the original URL: + * + *

 if (not_logged_id) {
+ *   throw new RsForward(
+ *     new RsWithPrevious(
+ *       new RsFlash("You must be logged in!")
+ *     )
+ *   );
+ * }
+ * + *

Then, you decorate your application with + * {@link org.takes.facets.previous.TkPrevious} and that's it. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 0.10 + */ +package org.takes.facets.previous; diff --git a/src/main/java/org/takes/rq/RqCookies.java b/src/main/java/org/takes/rq/RqCookies.java index 70ff16d9f..84d17be6e 100644 --- a/src/main/java/org/takes/rq/RqCookies.java +++ b/src/main/java/org/takes/rq/RqCookies.java @@ -88,7 +88,7 @@ public Iterable cookie(final CharSequence key) Collections.emptyList(), new Sprintf( // @checkstyle LineLengthCheck (1 line) - "there are no Cookies by name \"%s\" among %d others: %s", + "There are no Cookies by name \"%s\" among %d others: %s", key, map.size(), map.keySet() ) ); @@ -96,7 +96,7 @@ public Iterable cookie(final CharSequence key) iter = new VerboseIterable( Collections.singleton(value), new Sprintf( - "there is always only one Cookie by name \"%s\"", + "There is always only one Cookie by name \"%s\"", key ) ); diff --git a/src/test/java/org/takes/facets/previous/RsPreviousTest.java b/src/test/java/org/takes/facets/previous/RsPreviousTest.java new file mode 100644 index 000000000..214c28670 --- /dev/null +++ b/src/test/java/org/takes/facets/previous/RsPreviousTest.java @@ -0,0 +1,57 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.takes.facets.previous; + +import java.io.IOException; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.takes.rs.RsPrint; +import org.takes.rs.RsText; + +/** + * Test case for {@link RsPrevious}. + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 0.2 + */ +public final class RsPreviousTest { + + /** + * RsPrevious can build a response. + * @throws IOException If some problem inside + */ + @Test + public void buildsResponse() throws IOException { + MatcherAssert.assertThat( + new RsPrint( + new RsPrevious(new RsText(""), "/home") + ).print(), + Matchers.containsString( + "Set-Cookie: org.takes.facets.previous.TkPrevious=/home" + ) + ); + } + +} diff --git a/src/test/java/org/takes/facets/previous/TkPreviousTest.java b/src/test/java/org/takes/facets/previous/TkPreviousTest.java new file mode 100644 index 000000000..31dd41943 --- /dev/null +++ b/src/test/java/org/takes/facets/previous/TkPreviousTest.java @@ -0,0 +1,63 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.takes.facets.previous; + +import java.io.IOException; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.takes.rq.RqFake; +import org.takes.rq.RqWithHeader; +import org.takes.rs.RsPrint; +import org.takes.tk.TkText; + +/** + * Test case for {@link TkPrevious}. + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 0.2 + */ +public final class TkPreviousTest { + + /** + * TkPrevious can redirect. + * @throws IOException If some problem inside + */ + @Test + public void redirectsOnCookie() throws IOException { + MatcherAssert.assertThat( + new RsPrint( + new TkPrevious(new TkText("")).act( + new RqWithHeader( + new RqFake(), + "Cookie", + "org.takes.facets.previous.TkPrevious=/home" + ) + ) + ).print(), + Matchers.startsWith("HTTP/1.1 303 See Other") + ); + } + +} diff --git a/src/test/java/org/takes/facets/previous/package-info.java b/src/test/java/org/takes/facets/previous/package-info.java new file mode 100644 index 000000000..03137a7ad --- /dev/null +++ b/src/test/java/org/takes/facets/previous/package-info.java @@ -0,0 +1,32 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2014-2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/** + * Previous, tests. + * + * @author Yegor Bugayenko (yegor256@gmail.com) + * @version $Id$ + * @since 0.10 + */ +package org.takes.facets.previous;