Made a very simple tenant controller Project: http://git-wip-us.apache.org/repos/asf/metamodel/repo Commit: http://git-wip-us.apache.org/repos/asf/metamodel/commit/8e2ff716 Tree: http://git-wip-us.apache.org/repos/asf/metamodel/tree/8e2ff716 Diff: http://git-wip-us.apache.org/repos/asf/metamodel/diff/8e2ff716
Branch: refs/heads/feature/5.x/swagger-docs Commit: 8e2ff7167eeae456a1e307426407e262dd7297f8 Parents: c9f56aa Author: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Authored: Mon May 23 23:05:21 2016 -0700 Committer: Kasper Sørensen <i.am.kasper.soren...@gmail.com> Committed: Mon May 23 23:05:21 2016 -0700 ---------------------------------------------------------------------- service-webapp/pom.xml | 10 ++ .../service/app/DataContextRegistry.java | 33 ++++++ .../app/InMemoryDataContextRegistry.java | 51 +++++++++ .../service/app/InMemoryTenantContext.java | 41 +++++++ .../service/app/InMemoryTenantRegistry.java | 64 +++++++++++ .../metamodel/service/app/TenantContext.java | 31 +++++ .../metamodel/service/app/TenantRegistry.java | 35 ++++++ .../service/controllers/TenantController.java | 113 +++++++++++++++++++ .../service/controllers/model/Link.java | 59 ++++++++++ .../resources/context/application-context.xml | 2 + 10 files changed, 439 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/pom.xml ---------------------------------------------------------------------- diff --git a/service-webapp/pom.xml b/service-webapp/pom.xml index f3836dd..b452f55 100644 --- a/service-webapp/pom.xml +++ b/service-webapp/pom.xml @@ -35,6 +35,16 @@ under the License. <dependencies> <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-spring</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.metamodel</groupId> + <artifactId>MetaModel-full</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/DataContextRegistry.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/DataContextRegistry.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/DataContextRegistry.java new file mode 100644 index 0000000..dd18a04 --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/DataContextRegistry.java @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +import java.util.List; + +import org.apache.metamodel.DataContext; + +/** + * Represents a user's/tenant's registry of {@link DataContext}s. + */ +public interface DataContextRegistry { + + public List<String> getDataContextIdentifiers(); + + public DataContext openDataContext(String dataContextIdentifier) throws IllegalArgumentException; +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryDataContextRegistry.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryDataContextRegistry.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryDataContextRegistry.java new file mode 100644 index 0000000..89d835d --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryDataContextRegistry.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.apache.metamodel.DataContext; + +public class InMemoryDataContextRegistry implements DataContextRegistry { + + private final Map<String, Supplier<DataContext>> dataContextIdentifiers; + + public InMemoryDataContextRegistry() { + dataContextIdentifiers = new LinkedHashMap<>(); + } + + @Override + public List<String> getDataContextIdentifiers() { + return dataContextIdentifiers.keySet().stream().collect(Collectors.toList()); + } + + @Override + public DataContext openDataContext(String dataContextIdentifier) { + final Supplier<DataContext> supplier = dataContextIdentifiers.get(dataContextIdentifier); + if (supplier == null) { + throw new IllegalArgumentException("No such DataContext: " + dataContextIdentifier); + } + return supplier.get(); + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantContext.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantContext.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantContext.java new file mode 100644 index 0000000..99a3e4e --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantContext.java @@ -0,0 +1,41 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +public class InMemoryTenantContext implements TenantContext { + + private final String tenantIdentifier; + private final DataContextRegistry dataContextRegistry; + + public InMemoryTenantContext(String tenantIdentifier) { + this.tenantIdentifier = tenantIdentifier; + this.dataContextRegistry = new InMemoryDataContextRegistry(); + } + + @Override + public String getTenantIdentifier() { + return tenantIdentifier; + } + + @Override + public DataContextRegistry getDataContextRegistry() { + return dataContextRegistry; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantRegistry.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantRegistry.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantRegistry.java new file mode 100644 index 0000000..c74fb22 --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/InMemoryTenantRegistry.java @@ -0,0 +1,64 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * In-memory {@link TenantRegistry}. This is not particularly + * production-friendly as it is non-persistent, but it is useful for demo + * purposes. + */ +public class InMemoryTenantRegistry implements TenantRegistry { + + private final Map<String, TenantContext> tenants; + + public InMemoryTenantRegistry() { + tenants = new LinkedHashMap<>(); + } + + @Override + public List<String> getTenantIdentifiers() { + return tenants.keySet().stream().collect(Collectors.toList()); + } + + @Override + public TenantContext getTenantContext(String tenantIdentifier) { + return tenants.get(tenantIdentifier); + } + + @Override + public TenantContext createTenantContext(String tenantIdentifier) { + if (tenants.containsKey(tenantIdentifier)) { + throw new IllegalArgumentException("Tenant already exist: " + tenantIdentifier); + } + final InMemoryTenantContext tenantContext = new InMemoryTenantContext(tenantIdentifier); + tenants.put(tenantIdentifier, tenantContext); + return tenantContext; + } + + @Override + public boolean deleteTenantContext(String tenantIdentifier) { + return tenants.remove(tenantIdentifier) != null; + } + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantContext.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantContext.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantContext.java new file mode 100644 index 0000000..4e27922 --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantContext.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +/** + * Represents a context-object containing all the information and services + * related to a particular tenant. + */ +public interface TenantContext { + + public String getTenantIdentifier(); + + public DataContextRegistry getDataContextRegistry(); + +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantRegistry.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantRegistry.java b/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantRegistry.java new file mode 100644 index 0000000..450db2d --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/app/TenantRegistry.java @@ -0,0 +1,35 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.app; + +import java.util.List; + +/** + * Represents the application's central registry of tenants + */ +public interface TenantRegistry { + + public List<String> getTenantIdentifiers(); + + public TenantContext getTenantContext(String tenantIdentifier); + + public TenantContext createTenantContext(String tenantIdentifier) throws IllegalArgumentException; + + public boolean deleteTenantContext(String tenantIdentifier); +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/controllers/TenantController.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/controllers/TenantController.java b/service-webapp/src/main/java/org/apache/metamodel/service/controllers/TenantController.java new file mode 100644 index 0000000..afefb9e --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/controllers/TenantController.java @@ -0,0 +1,113 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.controllers; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.UriBuilder; + +import org.apache.metamodel.service.app.TenantContext; +import org.apache.metamodel.service.app.TenantRegistry; +import org.apache.metamodel.service.controllers.model.Link; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.client.HttpServerErrorException; + +@RestController +@RequestMapping(value = "/{tenant}", produces = MediaType.APPLICATION_JSON_VALUE) +public class TenantController { + + @Autowired + TenantRegistry tenantRegistry; + + @RequestMapping(method = RequestMethod.PUT) + @ResponseBody + public Map<String, Object> putTenant(@PathVariable("tenant") String tenantName) { + final TenantContext tenantContext; + try { + tenantContext = tenantRegistry.createTenantContext(tenantName); + } catch (IllegalArgumentException e) { + throw new HttpServerErrorException(HttpStatus.CONFLICT, e.getMessage()); + } + final String tenantIdentifier = tenantContext.getTenantIdentifier(); + + final Map<String, Object> map = new LinkedHashMap<>(); + map.put("type", "tenant"); + map.put("id", tenantIdentifier); + + return map; + } + + @RequestMapping(method = RequestMethod.DELETE) + @ResponseBody + public Map<String, Object> deleteTenant(@PathVariable("tenant") String tenantName) { + final boolean deleted = tenantRegistry.deleteTenantContext(tenantName); + + if (!deleted) { + throw new HttpServerErrorException(HttpStatus.NOT_FOUND, "No such tenant: " + tenantName); + } + + final Map<String, Object> map = new LinkedHashMap<>(); + map.put("type", "tenant"); + map.put("id", tenantName); + map.put("deleted", deleted); + + return map; + } + + @RequestMapping(method = RequestMethod.GET) + @ResponseBody + public Map<String, Object> getTenant(@PathVariable("tenant") String tenantName) { + final TenantContext tenantContext = tenantRegistry.getTenantContext(tenantName); + if (tenantContext == null) { + throw new HttpServerErrorException(HttpStatus.NOT_FOUND, "No such tenant: " + tenantName); + } + + final String tenantIdentifier = tenantContext.getTenantIdentifier(); + + final UriBuilder uriBuilder = UriBuilder.fromPath("/{tenant}/{dataContext}"); + + final List<String> dataContextIdentifiers = tenantContext.getDataContextRegistry().getDataContextIdentifiers(); + final List<Link> dataContextLinks = dataContextIdentifiers.stream().map(s -> new Link(s, uriBuilder.build( + tenantIdentifier, s))).collect(Collectors.toList()); + + final Map<String, Object> map = new LinkedHashMap<>(); + map.put("type", "tenant"); + map.put("id", tenantIdentifier); + map.put("data-contexts", dataContextLinks); + return map; + } + + @ExceptionHandler(HttpServerErrorException.class) + public void handleException(HttpServerErrorException e, HttpServletResponse resp) throws IOException { + resp.sendError(e.getStatusCode().value(), e.getStatusText()); + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/java/org/apache/metamodel/service/controllers/model/Link.java ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/java/org/apache/metamodel/service/controllers/model/Link.java b/service-webapp/src/main/java/org/apache/metamodel/service/controllers/model/Link.java new file mode 100644 index 0000000..4871553 --- /dev/null +++ b/service-webapp/src/main/java/org/apache/metamodel/service/controllers/model/Link.java @@ -0,0 +1,59 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.metamodel.service.controllers.model; + +import java.io.Serializable; +import java.net.URI; + +/** + * Represents a hyper-link to a service (typically provided in the REST + * responses) + */ +public class Link implements Serializable { + + private static final long serialVersionUID = 1L; + + private String name; + private URI uri; + + public Link() { + } + + public Link(String name, URI uri) { + this(); + this.name = name; + this.uri = uri; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public URI getUri() { + return uri; + } + + public void setUri(URI uri) { + this.uri = uri; + } +} http://git-wip-us.apache.org/repos/asf/metamodel/blob/8e2ff716/service-webapp/src/main/resources/context/application-context.xml ---------------------------------------------------------------------- diff --git a/service-webapp/src/main/resources/context/application-context.xml b/service-webapp/src/main/resources/context/application-context.xml index b0c945d..89a1b28 100644 --- a/service-webapp/src/main/resources/context/application-context.xml +++ b/service-webapp/src/main/resources/context/application-context.xml @@ -29,4 +29,6 @@ under the License. <context:component-scan base-package="org.apache.metamodel.service.app" /> + <bean id="tenantRegistry" class="org.apache.metamodel.service.app.InMemoryTenantRegistry" /> + </beans> \ No newline at end of file