diff --git a/src/main/java/io/jare/Entrance.java b/src/main/java/io/jare/Entrance.java index de09c0f..3bafed5 100644 --- a/src/main/java/io/jare/Entrance.java +++ b/src/main/java/io/jare/Entrance.java @@ -22,6 +22,7 @@ */ package io.jare; +import io.jare.dynamo.DyBase; import io.jare.tk.TkApp; import java.io.IOException; import org.takes.http.Exit; @@ -49,7 +50,7 @@ private Entrance() { * @throws IOException If fails */ public static void main(final String... args) throws IOException { - new FtCLI(new TkApp(), args).start(Exit.NEVER); + new FtCLI(new TkApp(new DyBase()), args).start(Exit.NEVER); } } diff --git a/src/main/java/io/jare/dynamo/DyBase.java b/src/main/java/io/jare/dynamo/DyBase.java new file mode 100644 index 0000000..9378161 --- /dev/null +++ b/src/main/java/io/jare/dynamo/DyBase.java @@ -0,0 +1,99 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import com.amazonaws.services.dynamodbv2.model.Select; +import com.jcabi.dynamo.Conditions; +import com.jcabi.dynamo.QueryValve; +import com.jcabi.dynamo.Region; +import com.jcabi.dynamo.Table; +import io.jare.model.Base; +import io.jare.model.Domain; +import io.jare.model.User; +import java.util.Iterator; +import java.util.Locale; +import java.util.stream.Collectors; + +/** + * Dynamo Base. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class DyBase implements Base { + + /** + * The region to work with. + */ + private final transient Region region; + + /** + * Ctor. + */ + public DyBase() { + this(new Dynamo()); + } + + /** + * Ctor. + * @param reg Region + */ + public DyBase(final Region reg) { + this.region = reg; + } + + @Override + public User user(final String name) { + return new DyUser(this.region, name); + } + + @Override + public Iterator domain(final String name) { + return this.table() + .frame() + .through( + new QueryValve() + .withSelect(Select.ALL_ATTRIBUTES) + .withLimit(1) + .withConsistentRead(true) + ) + .where( + "domain", + Conditions.equalTo(name.toLowerCase(Locale.ENGLISH)) + ) + .stream() + .map(DyDomain::new) + .collect(Collectors.toList()) + .iterator(); + } + + /** + * Table to work with. + * @return Table + */ + private Table table() { + return this.region.table("domains"); + } + +} diff --git a/src/main/java/io/jare/dynamo/DyDomain.java b/src/main/java/io/jare/dynamo/DyDomain.java new file mode 100644 index 0000000..c5a544a --- /dev/null +++ b/src/main/java/io/jare/dynamo/DyDomain.java @@ -0,0 +1,70 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import com.jcabi.dynamo.Attributes; +import com.jcabi.dynamo.Item; +import io.jare.model.Domain; +import java.io.IOException; + +/** + * Dynamo domain. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle MultipleStringLiteralsCheck (500 lines) + */ +public final class DyDomain implements Domain { + + /** + * The item. + */ + private final transient Item item; + + /** + * Ctor. + * @param itm Item + */ + public DyDomain(final Item itm) { + this.item = itm; + } + + @Override + public String owner() throws IOException { + return this.item.get("user").getS(); + } + + @Override + public String name() throws IOException { + return this.item.get("domain").getS(); + } + + @Override + public void delete() throws IOException { + this.item.frame().table().delete( + new Attributes().with("domain", this.name()) + ); + } + +} diff --git a/src/main/java/io/jare/dynamo/DyUser.java b/src/main/java/io/jare/dynamo/DyUser.java new file mode 100644 index 0000000..2bc0e6b --- /dev/null +++ b/src/main/java/io/jare/dynamo/DyUser.java @@ -0,0 +1,118 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import com.amazonaws.services.dynamodbv2.model.Select; +import com.jcabi.aspects.Tv; +import com.jcabi.dynamo.Attributes; +import com.jcabi.dynamo.Conditions; +import com.jcabi.dynamo.QueryValve; +import com.jcabi.dynamo.Region; +import com.jcabi.dynamo.Table; +import io.jare.model.Domain; +import io.jare.model.User; +import java.io.IOException; +import java.util.Iterator; +import java.util.Locale; +import java.util.stream.Collectors; + +/** + * Dynamo user. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle MultipleStringLiteralsCheck (500 lines) + */ +public final class DyUser implements User { + + /** + * The region to work with. + */ + private final transient Region region; + + /** + * The name of him. + */ + private final transient String handle; + + /** + * Ctor. + * @param reg Region + * @param name Name of him + */ + public DyUser(final Region reg, final String name) { + this.region = reg; + this.handle = name.toLowerCase(Locale.ENGLISH); + } + + @Override + public Iterable mine() { + return this.table() + .frame() + .through( + new QueryValve() + .withSelect(Select.ALL_ATTRIBUTES) + .withLimit(Tv.HUNDRED) + .withConsistentRead(false) + .withIndexName("mine") + ) + .where("user", Conditions.equalTo(this.handle)) + .stream() + .map(DyDomain::new) + .collect(Collectors.toList()); + } + + @Override + public void add(final String name) throws IOException { + synchronized (this.region) { + final Iterator before = new DyBase(this.region) + .domain(name); + if (before.hasNext()) { + final Domain domain = before.next(); + if (!domain.owner().equals(this.handle)) { + throw new IOException( + String.format( + "domain \"%s\" is occupied by @%s", + domain.name(), domain.owner() + ) + ); + } + } + this.table().put( + new Attributes() + .with("user", this.handle) + .with("domain", name.toLowerCase(Locale.ENGLISH)) + ); + } + } + + /** + * Table to work with. + * @return Table + */ + private Table table() { + return this.region.table("domains"); + } + +} diff --git a/src/main/java/io/jare/dynamo/Dynamo.java b/src/main/java/io/jare/dynamo/Dynamo.java new file mode 100644 index 0000000..5fba694 --- /dev/null +++ b/src/main/java/io/jare/dynamo/Dynamo.java @@ -0,0 +1,84 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.jcabi.dynamo.Credentials; +import com.jcabi.dynamo.Region; +import com.jcabi.dynamo.Table; +import com.jcabi.dynamo.retry.ReRegion; +import com.jcabi.log.Logger; +import com.jcabi.manifests.Manifests; + +/** + * Dynamo. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +final class Dynamo implements Region { + + /** + * Region. + */ + private final transient Region region = Dynamo.connect(); + + @Override + public AmazonDynamoDB aws() { + return this.region.aws(); + } + + @Override + public Table table(final String name) { + return this.region.table(name); + } + + /** + * Connect. + * @return Region + */ + private static Region connect() { + final String key = Manifests.read("Jare-DynamoKey"); + final Credentials creds = new Credentials.Simple( + key, Manifests.read("Jare-DynamoSecret") + ); + final Region region; + if (key.startsWith("AAAAA")) { + final int port = Integer.parseInt( + System.getProperty("dynamo.port") + ); + region = new Region.Simple(new Credentials.Direct(creds, port)); + Logger.warn(Dynamo.class, "test DynamoDB at port #%d", port); + } else { + region = new Region.Prefixed( + new ReRegion(new Region.Simple(creds)), + "jare-" + ); + } + Logger.info(Dynamo.class, "DynamoDB connected as %s", key); + return region; + } + +} diff --git a/src/main/java/io/jare/dynamo/package-info.java b/src/main/java/io/jare/dynamo/package-info.java new file mode 100644 index 0000000..d0f41a4 --- /dev/null +++ b/src/main/java/io/jare/dynamo/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Dynamo. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare.dynamo; diff --git a/src/main/java/io/jare/fake/FkBase.java b/src/main/java/io/jare/fake/FkBase.java new file mode 100644 index 0000000..9a9291d --- /dev/null +++ b/src/main/java/io/jare/fake/FkBase.java @@ -0,0 +1,50 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.fake; + +import io.jare.model.Base; +import io.jare.model.Domain; +import io.jare.model.User; +import java.util.Collections; +import java.util.Iterator; + +/** + * Fake Base. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class FkBase implements Base { + + @Override + public User user(final String name) { + return new FkUser(); + } + + @Override + public Iterator domain(final String name) { + return Collections.singleton(new FkDomain()).iterator(); + } + +} diff --git a/src/main/java/io/jare/fake/FkDomain.java b/src/main/java/io/jare/fake/FkDomain.java new file mode 100644 index 0000000..78a121b --- /dev/null +++ b/src/main/java/io/jare/fake/FkDomain.java @@ -0,0 +1,50 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.fake; + +import io.jare.model.Domain; + +/** + * Fake domain. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class FkDomain implements Domain { + + @Override + public String owner() { + return "name:test:1"; + } + + @Override + public String name() { + return "jare.io"; + } + + @Override + public void delete() { + // nothing + } +} diff --git a/src/main/java/io/jare/fake/FkUser.java b/src/main/java/io/jare/fake/FkUser.java new file mode 100644 index 0000000..2ddd51f --- /dev/null +++ b/src/main/java/io/jare/fake/FkUser.java @@ -0,0 +1,48 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.fake; + +import io.jare.model.Domain; +import io.jare.model.User; +import java.util.Collections; + +/** + * Fake user. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class FkUser implements User { + + @Override + public Iterable mine() { + return Collections.emptyList(); + } + + @Override + public void add(final String name) { + // nothing + } + +} diff --git a/src/main/java/io/jare/fake/package-info.java b/src/main/java/io/jare/fake/package-info.java new file mode 100644 index 0000000..e91d94b --- /dev/null +++ b/src/main/java/io/jare/fake/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Fakes. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare.fake; diff --git a/src/main/java/io/jare/model/Base.java b/src/main/java/io/jare/model/Base.java new file mode 100644 index 0000000..4c30856 --- /dev/null +++ b/src/main/java/io/jare/model/Base.java @@ -0,0 +1,50 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.model; + +import java.util.Iterator; + +/** + * Base. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public interface Base { + + /** + * Get user by GitHub handle. + * @param name GitHub name of the user + * @return The user + */ + User user(String name); + + /** + * Find domain by hostname. + * @param name The name + * @return The domain + */ + Iterator domain(String name); + +} diff --git a/src/main/java/io/jare/model/Domain.java b/src/main/java/io/jare/model/Domain.java new file mode 100644 index 0000000..5c1c5dd --- /dev/null +++ b/src/main/java/io/jare/model/Domain.java @@ -0,0 +1,56 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.model; + +import java.io.IOException; + +/** + * Domain. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public interface Domain { + + /** + * Owner of it. + * @return The owner's GitHub handle + * @throws IOException If fails + */ + String owner() throws IOException; + + /** + * Name. + * @return The name + * @throws IOException If fails + */ + String name() throws IOException; + + /** + * Delete it. + * @throws IOException If fails + */ + void delete() throws IOException; + +} diff --git a/src/main/java/io/jare/model/User.java b/src/main/java/io/jare/model/User.java new file mode 100644 index 0000000..212b423 --- /dev/null +++ b/src/main/java/io/jare/model/User.java @@ -0,0 +1,49 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.model; + +import java.io.IOException; + +/** + * User. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public interface User { + + /** + * All my domains. + * @return All domains + */ + Iterable mine(); + + /** + * Add a domain. + * @param name The name of the domain + * @throws IOException If fails + */ + void add(String name) throws IOException; + +} diff --git a/src/main/java/io/jare/model/package-info.java b/src/main/java/io/jare/model/package-info.java new file mode 100644 index 0000000..8b31459 --- /dev/null +++ b/src/main/java/io/jare/model/package-info.java @@ -0,0 +1,23 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.model; diff --git a/src/main/java/io/jare/package-info.java b/src/main/java/io/jare/package-info.java new file mode 100644 index 0000000..5d6b71b --- /dev/null +++ b/src/main/java/io/jare/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Jare. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare; diff --git a/src/main/java/io/jare/tk/RqUser.java b/src/main/java/io/jare/tk/RqUser.java new file mode 100644 index 0000000..551cda1 --- /dev/null +++ b/src/main/java/io/jare/tk/RqUser.java @@ -0,0 +1,72 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import java.io.IOException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.takes.Request; +import org.takes.facets.auth.RqAuth; +import org.takes.rq.RqWrap; + +/** + * User in request. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class RqUser extends RqWrap { + + /** + * Pattern to fetch name. + */ + private static final Pattern PTN = Pattern.compile( + "urn:(github|test):(.*)" + ); + + /** + * Ctor. + * @param req Request + */ + public RqUser(final Request req) { + super(req); + } + + /** + * Get user name (GitHub handle). + * @return Name + * @throws IOException If fails + */ + public String name() throws IOException { + final String urn = new RqAuth(this).identity().urn(); + final Matcher mtr = RqUser.PTN.matcher(urn); + if (!mtr.matches()) { + throw new IllegalArgumentException( + String.format("URN \"%s\" is not from GitHub", urn) + ); + } + return mtr.group(1); + } + +} diff --git a/src/main/java/io/jare/tk/RsPage.java b/src/main/java/io/jare/tk/RsPage.java new file mode 100644 index 0000000..66a5497 --- /dev/null +++ b/src/main/java/io/jare/tk/RsPage.java @@ -0,0 +1,152 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.jcabi.manifests.Manifests; +import java.io.IOException; +import java.util.Arrays; +import lombok.EqualsAndHashCode; +import org.takes.Request; +import org.takes.Response; +import org.takes.facets.auth.Identity; +import org.takes.facets.auth.RqAuth; +import org.takes.facets.auth.XeIdentity; +import org.takes.facets.auth.XeLogoutLink; +import org.takes.facets.auth.social.XeGithubLink; +import org.takes.facets.flash.XeFlash; +import org.takes.facets.fork.FkTypes; +import org.takes.facets.fork.RsFork; +import org.takes.rs.RsPrettyXML; +import org.takes.rs.RsWithType; +import org.takes.rs.RsWrap; +import org.takes.rs.RsXSLT; +import org.takes.rs.xe.RsXembly; +import org.takes.rs.xe.XeAppend; +import org.takes.rs.xe.XeChain; +import org.takes.rs.xe.XeDate; +import org.takes.rs.xe.XeLink; +import org.takes.rs.xe.XeLinkHome; +import org.takes.rs.xe.XeLinkSelf; +import org.takes.rs.xe.XeLocalhost; +import org.takes.rs.xe.XeMillis; +import org.takes.rs.xe.XeSLA; +import org.takes.rs.xe.XeSource; +import org.takes.rs.xe.XeStylesheet; +import org.takes.rs.xe.XeWhen; + +/** + * Index resource, front page of the website. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +@EqualsAndHashCode(callSuper = true) +@SuppressWarnings("PMD.ExcessiveImports") +public final class RsPage extends RsWrap { + + /** + * Ctor. + * @param xsl XSL + * @param req Request + * @param src Source + * @throws IOException If fails + */ + public RsPage(final String xsl, final Request req, final XeSource... src) + throws IOException { + this(xsl, req, Arrays.asList(src)); + } + + /** + * Ctor. + * @param xsl XSL + * @param req Request + * @param src Source + * @throws IOException If fails + */ + public RsPage(final String xsl, final Request req, + final Iterable src) + throws IOException { + super(RsPage.make(xsl, req, src)); + } + + /** + * Make it. + * @param xsl XSL + * @param req Request + * @param src Source + * @return Response + * @throws IOException If fails + */ + private static Response make(final String xsl, final Request req, + final Iterable src) throws IOException { + final Response raw = new RsXembly( + new XeStylesheet(xsl), + new XeAppend( + "page", + new XeMillis(false), + new XeChain(src), + new XeLinkHome(req), + new XeLinkSelf(req), + new XeMillis(true), + new XeDate(), + new XeSLA(), + new XeLocalhost(), + new XeFlash(req), + new XeWhen( + new RqAuth(req).identity().equals(Identity.ANONYMOUS), + new XeChain( + new XeGithubLink(req, Manifests.read("Jare-GithubId")) + ) + ), + new XeWhen( + !new RqAuth(req).identity().equals(Identity.ANONYMOUS), + new XeChain( + new XeIdentity(req), + new XeLogoutLink(req), + new XeLink("domains", "/domains") + ) + ), + new XeAppend( + "version", + new XeAppend("name", Manifests.read("Jare-Version")), + new XeAppend("revision", Manifests.read("Jare-Revision")), + new XeAppend("date", Manifests.read("Jare-Date")) + ) + ) + ); + return new RsFork( + req, + new FkTypes( + "application/xml,text/xml", + new RsPrettyXML(new RsWithType(raw, "text/xml")) + ), + new FkTypes( + "*/*", + new RsXSLT(new RsWithType(raw, "text/html")) + ) + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkAdd.java b/src/main/java/io/jare/tk/TkAdd.java new file mode 100644 index 0000000..fab14f4 --- /dev/null +++ b/src/main/java/io/jare/tk/TkAdd.java @@ -0,0 +1,71 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import io.jare.model.Base; +import java.io.IOException; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; +import org.takes.facets.flash.RsFlash; +import org.takes.facets.forward.RsForward; +import org.takes.rq.RqForm; + +/** + * Add pipe. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +final class TkAdd implements Take { + + /** + * Base. + */ + private final transient Base base; + + /** + * Ctor. + * @param bse Base + */ + TkAdd(final Base bse) { + this.base = bse; + } + + @Override + public Response act(final Request req) throws IOException { + final String name = new RqForm.Base(req).param("name") + .iterator().next().trim(); + this.base.user(new RqUser(req).name()).add(name); + return new RsForward( + new RsFlash( + String.format( + "domain \"%s\" added", name + ) + ), + "/domains" + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkApp.java b/src/main/java/io/jare/tk/TkApp.java index 4d5baea..9cea601 100644 --- a/src/main/java/io/jare/tk/TkApp.java +++ b/src/main/java/io/jare/tk/TkApp.java @@ -22,24 +22,165 @@ */ package io.jare.tk; +import com.jcabi.log.VerboseProcess; +import com.jcabi.manifests.Manifests; +import io.jare.model.Base; +import java.io.File; import java.io.IOException; -import org.takes.Request; -import org.takes.Response; +import java.nio.charset.Charset; import org.takes.Take; -import org.takes.rs.RsText; +import org.takes.facets.auth.TkSecure; +import org.takes.facets.flash.TkFlash; +import org.takes.facets.fork.FkAuthenticated; +import org.takes.facets.fork.FkFixed; +import org.takes.facets.fork.FkHitRefresh; +import org.takes.facets.fork.FkHost; +import org.takes.facets.fork.FkRegex; +import org.takes.facets.fork.TkFork; +import org.takes.facets.forward.TkForward; +import org.takes.tk.TkClasspath; +import org.takes.tk.TkFiles; +import org.takes.tk.TkGzip; +import org.takes.tk.TkMeasured; +import org.takes.tk.TkVersioned; +import org.takes.tk.TkWithHeaders; +import org.takes.tk.TkWithType; +import org.takes.tk.TkWrap; /** - * Command line entry. + * App. * * @author Yegor Bugayenko (yegor@teamed.io) * @version $Id$ * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + * @checkstyle MultipleStringLiteralsCheck (500 lines) + * @checkstyle ClassFanOutComplexityCheck (500 lines) */ -public final class TkApp implements Take { +public final class TkApp extends TkWrap { - @Override - public Response act(final Request req) throws IOException { - return new RsText("hello, world!"); + /** + * Revision of app. + */ + private static final String REV = Manifests.read("Jare-Revision"); + + /** + * Ctor. + * @param base Base + * @throws IOException If fails + */ + public TkApp(final Base base) throws IOException { + super(TkApp.make(base)); + } + + /** + * Ctor. + * @param base Base + * @return Takes + * @throws IOException If fails + */ + private static Take make(final Base base) throws IOException { + if (!"UTF-8".equals(Charset.defaultCharset().name())) { + throw new IllegalStateException( + String.format( + "default encoding is %s", Charset.defaultCharset() + ) + ); + } + return new TkWithHeaders( + new TkVersioned( + new TkMeasured( + new TkGzip( + new TkFlash( + new TkAppFallback( + new TkAppAuth( + new TkForward( + TkApp.regex(base) + ) + ) + ) + ) + ) + ) + ), + String.format("X-Jare-Revision: %s", TkApp.REV), + "Vary: Cookie" + ); + } + + /** + * Regex takes. + * @param base Base + * @return Takes + * @throws IOException If fails + */ + private static Take regex(final Base base) throws IOException { + return new TkFork( + new FkHost("relay.jare.io", new TkRelay(base)), + new FkRegex("/robots.txt", ""), + new FkRegex( + "/xsl/[a-z\\-]+\\.xsl", + new TkWithType( + TkApp.refresh("./src/main/xsl"), + "text/xsl" + ) + ), + new FkRegex( + "/css/[a-z]+\\.css", + new TkWithType( + TkApp.refresh("./src/main/scss"), + "text/css" + ) + ), + new FkRegex( + "/images/[a-z]+\\.svg", + new TkWithType( + TkApp.refresh("./src/main/resources"), + "image/svg+xml" + ) + ), + new FkRegex( + "/images/[a-z]+\\.png", + new TkWithType( + TkApp.refresh("./src/main/resources"), + "image/png" + ) + ), + new FkRegex("/", new TkIndex()), + new FkAuthenticated( + new TkSecure( + new TkFork( + new FkRegex("/domains", new TkDomains(base)), + new FkRegex("/add", new TkAdd(base)), + new FkRegex("/delete", new TkDelete(base)) + ) + ) + ) + ); + } + + /** + * Hit refresh fork. + * @param path Path of files + * @return Fork + * @throws IOException If fails + */ + private static Take refresh(final String path) throws IOException { + return new TkFork( + new FkHitRefresh( + new File(path), + () -> { + new VerboseProcess( + new ProcessBuilder( + "mvn", + "generate-resources" + ) + ).stdout(); + }, + new TkFiles("./target/classes") + ), + new FkFixed(new TkClasspath()) + ); } } diff --git a/src/main/java/io/jare/tk/TkAppAuth.java b/src/main/java/io/jare/tk/TkAppAuth.java new file mode 100644 index 0000000..f11249e --- /dev/null +++ b/src/main/java/io/jare/tk/TkAppAuth.java @@ -0,0 +1,110 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.jcabi.manifests.Manifests; +import java.util.regex.Pattern; +import org.takes.Take; +import org.takes.facets.auth.PsByFlag; +import org.takes.facets.auth.PsChain; +import org.takes.facets.auth.PsCookie; +import org.takes.facets.auth.PsFake; +import org.takes.facets.auth.PsLogout; +import org.takes.facets.auth.TkAuth; +import org.takes.facets.auth.codecs.CcCompact; +import org.takes.facets.auth.codecs.CcHex; +import org.takes.facets.auth.codecs.CcSafe; +import org.takes.facets.auth.codecs.CcSalted; +import org.takes.facets.auth.codecs.CcXOR; +import org.takes.facets.auth.social.PsGithub; +import org.takes.facets.fork.FkFixed; +import org.takes.facets.fork.FkParams; +import org.takes.facets.fork.TkFork; +import org.takes.tk.TkRedirect; +import org.takes.tk.TkWrap; + +/** + * Authenticated app. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +final class TkAppAuth extends TkWrap { + + /** + * Ctor. + * @param take Take + */ + TkAppAuth(final Take take) { + super(TkAppAuth.make(take)); + } + + /** + * Authenticated. + * @param take Takes + * @return Authenticated takes + */ + private static Take make(final Take take) { + return new TkAuth( + new TkFork( + new FkParams( + PsByFlag.class.getSimpleName(), + Pattern.compile(".+"), + new TkRedirect() + ), + new FkFixed(take) + ), + new PsChain( + new PsFake( + Manifests.read("Jare-DynamoKey").startsWith("AAAA") + ), + new PsByFlag( + new PsByFlag.Pair( + PsGithub.class.getSimpleName(), + new PsGithub( + Manifests.read("Jare-GithubId"), + Manifests.read("Jare-GithubSecret") + ) + ), + new PsByFlag.Pair( + PsLogout.class.getSimpleName(), + new PsLogout() + ) + ), + new PsCookie( + new CcSafe( + new CcHex( + new CcXOR( + new CcSalted(new CcCompact()), + Manifests.read("Jare-SecurityKey") + ) + ) + ) + ) + ) + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkAppFallback.java b/src/main/java/io/jare/tk/TkAppFallback.java new file mode 100644 index 0000000..65ef6b7 --- /dev/null +++ b/src/main/java/io/jare/tk/TkAppFallback.java @@ -0,0 +1,116 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.jcabi.manifests.Manifests; +import java.io.IOException; +import java.net.HttpURLConnection; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.takes.Response; +import org.takes.Take; +import org.takes.facets.fallback.FbChain; +import org.takes.facets.fallback.FbStatus; +import org.takes.facets.fallback.RqFallback; +import org.takes.facets.fallback.TkFallback; +import org.takes.misc.Opt; +import org.takes.rs.RsText; +import org.takes.rs.RsVelocity; +import org.takes.rs.RsWithStatus; +import org.takes.rs.RsWithType; +import org.takes.tk.TkWrap; + +/** + * App with fallback. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +final class TkAppFallback extends TkWrap { + + /** + * Revision. + */ + private static final String REV = Manifests.read("Jare-Revision"); + + /** + * Ctor. + * @param take Take + */ + TkAppFallback(final Take take) { + super(TkAppFallback.make(take)); + } + + /** + * Authenticated. + * @param take Takes + * @return Authenticated takes + */ + private static Take make(final Take take) { + return new TkFallback( + take, + new FbChain( + new FbStatus( + HttpURLConnection.HTTP_NOT_FOUND, + new RsWithStatus( + new RsText("page not found"), + HttpURLConnection.HTTP_NOT_FOUND + ) + ), + new FbStatus( + HttpURLConnection.HTTP_BAD_REQUEST, + new RsWithStatus( + new RsText("bad request"), + HttpURLConnection.HTTP_BAD_REQUEST + ) + ), + req -> new Opt.Single<>(TkAppFallback.fatal(req)) + ) + ); + } + + /** + * Make fatal error page. + * @param req Request + * @return Response + * @throws IOException If fails + */ + private static Response fatal(final RqFallback req) throws IOException { + return new RsWithStatus( + new RsWithType( + new RsVelocity( + TkAppFallback.class.getResource("error.html.vm"), + new RsVelocity.Pair( + "err", + ExceptionUtils.getStackTrace(req.throwable()) + ), + new RsVelocity.Pair("rev", TkAppFallback.REV) + ), + "text/html" + ), + HttpURLConnection.HTTP_INTERNAL_ERROR + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkDelete.java b/src/main/java/io/jare/tk/TkDelete.java new file mode 100644 index 0000000..5bdc7ae --- /dev/null +++ b/src/main/java/io/jare/tk/TkDelete.java @@ -0,0 +1,90 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import io.jare.model.Base; +import io.jare.model.Domain; +import java.io.IOException; +import java.util.Iterator; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; +import org.takes.facets.flash.RsFlash; +import org.takes.facets.forward.RsForward; +import org.takes.rq.RqHref; + +/** + * Delete domain. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +final class TkDelete implements Take { + + /** + * Base. + */ + private final transient Base base; + + /** + * Ctor. + * @param bse Base + */ + TkDelete(final Base bse) { + this.base = bse; + } + + @Override + public Response act(final Request req) throws IOException { + final String name = new RqHref.Base(req).href() + .param("name").iterator().next(); + final Iterator domains = this.base.domain(name); + if (!domains.hasNext()) { + throw new RsForward( + new RsFlash( + String.format("domain \"%s\" doesn't exist", name) + ) + ); + } + final Domain domain = domains.next(); + final String user = new RqUser(req).name(); + if (!domain.owner().equals(user)) { + throw new RsForward( + new RsFlash( + String.format("domain \"%s\" is not yours", name) + ) + ); + } + domain.delete(); + return new RsForward( + new RsFlash( + String.format( + "domain \"%s\" deleted", name + ) + ), + "/domains" + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkDomains.java b/src/main/java/io/jare/tk/TkDomains.java new file mode 100644 index 0000000..a3f12ef --- /dev/null +++ b/src/main/java/io/jare/tk/TkDomains.java @@ -0,0 +1,101 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import io.jare.model.Base; +import io.jare.model.Domain; +import java.io.IOException; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; +import org.takes.misc.Href; +import org.takes.rs.xe.XeAppend; +import org.takes.rs.xe.XeDirectives; +import org.takes.rs.xe.XeLink; +import org.takes.rs.xe.XeSource; +import org.takes.rs.xe.XeTransform; +import org.xembly.Directives; + +/** + * Index page, for authenticated user. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + * @checkstyle MultipleStringLiteralsCheck (500 lines) + */ +final class TkDomains implements Take { + + /** + * Base. + */ + private final transient Base base; + + /** + * Ctor. + * @param bse Base + */ + TkDomains(final Base bse) { + this.base = bse; + } + + @Override + public Response act(final Request req) throws IOException { + return new RsPage( + "/xsl/domains.xsl", + req, + new XeAppend( + "domains", + new XeTransform<>( + this.base.user(new RqUser(req).name()).mine(), + TkDomains::source + ) + ), + new XeLink("add", "/add") + ); + } + + /** + * Convert event to Xembly. + * @param domain The event + * @return Xembly + * @throws IOException If fails + */ + private static XeSource source(final Domain domain) throws IOException { + final String name = domain.name(); + return new XeDirectives( + new Directives() + .add("domain") + .add("name").set(name).up() + .append( + new XeLink( + "delete", + new Href("/delete").with("name", name) + ).toXembly() + ) + .up() + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkIndex.java b/src/main/java/io/jare/tk/TkIndex.java new file mode 100644 index 0000000..9a0f76d --- /dev/null +++ b/src/main/java/io/jare/tk/TkIndex.java @@ -0,0 +1,47 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import java.io.IOException; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; + +/** + * Index page, for anonymous users. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +final class TkIndex implements Take { + + @Override + public Response act(final Request req) throws IOException { + return new RsPage( + "/xsl/index.xsl", + req + ); + } + +} diff --git a/src/main/java/io/jare/tk/TkRelay.java b/src/main/java/io/jare/tk/TkRelay.java new file mode 100644 index 0000000..53a500e --- /dev/null +++ b/src/main/java/io/jare/tk/TkRelay.java @@ -0,0 +1,105 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.google.common.collect.Iterables; +import io.jare.model.Base; +import io.jare.model.Domain; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URI; +import java.util.Collections; +import java.util.Iterator; +import java.util.Locale; +import org.takes.HttpException; +import org.takes.Request; +import org.takes.Response; +import org.takes.Take; +import org.takes.rq.RqHref; +import org.takes.tk.TkProxy; + +/** + * Relay. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +final class TkRelay implements Take { + + /** + * Base. + */ + private final transient Base base; + + /** + * Ctor. + * @param bse Base + */ + TkRelay(final Base bse) { + this.base = bse; + } + + @Override + public Response act(final Request req) throws IOException { + final URI uri = URI.create( + new RqHref.Base(req).href().param("u").iterator().next().trim() + ); + final String host = uri.getHost().toLowerCase(Locale.ENGLISH); + final Iterator domains = this.base.domain(host); + if (!domains.hasNext()) { + throw new HttpException( + HttpURLConnection.HTTP_NOT_FOUND, + String.format("domain \"%s\" is not registered", host) + ); + } + final String path; + if (uri.getPath().isEmpty()) { + path = "/"; + } else { + path = uri.getPath(); + } + return new TkProxy(uri.toString()).act( + new Request() { + @Override + public Iterable head() throws IOException { + return Iterables.concat( + Collections.singleton( + String.format( + "GET %s HTTP/1.1", + path + ) + ), + Iterables.skip(req.head(), 1) + ); + } + @Override + public InputStream body() throws IOException { + return req.body(); + } + } + ); + } + +} diff --git a/src/main/java/io/jare/tk/package-info.java b/src/main/java/io/jare/tk/package-info.java new file mode 100644 index 0000000..2a78259 --- /dev/null +++ b/src/main/java/io/jare/tk/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Takes. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare.tk; diff --git a/src/test/dynamodb/domains.json b/src/test/dynamodb/domains.json new file mode 100644 index 0000000..98d2fa1 --- /dev/null +++ b/src/test/dynamodb/domains.json @@ -0,0 +1,45 @@ +{ + "AttributeDefinitions": [ + { + "AttributeName": "domain", + "AttributeType": "S" + }, + { + "AttributeName": "user", + "AttributeType": "S" + } + ], + "KeySchema": [ + { + "AttributeName": "domain", + "KeyType": "HASH" + } + ], + "ProvisionedThroughput": { + "ReadCapacityUnits": "1", + "WriteCapacityUnits": "1" + }, + "TableName": "domains", + "GlobalSecondaryIndexes": [ + { + "IndexName": "mine", + "KeySchema": [ + { + "AttributeName": "user", + "KeyType": "HASH" + }, + { + "AttributeName": "domain", + "KeyType": "RANGE" + } + ], + "Projection": { + "ProjectionType": "ALL" + }, + "ProvisionedThroughput": { + "ReadCapacityUnits": "1", + "WriteCapacityUnits": "1" + } + } + ] +} diff --git a/src/test/java/io/jare/dynamo/DyDomainITCase.java b/src/test/java/io/jare/dynamo/DyDomainITCase.java new file mode 100644 index 0000000..4a79bd3 --- /dev/null +++ b/src/test/java/io/jare/dynamo/DyDomainITCase.java @@ -0,0 +1,62 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import io.jare.model.Base; +import io.jare.model.Domain; +import io.jare.model.User; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; + +/** + * Integration case for {@link DyDomain}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +public final class DyDomainITCase { + + /** + * DyDomain can be added and removed. + * @throws Exception If some problem inside + */ + @Test + public void addsAndRemoveDomains() throws Exception { + final Base base = new DyBase(new Dynamo()); + final String john = "john"; + final User user = base.user(john); + final String name = "google.com"; + user.add(name); + final Domain domain = base.domain(name).next(); + MatcherAssert.assertThat(domain.name(), Matchers.equalTo(name)); + MatcherAssert.assertThat(domain.owner(), Matchers.equalTo(john)); + domain.delete(); + MatcherAssert.assertThat( + base.domain(name).hasNext(), + Matchers.equalTo(false) + ); + } + +} diff --git a/src/test/java/io/jare/dynamo/DyUserITCase.java b/src/test/java/io/jare/dynamo/DyUserITCase.java new file mode 100644 index 0000000..3171b6e --- /dev/null +++ b/src/test/java/io/jare/dynamo/DyUserITCase.java @@ -0,0 +1,94 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.dynamo; + +import com.jcabi.aspects.Tv; +import io.jare.model.Base; +import io.jare.model.Domain; +import io.jare.model.User; +import java.io.IOException; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; + +/** + * Integration case for {@link DyUser}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +public final class DyUserITCase { + + /** + * DyUser can add and remove domains. + * @throws Exception If some problem inside + */ + @Test + public void addsAndRemoveDomains() throws Exception { + final Base base = new DyBase(new Dynamo()); + final User user = base.user("jeffrey"); + final String name = "google.com"; + user.add(name); + final Domain domain = base.domain(name).next(); + MatcherAssert.assertThat( + domain.name(), + Matchers.equalTo(name) + ); + domain.delete(); + MatcherAssert.assertThat( + base.domain(name).hasNext(), + Matchers.equalTo(false) + ); + } + + /** + * DyUser can list domains. + * @throws Exception If some problem inside + */ + @Test + public void listsMineDomains() throws Exception { + final Base base = new DyBase(new Dynamo()); + final User user = base.user("willy"); + for (int idx = 0; idx < Tv.TEN; ++idx) { + user.add(String.format("facebook-%d.com", idx)); + } + MatcherAssert.assertThat( + user.mine().spliterator().getExactSizeIfKnown(), + Matchers.equalTo((long) Tv.TEN) + ); + } + + /** + * DyUser can reject if domain is occupied. + * @throws Exception If some problem inside + */ + @Test(expected = IOException.class) + public void rejectsIfOccupied() throws Exception { + final Base base = new DyBase(new Dynamo()); + base.user("melissa").add("yahoo.com"); + final User alex = base.user("alex"); + alex.add("Yahoo.com"); + } + +} diff --git a/src/test/java/io/jare/dynamo/package-info.java b/src/test/java/io/jare/dynamo/package-info.java new file mode 100644 index 0000000..9c50279 --- /dev/null +++ b/src/test/java/io/jare/dynamo/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Dynamo, tests. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare.dynamo; diff --git a/src/test/java/io/jare/tk/PingingTest.java b/src/test/java/io/jare/tk/PingingTest.java new file mode 100644 index 0000000..0a679b2 --- /dev/null +++ b/src/test/java/io/jare/tk/PingingTest.java @@ -0,0 +1,96 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import io.jare.fake.FkBase; +import java.net.HttpURLConnection; +import java.util.Arrays; +import java.util.Collection; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.takes.Take; +import org.takes.facets.hamcrest.HmRsStatus; +import org.takes.rq.RqFake; + +/** + * Test case for {@link TkApp}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +@RunWith(Parameterized.class) +public final class PingingTest { + + /** + * The URL to ping. + */ + private final transient String url; + + /** + * Ctor. + * @param addr The URL to test + */ + public PingingTest(final String addr) { + this.url = addr; + } + + /** + * Params for JUnit. + * @return Parameters + */ + @Parameterized.Parameters + public static Collection params() { + return Arrays.asList( + new Object[][] { + {"/?x=y"}, + {"/robots.txt"}, + {"/xsl/layout.xsl"}, + {"/css/main.css"}, + {"/images/logo.svg"}, + {"/images/logo.png"}, + } + ); + } + + /** + * App can render the URL. + * @throws Exception If some problem inside + */ + @Test + public void rendersAllPossibleUrls() throws Exception { + final Take take = new TkApp(new FkBase()); + MatcherAssert.assertThat( + this.url, + take.act(new RqFake("INFO", this.url)), + Matchers.not( + new HmRsStatus( + HttpURLConnection.HTTP_NOT_FOUND + ) + ) + ); + } + +} diff --git a/src/test/java/io/jare/tk/TkAppTest.java b/src/test/java/io/jare/tk/TkAppTest.java new file mode 100644 index 0000000..1c1ee9e --- /dev/null +++ b/src/test/java/io/jare/tk/TkAppTest.java @@ -0,0 +1,105 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.jcabi.http.request.JdkRequest; +import com.jcabi.http.response.RestResponse; +import com.jcabi.http.response.XmlResponse; +import com.jcabi.http.wire.VerboseWire; +import com.jcabi.matchers.XhtmlMatchers; +import io.jare.fake.FkBase; +import java.net.HttpURLConnection; +import org.hamcrest.MatcherAssert; +import org.junit.Test; +import org.takes.Take; +import org.takes.http.FtRemote; +import org.takes.rq.RqFake; +import org.takes.rq.RqWithHeader; +import org.takes.rs.RsPrint; + +/** + * Test case for {@link TkApp}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +public final class TkAppTest { + + /** + * App can render front page. + * @throws Exception If some problem inside + */ + @Test + public void rendersHomePage() throws Exception { + final Take take = new TkApp(new FkBase()); + MatcherAssert.assertThat( + XhtmlMatchers.xhtml( + new RsPrint( + take.act( + new RqWithHeader( + new RqFake("GET", "/"), + // @checkstyle MultipleStringLiteralsCheck (1 line) + "Accept", + "text/xml" + ) + ) + ).printBody() + ), + XhtmlMatchers.hasXPaths( + "/page/@date", + "/page/@sla", + "/page/millis", + "/page/links/link[@rel='takes:logout']" + ) + ); + } + + /** + * App can render front page. + * @throws Exception If some problem inside + */ + @Test + public void rendersHomePageViaHttp() throws Exception { + final Take app = new TkApp(new FkBase()); + new FtRemote(app).exec( + home -> { + new JdkRequest(home) + .fetch() + .as(RestResponse.class) + .assertStatus(HttpURLConnection.HTTP_OK) + .as(XmlResponse.class) + .assertXPath("/xhtml:html"); + new JdkRequest(home) + .through(VerboseWire.class) + .header("Accept", "application/xml") + .fetch() + .as(RestResponse.class) + .assertStatus(HttpURLConnection.HTTP_OK) + .as(XmlResponse.class) + .assertXPath("/page/version"); + } + ); + } + +} diff --git a/src/test/java/io/jare/tk/TkIndexTest.java b/src/test/java/io/jare/tk/TkIndexTest.java new file mode 100644 index 0000000..a3e731d --- /dev/null +++ b/src/test/java/io/jare/tk/TkIndexTest.java @@ -0,0 +1,71 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import com.jcabi.matchers.XhtmlMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.Test; +import org.takes.Take; +import org.takes.rq.RqFake; +import org.takes.rq.RqWithHeader; +import org.takes.rs.RsPrint; + +/** + * Test case for {@link TkIndex}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +public final class TkIndexTest { + + /** + * TkHome can render home page. + * @throws Exception If some problem inside + */ + @Test + public void rendersHomePage() throws Exception { + final Take take = new TkAppAuth(new TkIndex()); + MatcherAssert.assertThat( + XhtmlMatchers.xhtml( + new RsPrint( + take.act( + new RqWithHeader( + new RqFake("GET", "/"), + "Accept", + "text/xml" + ) + ) + ).printBody() + ), + XhtmlMatchers.hasXPaths( + "/page/millis", + "/page/identity/urn", + "/page/version", + "/page/links/link[@rel='home']", + "/page/links/link[@rel='self']", + "/page/links/link[@rel='takes:logout']" + ) + ); + } + +} diff --git a/src/test/java/io/jare/tk/TkRelayTest.java b/src/test/java/io/jare/tk/TkRelayTest.java new file mode 100644 index 0000000..3138fba --- /dev/null +++ b/src/test/java/io/jare/tk/TkRelayTest.java @@ -0,0 +1,101 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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 io.jare.tk; + +import io.jare.fake.FkBase; +import java.util.Arrays; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.takes.Take; +import org.takes.facets.fork.FkRegex; +import org.takes.facets.fork.TkFork; +import org.takes.http.FtRemote; +import org.takes.rq.RqFake; +import org.takes.rs.RsPrint; +import org.takes.tk.TkText; + +/** + * Test case for {@link TkRelay}. + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) + */ +public final class TkRelayTest { + + /** + * TkRelay can send the request through. + * @throws Exception If some problem inside + */ + @Test + public void sendsRequestThrough() throws Exception { + final Take target = new TkFork( + new FkRegex("/alpha/beta", new TkText("it's success")) + ); + new FtRemote(target).exec( + home -> MatcherAssert.assertThat( + new RsPrint( + new TkRelay(new FkBase()).act( + new RqFake( + Arrays.asList( + String.format("GET /?u=%s/alpha/beta", home), + "Host: localhost" + ), + "" + ) + ) + ).printBody(), + Matchers.containsString("success") + ) + ); + } + + /** + * TkRelay can send the request through. + * @throws Exception If some problem inside + */ + @Test + public void sendsRequestThroughToHome() throws Exception { + final Take target = new TkFork( + new FkRegex("/", new TkText("it's home")) + ); + new FtRemote(target).exec( + home -> MatcherAssert.assertThat( + new RsPrint( + new TkRelay(new FkBase()).act( + new RqFake( + Arrays.asList( + String.format("GET /?u=%s", home), + "Host: localhost " + ), + "" + ) + ) + ).printBody(), + Matchers.containsString("home") + ) + ); + } + +} diff --git a/src/test/java/io/jare/tk/package-info.java b/src/test/java/io/jare/tk/package-info.java new file mode 100644 index 0000000..cbbb45f --- /dev/null +++ b/src/test/java/io/jare/tk/package-info.java @@ -0,0 +1,31 @@ +/** + * The MIT License (MIT) + * + * Copyright (c) 2016 jare.io + * + * 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. + */ + +/** + * Takes, tests. + * + * @author Yegor Bugayenko (yegor@teamed.io) + * @version $Id$ + * @since 1.0 + */ +package io.jare.tk; diff --git a/src/test/resources/META-INF/MANIFEST.MF b/src/test/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..21ab07b --- /dev/null +++ b/src/test/resources/META-INF/MANIFEST.MF @@ -0,0 +1,8 @@ +Jare-Revision: a1b2c3e +Jare-Version: 1.0 +Jare-Date: ${timestamp} +Jare-DynamoKey: ${failsafe.dynamo.key} +Jare-DynamoSecret: ${failsafe.dynamo.secret} +Jare-GithubId: ${failsafe.github.id} +Jare-GithubSecret: ${failsafe.github.secret} +Jare-SecurityKey: ${failsafe.security.key} diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties new file mode 100644 index 0000000..647e192 --- /dev/null +++ b/src/test/resources/log4j.properties @@ -0,0 +1,29 @@ +# The MIT License (MIT) +# +# Copyright (c) 2016 jare.io +# +# 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. + +log4j.rootLogger=WARN, CONSOLE + +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=com.jcabi.log.MulticolorLayout +log4j.appender.CONSOLE.layout.ConversionPattern=[%color{%p}] %c: %m%n + +log4j.logger.io.jare=INFO +log4j.logger.com.jcabi.dynamo=INFO diff --git a/web.iml b/web.iml index aed18f4..d7c201d 100644 --- a/web.iml +++ b/web.iml @@ -5,6 +5,9 @@ + + + @@ -52,5 +55,10 @@ + + + + + \ No newline at end of file