Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 4637F200D5F for ; Mon, 18 Dec 2017 17:04:45 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id 448C1160C05; Mon, 18 Dec 2017 16:04:45 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B660B160BF9 for ; Mon, 18 Dec 2017 17:04:43 +0100 (CET) Received: (qmail 80522 invoked by uid 500); 18 Dec 2017 16:04:42 -0000 Mailing-List: contact commits-help@karaf.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@karaf.apache.org Delivered-To: mailing list commits@karaf.apache.org Received: (qmail 80512 invoked by uid 99); 18 Dec 2017 16:04:42 -0000 Received: from ec2-52-202-80-70.compute-1.amazonaws.com (HELO gitbox.apache.org) (52.202.80.70) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 18 Dec 2017 16:04:42 +0000 Received: by gitbox.apache.org (ASF Mail Server at gitbox.apache.org, from userid 33) id C7EF381F81; Mon, 18 Dec 2017 16:04:41 +0000 (UTC) Date: Mon, 18 Dec 2017 16:04:41 +0000 To: "commits@karaf.apache.org" Subject: [karaf-cave] branch master updated: [KARAF-5188] Provide Cave Features Gateway feature MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Message-ID: <151361308176.13530.8600836249108242799@gitbox.apache.org> From: jbonofre@apache.org X-Git-Host: gitbox.apache.org X-Git-Repo: karaf-cave X-Git-Refname: refs/heads/master X-Git-Reftype: branch X-Git-Oldrev: e88795a8699ec515fceb438f6058e5a126042a84 X-Git-Newrev: 3a478cbc336a058374d2c68ada277796c684e4fc X-Git-Rev: 3a478cbc336a058374d2c68ada277796c684e4fc X-Git-NotificationType: ref_changed_plus_diff X-Git-Multimail-Version: 1.5.dev Auto-Submitted: auto-generated archived-at: Mon, 18 Dec 2017 16:04:45 -0000 This is an automated email from the ASF dual-hosted git repository. jbonofre pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/karaf-cave.git The following commit(s) were added to refs/heads/master by this push: new 3a478cb [KARAF-5188] Provide Cave Features Gateway feature 3a478cb is described below commit 3a478cbc336a058374d2c68ada277796c684e4fc Author: Jean-Baptiste Onofré AuthorDate: Mon Dec 18 17:04:21 2017 +0100 [KARAF-5188] Provide Cave Features Gateway feature --- manual/src/main/asciidoc/index.adoc | 2 + .../main/asciidoc/user-guide/features-gateway.adoc | 84 +++++++++++++++++++++ .../karaf/cave/server/api/CaveFeatureGateway.java | 32 ++++++++ .../cave/server/command/GatewayListCommand.java | 40 ++++++++++ .../server/command/GatewayRegisterCommand.java | 42 +++++++++++ .../cave/server/command/GatewayRemoveCommand.java | 45 +++++++++++ .../command/completers/GatewayCompleter.java | 48 ++++++++++++ .../karaf/cave/server/http/CaveHttpServlet.java | 46 ++++++++---- .../cave/server/management/CaveGatewayMBean.java | 24 ++++++ .../cave/server/management/internal/Activator.java | 39 +++++++--- .../management/internal/CaveGatewayMBeanImpl.java | 49 ++++++++++++ .../internal/CaveRepositoryMBeanImpl.java | 1 - server/storage/pom.xml | 13 +++- .../karaf/cave/server/storage/Activator.java | 9 ++- .../server/storage/CaveFeatureGatewayImpl.java | 86 ++++++++++++++++++++++ .../server/storage/CaveFeatureGatewayImplTest.java | 79 ++++++++++++++++++++ 16 files changed, 609 insertions(+), 30 deletions(-) diff --git a/manual/src/main/asciidoc/index.adoc b/manual/src/main/asciidoc/index.adoc index c78f2d2..34026f4 100644 --- a/manual/src/main/asciidoc/index.adoc +++ b/manual/src/main/asciidoc/index.adoc @@ -39,3 +39,5 @@ include::user-guide/http-wrapper.adoc[] include::user-guide/maven-wrapper.adoc[] include::user-guide/administrate-cave.adoc[] + +include::user-guide/features-gateway.adoc[] diff --git a/manual/src/main/asciidoc/user-guide/features-gateway.adoc b/manual/src/main/asciidoc/user-guide/features-gateway.adoc new file mode 100644 index 0000000..b32602b --- /dev/null +++ b/manual/src/main/asciidoc/user-guide/features-gateway.adoc @@ -0,0 +1,84 @@ +// +// Licensed 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. +// + +=== Cave Features Gateway + +Apache Karaf Cave can also act as a central Karaf Features gateway. For instance, you can have an unique Cave server in your organization, providing +a single features repository for your Karaf instances. + +Your Karaf instances on your ecosystem can connect to this unique Cave features gateway URL. + +Then, you manage your features repository on the "central" Cave server, and the Karaf instances get the features (without knowing exactly where they come from). + +The Cave Features Gateway is automatically installed by the `cave-server` feature. + +==== Cave Features Gateway server + +You can manipulate the Features Gateway using specific shell commands or corresponding MBean. + +===== Shell commands + +You can register a features repository in the gateway using `cave:gateway-register` command. For example, you can register +Apache Camel feature in the gateway using: + +---- +karaf@root()> cave:gateway-register mvn:org.apache.camel.karaf/apache-camel/2.18.1/xml/features +---- + +Any URL (http, file, mvn, ...) supported by Apache Karaf is supported by Cave Features Gateway. + +You can see the features repository registered in the gateway using the `cave:gateway-register` command: + +---- +karaf@root()> cave:gateway-list +mvn:org.apache.camel.karaf/apache-camel/2.18.1/xml/features +---- + +You can also delete a features repository from the gateway using `cave:gateway-remove` command: + +---- +karaf@root()> cave:gateway-remove mvn:org.apache.camel.karaf/apache-camel/2.18.1/xml/features +---- + +===== MBean + +Similar to the `cave:gateway*` commands, you find similar operation on the CaveGatewayMBean. + +This MBean uses the following object name: + +---- +org.apache.karaf.cave:type=gateway,name=* +---- + +This MBean provides the following operations: + +* `List list()` +* `register(repository)` +* `remove(repository)` + +==== Plugin your Karaf instances with the central gateway + +The Cave Features Gateway is available on the Cave HTTP service at the following URL: + +---- +http://localhost:8181/cave/http/gateway +---- + +Any Karaf instance can use the gateway using the regular `feature:repo-add` command: + +---- +karaf@root()> feature:repo-add http://cave_server:8181/cave/http/gateway +---- + +NB: the Karaf instances use a cache, so you have to flush the changes on the gateway using the `feature:repo-refresh` command. \ No newline at end of file diff --git a/server/api/src/main/java/org/apache/karaf/cave/server/api/CaveFeatureGateway.java b/server/api/src/main/java/org/apache/karaf/cave/server/api/CaveFeatureGateway.java new file mode 100644 index 0000000..196dfe0 --- /dev/null +++ b/server/api/src/main/java/org/apache/karaf/cave/server/api/CaveFeatureGateway.java @@ -0,0 +1,32 @@ +/* + * 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.karaf.cave.server.api; + +import java.io.File; +import java.util.List; + +public interface CaveFeatureGateway { + + String STORAGE = System.getProperty("karaf.data") + File.separator + "cave-features-gateway.xml"; + + void register(String url) throws Exception; + + void remove(String id) throws Exception; + + List list() throws Exception; + +} diff --git a/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayListCommand.java b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayListCommand.java new file mode 100644 index 0000000..07c34b3 --- /dev/null +++ b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayListCommand.java @@ -0,0 +1,40 @@ +/* + * 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.karaf.cave.server.command; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.shell.api.action.Action; +import org.apache.karaf.shell.api.action.Command; +import org.apache.karaf.shell.api.action.lifecycle.Reference; +import org.apache.karaf.shell.api.action.lifecycle.Service; + +@Service +@Command(scope = "cave", name = "gateway-list", description = "List the features repositories registered in the gateway") +public class GatewayListCommand implements Action { + + @Reference + private CaveFeatureGateway gateway; + + @Override + public Object execute() throws Exception { + for (String repository : gateway.list()) { + System.out.println(repository); + } + return null; + } + +} diff --git a/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRegisterCommand.java b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRegisterCommand.java new file mode 100644 index 0000000..86c5f70 --- /dev/null +++ b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRegisterCommand.java @@ -0,0 +1,42 @@ +/* + * 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.karaf.cave.server.command; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.shell.api.action.Action; +import org.apache.karaf.shell.api.action.Argument; +import org.apache.karaf.shell.api.action.Command; +import org.apache.karaf.shell.api.action.lifecycle.Reference; +import org.apache.karaf.shell.api.action.lifecycle.Service; + +@Service +@Command(scope = "cave", name = "gateway-register", description = "Register a features repository in the gateway") +public class GatewayRegisterCommand implements Action { + + @Argument(name = "repository", description = "The features repository URL ", required = true, multiValued = false) + String repository; + + @Reference + CaveFeatureGateway gateway; + + @Override + public Object execute() throws Exception { + gateway.register(repository); + return null; + } + +} diff --git a/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRemoveCommand.java b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRemoveCommand.java new file mode 100644 index 0000000..e2d64cf --- /dev/null +++ b/server/command/src/main/java/org/apache/karaf/cave/server/command/GatewayRemoveCommand.java @@ -0,0 +1,45 @@ +/* + * 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.karaf.cave.server.command; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.cave.server.command.completers.GatewayCompleter; +import org.apache.karaf.shell.api.action.Action; +import org.apache.karaf.shell.api.action.Argument; +import org.apache.karaf.shell.api.action.Command; +import org.apache.karaf.shell.api.action.Completion; +import org.apache.karaf.shell.api.action.lifecycle.Reference; +import org.apache.karaf.shell.api.action.lifecycle.Service; + +@Service +@Command(scope = "cave", name = "gateway-remove", description = "Remove a features repository from the gateway") +public class GatewayRemoveCommand implements Action { + + @Argument(name = "repository", description = "The features repository URL", required = true, multiValued = false) + @Completion(GatewayCompleter.class) + String repository; + + @Reference + private CaveFeatureGateway gateway; + + @Override + public Object execute() throws Exception { + gateway.remove(repository); + return null; + } + +} diff --git a/server/command/src/main/java/org/apache/karaf/cave/server/command/completers/GatewayCompleter.java b/server/command/src/main/java/org/apache/karaf/cave/server/command/completers/GatewayCompleter.java new file mode 100644 index 0000000..7e85a37 --- /dev/null +++ b/server/command/src/main/java/org/apache/karaf/cave/server/command/completers/GatewayCompleter.java @@ -0,0 +1,48 @@ +/* + * 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.karaf.cave.server.command.completers; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.shell.api.action.lifecycle.Reference; +import org.apache.karaf.shell.api.action.lifecycle.Service; +import org.apache.karaf.shell.api.console.CommandLine; +import org.apache.karaf.shell.api.console.Completer; +import org.apache.karaf.shell.api.console.Session; +import org.apache.karaf.shell.support.completers.StringsCompleter; + +import java.util.List; + +@Service +public class GatewayCompleter implements Completer { + + @Reference + private CaveFeatureGateway gateway; + + @Override + public int complete(Session session, CommandLine commandLine, List list) { + StringsCompleter delegate = new StringsCompleter(); + try { + for (String repository : gateway.list()) { + delegate.getStrings().add(repository); + } + } catch (Exception e) { + // ignore + } + return delegate.complete(session, commandLine, list); + } + +} diff --git a/server/http/src/main/java/org/apache/karaf/cave/server/http/CaveHttpServlet.java b/server/http/src/main/java/org/apache/karaf/cave/server/http/CaveHttpServlet.java index 4fb2f0f..ff02500 100644 --- a/server/http/src/main/java/org/apache/karaf/cave/server/http/CaveHttpServlet.java +++ b/server/http/src/main/java/org/apache/karaf/cave/server/http/CaveHttpServlet.java @@ -16,10 +16,7 @@ */ package org.apache.karaf.cave.server.http; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintWriter; +import java.io.*; import java.net.URI; import java.net.URL; import java.util.zip.GZIPOutputStream; @@ -36,6 +33,7 @@ import javax.xml.transform.TransformerException; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.apache.karaf.cave.server.api.CaveFeatureGateway; import org.apache.karaf.cave.server.api.CaveRepository; import org.apache.karaf.cave.server.api.CaveRepositoryService; import org.apache.karaf.util.XmlUtils; @@ -85,17 +83,19 @@ public class CaveHttpServlet extends HttpServlet { protected long getLastModified(HttpServletRequest request) { String uri = request.getPathInfo(); // remove the starting / - uri = uri.substring(1); - if (request.getPathInfo().endsWith("-repository.xml")) { - // the user wants to get the Cave repository repository.xml - // the expected format is {cave-repo-name}-repository.xml - int index = uri.indexOf("-repository.xml"); - String caveRepositoryName = uri.substring(0, index); - CaveRepositoryService caveRepositoryService = tracker.getService(); - if (caveRepositoryService != null) { - CaveRepository caveRepository = caveRepositoryService.getRepository(caveRepositoryName); - if (caveRepository != null) { - return caveRepository.getIncrement(); + if (uri != null) { + uri = uri.substring(1); + if (request.getPathInfo().endsWith("-repository.xml")) { + // the user wants to get the Cave repository repository.xml + // the expected format is {cave-repo-name}-repository.xml + int index = uri.indexOf("-repository.xml"); + String caveRepositoryName = uri.substring(0, index); + CaveRepositoryService caveRepositoryService = tracker.getService(); + if (caveRepositoryService != null) { + CaveRepository caveRepository = caveRepositoryService.getRepository(caveRepositoryName); + if (caveRepository != null) { + return caveRepository.getIncrement(); + } } } } @@ -114,6 +114,22 @@ public class CaveHttpServlet extends HttpServlet { String uri = request.getPathInfo(); + // Cave Feature gateway + if (uri.equals("/gateway")) { + response.setContentType("application/xml"); + File file = new File(CaveFeatureGateway.STORAGE); + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + PrintWriter writer = response.getWriter(); + String line; + while ((line = reader.readLine()) != null) { + writer.println(line); + } + writer.flush(); + writer.close(); + } + return; + } + // remove the starting / uri = uri.substring(1); diff --git a/server/management/src/main/java/org/apache/karaf/cave/server/management/CaveGatewayMBean.java b/server/management/src/main/java/org/apache/karaf/cave/server/management/CaveGatewayMBean.java new file mode 100644 index 0000000..fdca603 --- /dev/null +++ b/server/management/src/main/java/org/apache/karaf/cave/server/management/CaveGatewayMBean.java @@ -0,0 +1,24 @@ +/* + * Licensed 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.karaf.cave.server.management; + +import java.util.List; + +public interface CaveGatewayMBean { + + List list() throws Exception; + void register(String repository) throws Exception; + void remove(String repository) throws Exception; + +} diff --git a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java index 3d61032..7579caa 100644 --- a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java +++ b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java @@ -2,6 +2,7 @@ package org.apache.karaf.cave.server.management.internal; import java.util.Hashtable; +import org.apache.karaf.cave.server.api.CaveFeatureGateway; import org.apache.karaf.cave.server.api.CaveRepositoryService; import org.apache.karaf.util.tracker.BaseActivator; import org.apache.karaf.util.tracker.annotation.RequireService; @@ -23,28 +24,44 @@ import org.osgi.framework.ServiceRegistration; */ @Services( - requires = { @RequireService(CaveRepositoryService.class) } + requires = { + @RequireService(CaveRepositoryService.class), + @RequireService(CaveFeatureGateway.class) + } ) public class Activator extends BaseActivator { - private volatile ServiceRegistration registration; + private volatile ServiceRegistration repositoryRegistration; + private volatile ServiceRegistration gatewayRegistration; @Override protected void doStart() throws Exception { - CaveRepositoryService service = getTrackedService(CaveRepositoryService.class); - CaveRepositoryMBeanImpl mbean = new CaveRepositoryMBeanImpl(); - mbean.setCaveRepositoryService(service); + CaveRepositoryService repositoryService = getTrackedService(CaveRepositoryService.class); + CaveRepositoryMBeanImpl repositoryMBean = new CaveRepositoryMBeanImpl(); + repositoryMBean.setCaveRepositoryService(repositoryService); + + Hashtable repositoryProps = new Hashtable<>(); + repositoryProps.put("jmx.objectname", "org.apache.karaf.cave:type=repository,name=" + System.getProperty("karaf.name")); + repositoryRegistration = this.bundleContext.registerService(getInterfaceNames(repositoryMBean), repositoryMBean, repositoryProps); - Hashtable props = new Hashtable<>(); - props.put("jmx.objectname", "org.apache.karaf.cave:type=repository,name=" + System.getProperty("karaf.name")); - registration = this.bundleContext.registerService(getInterfaceNames(mbean), mbean, props); + CaveFeatureGateway gatewayService = getTrackedService(CaveFeatureGateway.class); + CaveGatewayMBeanImpl gatewayMBean = new CaveGatewayMBeanImpl(); + gatewayMBean.setGateway(gatewayService); + + Hashtable gatewayProps = new Hashtable<>(); + gatewayProps.put("jmx.objectname", "org.apache.karaf.cave:type=gateway,name=" + System.getProperty("karaf.name")); + gatewayRegistration = this.bundleContext.registerService(getInterfaceNames(gatewayMBean), gatewayMBean, gatewayProps); } @Override protected void doStop() { - if (registration != null) { - registration.unregister(); - registration = null; + if (repositoryRegistration != null) { + repositoryRegistration.unregister(); + repositoryRegistration = null; + } + if (gatewayRegistration != null) { + gatewayRegistration.unregister(); + gatewayRegistration = null; } super.doStop(); } diff --git a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveGatewayMBeanImpl.java b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveGatewayMBeanImpl.java new file mode 100644 index 0000000..77d7bfc --- /dev/null +++ b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveGatewayMBeanImpl.java @@ -0,0 +1,49 @@ +/* + * Licensed 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.karaf.cave.server.management.internal; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.cave.server.management.CaveGatewayMBean; + +import javax.management.NotCompliantMBeanException; +import javax.management.StandardMBean; +import java.util.List; + +public class CaveGatewayMBeanImpl extends StandardMBean implements CaveGatewayMBean { + + private CaveFeatureGateway gateway; + + public CaveGatewayMBeanImpl() throws NotCompliantMBeanException { + super(CaveGatewayMBean.class); + } + + public void setGateway(CaveFeatureGateway gateway) { + this.gateway = gateway; + } + + @Override + public List list() throws Exception { + return gateway.list(); + } + + @Override + public void register(String repository) throws Exception { + + } + + @Override + public void remove(String repository) throws Exception { + + } +} diff --git a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveRepositoryMBeanImpl.java b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveRepositoryMBeanImpl.java index 39052cf..95f71aa 100644 --- a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveRepositoryMBeanImpl.java +++ b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/CaveRepositoryMBeanImpl.java @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.karaf.cave.server.management.internal; import java.io.FileInputStream; diff --git a/server/storage/pom.xml b/server/storage/pom.xml index cfccfe0..86cfe06 100644 --- a/server/storage/pom.xml +++ b/server/storage/pom.xml @@ -83,7 +83,14 @@ ${project.artifactId} - !org.apache.karaf.features.internal.*, + !org.apache.karaf.features.internal.model, + !org.apache.karaf.features.internal.resolver, + !org.apache.karaf.features.internal.repository, + !org.apache.karaf.features.internal.util, + !org.apache.karaf.util*, + !org.apache.felix.utils*, + !org.apache.felix.resolver, + !org.apache.felix.resolver.util, org.apache.karaf.features;version="[2,5)", * @@ -91,9 +98,11 @@ org.apache.felix.utils*, org.apache.felix.resolver, org.apache.felix.resolver.util, + org.apache.karaf.features.internal.model, org.apache.karaf.features.internal.resolver, org.apache.karaf.features.internal.repository, - org.apache.karaf.util.tracker* + org.apache.karaf.features.internal.util, + org.apache.karaf.util* diff --git a/server/storage/src/main/java/org/apache/karaf/cave/server/storage/Activator.java b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/Activator.java index 379dc8f..43d2e39 100644 --- a/server/storage/src/main/java/org/apache/karaf/cave/server/storage/Activator.java +++ b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/Activator.java @@ -18,6 +18,7 @@ package org.apache.karaf.cave.server.storage; import java.io.File; +import org.apache.karaf.cave.server.api.CaveFeatureGateway; import org.apache.karaf.cave.server.api.CaveRepositoryService; import org.apache.karaf.util.tracker.BaseActivator; import org.apache.karaf.util.tracker.annotation.Managed; @@ -27,7 +28,10 @@ import org.osgi.framework.FrameworkUtil; import org.osgi.service.cm.ManagedService; @Services( - provides = { @ProvideService(CaveRepositoryService.class) } + provides = { + @ProvideService(CaveRepositoryService.class), + @ProvideService(CaveFeatureGateway.class) + } ) @Managed("org.apache.karaf.cave.server.storage") public class Activator extends BaseActivator implements ManagedService { @@ -39,6 +43,9 @@ public class Activator extends BaseActivator implements ManagedService { service.setStorageLocation(new File(getString("cave.storage.location", System.getProperty("karaf.data") + File.separator + "cave"))); service.init(); register(CaveRepositoryService.class, service); + + CaveFeatureGatewayImpl gateway = new CaveFeatureGatewayImpl(); + register(CaveFeatureGateway.class, gateway); } } diff --git a/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImpl.java b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImpl.java new file mode 100644 index 0000000..0d2bd76 --- /dev/null +++ b/server/storage/src/main/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImpl.java @@ -0,0 +1,86 @@ +/* + * 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.karaf.cave.server.storage; + +import org.apache.karaf.cave.server.api.CaveFeatureGateway; +import org.apache.karaf.features.internal.model.Features; +import org.apache.karaf.features.internal.model.JaxbUtil; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +public class CaveFeatureGatewayImpl implements CaveFeatureGateway { + + @Override + public void register(String url) throws Exception { + File storage = new File(STORAGE); + + Features features = new Features(); + if (storage.exists()) { + features = JaxbUtil.unmarshal(storage.getAbsolutePath(), true); + } else { + storage.getParentFile().mkdirs(); + storage.createNewFile(); + } + features.setName("cave-gateway"); + if (isFeaturesRepositoryRegistered(url, features.getRepository())) { + throw new IllegalArgumentException("Features repository " + url + " already registered in the gateway"); + } + features.getRepository().add(url); + JaxbUtil.marshal(features, new FileOutputStream(storage)); + } + + @Override + public void remove(String url) throws Exception { + File storage = new File(STORAGE); + + if (!storage.exists()) { + return; + } + + Features features = JaxbUtil.unmarshal(storage.getAbsolutePath(), true); + if (!isFeaturesRepositoryRegistered(url, features.getRepository())) { + throw new IllegalArgumentException("Features repository " + url + " is not registered in the gateway"); + } + features.getRepository().remove(url); + JaxbUtil.marshal(features, new FileOutputStream(storage)); + } + + @Override + public List list() throws Exception { + List repositories = new ArrayList<>(); + + File storage = new File(STORAGE); + if (storage.exists()) { + Features features = JaxbUtil.unmarshal(storage.getAbsolutePath(), true); + repositories = features.getRepository(); + } + + return repositories; + } + + private boolean isFeaturesRepositoryRegistered(String url, List repositories) { + for (String repository : repositories) { + if (repository.equals(url)) { + return true; + } + } + return false; + } +} diff --git a/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImplTest.java b/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImplTest.java new file mode 100644 index 0000000..b6d8c7f --- /dev/null +++ b/server/storage/src/test/java/org/apache/karaf/cave/server/storage/CaveFeatureGatewayImplTest.java @@ -0,0 +1,79 @@ +/* + * 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.karaf.cave.server.storage; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; + +public class CaveFeatureGatewayImplTest { + + private CaveFeatureGatewayImpl gateway; + + @Before + public void setup() throws Exception { + System.setProperty("karaf.data", "target/test-classes"); + File file = new File("target/test-classes/cave-features-gateway.xml"); + if (file.exists()) { + file.delete(); + } + gateway = new CaveFeatureGatewayImpl(); + } + + @Test + public void testRegister() throws Exception { + gateway.register("mvn:test/test/1.0-SNAPSHOT"); + String expected = "" + + "" + + " mvn:test/test/1.0-SNAPSHOT" + + ""; + String result = readCaveFile(); + Assert.assertEquals(expected, result); + } + + @Test + public void testRemove() throws Exception { + gateway.register("mvn:test/second/1.0-SNAPSHOT"); + String expected = "" + + "" + + " mvn:test/second/1.0-SNAPSHOT" + + ""; + String result = readCaveFile(); + Assert.assertEquals(expected, result); + gateway.remove("mvn:test/second/1.0-SNAPSHOT"); + expected = "" + + ""; + result = readCaveFile(); + Assert.assertEquals(expected, result); + } + + private String readCaveFile() throws Exception { + File file = new File("target/test-classes/cave-features-gateway.xml"); + StringBuilder builder = new StringBuilder(); + BufferedReader reader = new BufferedReader(new FileReader(file)); + String line; + while ((line = reader.readLine()) != null) { + builder.append(line); + } + return builder.toString(); + } + +} -- To stop receiving notification emails like this one, please contact ['"commits@karaf.apache.org" '].