http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java new file mode 100644 index 0000000..08e3912 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java @@ -0,0 +1,50 @@ +/* + * 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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +import org.apache.karaf.jndi.command.completers.NamesCompleter; +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; + +@Command(scope = "jndi", name = "alias", description = "Create a JNDI alias on a given name.") +@Service +public class AliasCommand implements Action { + + @Argument(index = 0, name = "name", description = "The JNDI name", required = true, multiValued = false) + @Completion(NamesCompleter.class) + String name; + + @Argument(index = 1, name = "alias", description = "The JNDI alias", required = true, multiValued = false) + @Completion(ContextsCompleter.class) + String alias; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + jndiService.alias(name, alias); + return null; + } + +}
http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java new file mode 100644 index 0000000..b181762 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java @@ -0,0 +1,50 @@ +/* + * 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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +import org.apache.karaf.jndi.command.completers.ServicesIdCompleter; +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; + +@Command(scope = "jndi", name = "bind", description = "Bind an OSGi service in the JNDI context") +@Service +public class BindCommand implements Action { + + @Argument(index = 0, name = "service", description = "The ID of the OSGi service to bind", required = true, multiValued = false) + @Completion(ServicesIdCompleter.class) + Long serviceId; + + @Argument(index = 1, name = "name", description = "The JNDI name to bind the OSGi service", required = true, multiValued = false) + @Completion(ContextsCompleter.class) + String name; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + jndiService.bind(serviceId, name); + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java new file mode 100644 index 0000000..2209479 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.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.karaf.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +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; +import org.apache.karaf.shell.support.table.ShellTable; + +import java.util.List; + +@Command(scope = "jndi", name = "contexts", description = "List the JNDI sub-contexts.") +@Service +public class ContextsCommand implements Action { + + @Argument(index = 0, name = "context", description = "The base JNDI context", required = false, multiValued = false) + @Completion(ContextsCompleter.class) + String context; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + ShellTable table = new ShellTable(); + + table.column("JNDI Sub-Context"); + + List<String> contexts; + if (context == null) { + contexts = jndiService.contexts(); + } else { + contexts = jndiService.contexts(context); + } + + for (String c : contexts) { + table.addRow().addContent(c); + } + + table.print(System.out); + + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java new file mode 100644 index 0000000..86663bf --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +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; + +@Command(scope = "jndi", name = "create", description = "Create a new JNDI sub-context.") +@Service +public class CreateCommand implements Action { + + @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false) + @Completion(ContextsCompleter.class) + String context; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + jndiService.create(context); + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java new file mode 100644 index 0000000..3cd3a40 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +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; + +@Command(scope = "jndi", name = "delete", description = "Delete a JNDI sub-context.") +@Service +public class DeleteCommand implements Action { + + @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false) + @Completion(ContextsCompleter.class) + String context; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + jndiService.delete(context); + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java new file mode 100644 index 0000000..0345f11 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java @@ -0,0 +1,65 @@ +/* + * 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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.ContextsCompleter; +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; +import org.apache.karaf.shell.support.table.ShellTable; + +import java.util.Map; + +@Command(scope = "jndi", name = "names", description = "List the JNDI names.") +@Service +public class NamesCommand implements Action { + + @Argument(index = 0, name = "context", description = "The JNDI context to display the names", required = false, multiValued = false) + @Completion(ContextsCompleter.class) + String context; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + ShellTable table = new ShellTable(); + + table.column("JNDI Name"); + table.column("Class Name"); + + Map<String, String> names; + if (context == null) { + names = jndiService.names(); + } else { + names = jndiService.names(context); + } + + for (String name : names.keySet()) { + table.addRow().addContent(name, names.get(name)); + } + + table.print(System.out); + + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java new file mode 100644 index 0000000..b93c7b9 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.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.jndi.command; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.command.completers.NamesCompleter; +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; + +@Command(scope = "jndi", name = "unbind", description = "Unbind a JNDI name.") +@Service +public class UnbindCommand implements Action { + + @Argument(index = 0, name = "name", description = "The JNDI name to unbind", required = true, multiValued = false) + @Completion(NamesCompleter.class) + String name; + + @Reference + JndiService jndiService; + + @Override + public Object execute() throws Exception { + jndiService.unbind(name); + return null; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java new file mode 100644 index 0000000..8f2ac29 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java @@ -0,0 +1,60 @@ +/* + * 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.jndi.command.completers; + +import org.apache.karaf.jndi.JndiService; +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; + +/** + * Completers on the JNDI contexts. + */ +@Service +public class ContextsCompleter implements Completer { + + @Reference + private JndiService jndiService; + + @Override + public int complete(Session session, CommandLine commandLine, List<String> candidates) { + StringsCompleter delegate = new StringsCompleter(); + try { + List<String> contexts = jndiService.contexts(); + for (String context : contexts) { + delegate.getStrings().add(context); + } + } catch (Exception e) { + // nothing to do + } + return delegate.complete(session, commandLine, candidates); + } + + public JndiService getJndiService() { + return jndiService; + } + + public void setJndiService(JndiService jndiService) { + this.jndiService = jndiService; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java new file mode 100644 index 0000000..d94e3f4 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.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.karaf.jndi.command.completers; + +import org.apache.karaf.jndi.JndiService; +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; + +/** + * Completer to the JNDI names. + */ +@Service +public class NamesCompleter implements Completer { + + @Reference + private JndiService jndiService; + + @Override + public int complete(Session session, CommandLine commandLine, List<String> candidates) { + StringsCompleter delegate = new StringsCompleter(); + try { + for (String name : jndiService.names().keySet()) { + delegate.getStrings().add(name); + } + } catch (Exception e) { + // nothing to do + } + return delegate.complete(session, commandLine, candidates); + } + + public JndiService getJndiService() { + return jndiService; + } + + public void setJndiService(JndiService jndiService) { + this.jndiService = jndiService; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java new file mode 100644 index 0000000..c7cdb80 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java @@ -0,0 +1,66 @@ +/* + * 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.jndi.command.completers; + +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 org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; + +import java.util.List; + +/** + * Completer on the OSGi services ID. + */ +@Service +public class ServicesIdCompleter implements Completer { + + @Reference + private BundleContext bundleContext; + + @Override + public int complete(Session session, CommandLine commandLine, List<String> candidates) { + StringsCompleter delegate = new StringsCompleter(); + Bundle[] bundles = bundleContext.getBundles(); + for (Bundle bundle : bundles) { + ServiceReference[] references = bundle.getRegisteredServices(); + if (references != null) { + for (ServiceReference reference : references) { + if (reference.getProperty(Constants.SERVICE_ID) != null) { + delegate.getStrings().add(reference.getProperty(Constants.SERVICE_ID).toString()); + } + } + } + } + return delegate.complete(session, commandLine, candidates); + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java new file mode 100644 index 0000000..2433618 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java @@ -0,0 +1,122 @@ +/* + * 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.jndi.internal; + +import org.apache.karaf.jndi.JndiService; +import org.apache.karaf.jndi.JndiMBean; + +import javax.management.MBeanException; +import java.util.List; +import java.util.Map; + +/** + * Implementation of the JndiMBean + */ +public class JndiMBeanImpl implements JndiMBean { + + private JndiService jndiService; + + @Override + public Map<String, String> getNames() throws MBeanException { + try { + return this.jndiService.names(); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public List<String> getContexts() throws MBeanException { + try { + return this.jndiService.contexts(); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public Map<String, String> getNames(String context) throws MBeanException { + try { + return this.jndiService.names(context); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public List<String> getContexts(String context) throws MBeanException { + try { + return this.jndiService.contexts(context); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public void alias(String name, String alias) throws MBeanException { + try { + this.jndiService.alias(name, alias); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public void bind(Long serviceId, String name) throws MBeanException { + try { + this.jndiService.bind(serviceId, name); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public void unbind(String name) throws MBeanException { + try { + this.jndiService.unbind(name); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public void create(String context) throws MBeanException { + try { + this.jndiService.create(context); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + @Override + public void delete(String context) throws MBeanException { + try { + this.jndiService.delete(context); + } catch (Throwable t) { + throw new MBeanException(null, t.getMessage()); + } + } + + public JndiService getJndiService() { + return jndiService; + } + + public void setJndiService(JndiService jndiService) { + this.jndiService = jndiService; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java ---------------------------------------------------------------------- diff --git a/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java new file mode 100644 index 0000000..68d6b94 --- /dev/null +++ b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java @@ -0,0 +1,313 @@ +/* + * 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.jndi.internal; + +import org.apache.aries.proxy.ProxyManager; +import org.apache.karaf.jndi.JndiService; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; + +import javax.naming.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Implementation of the JNDI Service. + */ +public class JndiServiceImpl implements JndiService { + + private BundleContext bundleContext; + private ProxyManager proxyManager; + + private final static String OSGI_JNDI_CONTEXT_PREFIX = "osgi:service/"; + private final static String OSGI_JNDI_SERVICE_PROPERTY = "osgi.jndi.service.name"; + + @Override + public Map<String, String> names() throws Exception { + Map<String, String> result = names("/"); + result.putAll(names(OSGI_JNDI_CONTEXT_PREFIX)); + return result; + } + + @Override + public Map<String, String> names(String name) throws Exception { + Map<String, String> map = new HashMap<String, String>(); + if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) { + // OSGi service binding + // make a lookup using directly the OSGi service + Bundle[] bundles = bundleContext.getBundles(); + for (Bundle bundle : bundles) { + ServiceReference<?>[] services = bundle.getRegisteredServices(); + if (services != null) { + for (ServiceReference service : services) { + if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null) { + Object actualService = bundleContext.getService(service); + if (proxyManager.isProxy(actualService)) { + actualService = proxyManager.unwrap(actualService).call(); + } + map.put(OSGI_JNDI_CONTEXT_PREFIX + service.getProperty(OSGI_JNDI_SERVICE_PROPERTY), actualService.getClass().getName()); + bundleContext.ungetService(service); + } + } + } + } + } else { + // "real" JNDI lookup + Context context = new InitialContext(); + NamingEnumeration<NameClassPair> pairs = context.list(name); + while (pairs.hasMoreElements()) { + NameClassPair pair = pairs.nextElement(); + Object o; + if (name != null) { + o = context.lookup(name + "/" + pair.getName()); + } else { + o = context.lookup(pair.getName()); + } + if (o instanceof Context) { + StringBuilder sb = new StringBuilder(); + sb.append("/" + pair.getName()); + names((Context) o, sb, map); + } else { + map.put("/" + pair.getName(), pair.getClassName()); + } + } + } + return map; + } + + public List<String> contexts() throws Exception { + return contexts("/"); + } + + public List<String> contexts(String name) throws Exception { + List<String> contexts = new ArrayList<String>(); + Context context = new InitialContext(); + NamingEnumeration<NameClassPair> pairs = context.list(name); + while (pairs.hasMoreElements()) { + NameClassPair pair = pairs.nextElement(); + Object o; + if (name != null) { + o = context.lookup(name + "/" + pair.getName()); + } else { + o = context.lookup(pair.getName()); + } + if (o instanceof Context) { + StringBuilder sb = new StringBuilder(); + sb.append("/" + pair.getName()); + contexts((Context) o, sb, contexts); + } + } + return contexts; + } + + private void contexts(Context context, StringBuilder sb, List<String> contexts) throws Exception { + NamingEnumeration list = context.listBindings(""); + while (list.hasMore()) { + Binding item = (Binding) list.next(); + String name = item.getName(); + Object o = item.getObject(); + if (o instanceof Context) { + if (((Context) o).list("").hasMoreElements()) { + sb.append("/").append(name); + contexts((Context) o, sb, contexts); + } else { + contexts.add(sb.toString() + "/" + name); + } + } + } + } + + /** + * Recursively list a context/names + * + * @param ctx the startup context. + * @param sb the string builder where to construct the full qualified name. + * @param map the final map containing name/class name pairs. + * @throws Exception + */ + private static final void names(Context ctx, StringBuilder sb, Map<String, String> map) throws Exception { + NamingEnumeration list = ctx.listBindings(""); + while (list.hasMore()) { + Binding item = (Binding) list.next(); + String className = item.getClassName(); + String name = item.getName(); + Object o = item.getObject(); + if (o instanceof Context) { + sb.append("/").append(name); + names((Context) o, sb, map); + } else { + map.put(sb.toString() + "/" + name, className); + } + } + } + + @Override + public void create(String name) throws Exception { + Context context = new InitialContext(); + String[] splitted = name.split("/"); + if (splitted.length > 0) { + for (int i = 0; i < splitted.length; i++) { + try { + Object o = context.lookup(splitted[i]); + if (!(o instanceof Context)) { + throw new NamingException("Name " + splitted[i] + " already exists"); + } + } catch (NameNotFoundException e) { + context.createSubcontext(splitted[i]); + } + context = (Context) context.lookup(splitted[i]); + } + } else { + context.createSubcontext(name); + } + } + + @Override + public void delete(String name) throws Exception { + Context context = new InitialContext(); + context.destroySubcontext(name); + } + + @Override + public void bind(long serviceId, String name) throws Exception { + Context context = new InitialContext(); + Bundle[] bundles = bundleContext.getBundles(); + for (Bundle bundle : bundles) { + ServiceReference<?>[] services = bundle.getRegisteredServices(); + if (services != null) { + for (ServiceReference service : services) { + if (service.getProperty(Constants.SERVICE_ID) != null && ((Long) service.getProperty(Constants.SERVICE_ID)) == serviceId) { + Object actualService = bundleContext.getService(service); + if (proxyManager.isProxy(actualService)) { + actualService = proxyManager.unwrap(actualService).call(); + } + try { + String[] splitted = name.split("/"); + if (splitted.length > 0) { + for (int i = 0; i < splitted.length - 1; i++) { + try { + Object o = context.lookup(splitted[i]); + if (!(o instanceof Context)) { + throw new NamingException("Name " + splitted[i] + " already exists"); + } + } catch (NameNotFoundException nnfe) { + context.createSubcontext(splitted[i]); + } + context = (Context) context.lookup(splitted[i]); + } + name = splitted[splitted.length - 1]; + } + context.bind(name, actualService); + } finally { + bundleContext.ungetService(service); + } + } + } + } + } + } + + @Override + public void alias(String name, String alias) throws Exception { + Context context = new InitialContext(); + if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) { + // get the object + Bundle[] bundles = bundleContext.getBundles(); + for (Bundle bundle : bundles) { + ServiceReference<?>[] services = bundle.getRegisteredServices(); + if (services != null) { + for (ServiceReference service : services) { + if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null && ((String) service.getProperty(OSGI_JNDI_SERVICE_PROPERTY)).equals(name.substring(OSGI_JNDI_CONTEXT_PREFIX.length()))) { + Object actualService = bundleContext.getService(service); + try { + if (proxyManager.isProxy(actualService)) { + actualService = proxyManager.unwrap(actualService).call(); + } + String[] splitted = alias.split("/"); + if (splitted.length > 0) { + for (int i = 0; i < splitted.length - 1; i++) { + try { + Object o = context.lookup(splitted[i]); + if (!(o instanceof Context)) { + throw new NamingException("Name " + splitted[i] + " already exists"); + } + } catch (NameNotFoundException nnfe) { + context.createSubcontext(splitted[i]); + } + context = (Context) context.lookup(splitted[i]); + } + alias = splitted[splitted.length -1]; + } + context.bind(alias, actualService); + } finally { + bundleContext.ungetService(service); + } + } + } + } + } + } else { + Object object = context.lookup(name); + String[] splitted = alias.split("/"); + if (splitted.length > 0) { + for (int i = 0; i < splitted.length - 1; i++) { + try { + Object o = context.lookup(splitted[i]); + if (!(o instanceof Context)) { + throw new NamingException("Name " + splitted[i] + " already exists"); + } + } catch (NameNotFoundException nnfe) { + context.createSubcontext(splitted[i]); + } + context = (Context) context.lookup(splitted[i]); + } + alias = splitted[splitted.length - 1]; + } + context.bind(alias, object); + } + } + + @Override + public void unbind(String name) throws Exception { + InitialContext context = new InitialContext(); + if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) { + throw new IllegalArgumentException("You can't unbind a name from the " + OSGI_JNDI_CONTEXT_PREFIX + " JNDI context."); + } + context.unbind(name); + } + + public BundleContext getBundleContext() { + return bundleContext; + } + + public void setBundleContext(BundleContext bundleContext) { + this.bundleContext = bundleContext; + } + + public ProxyManager getProxyManager() { + return proxyManager; + } + + public void setProxyManager(ProxyManager proxyManager) { + this.proxyManager = proxyManager; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml ---------------------------------------------------------------------- diff --git a/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml b/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml new file mode 100644 index 0000000..e6be3b1 --- /dev/null +++ b/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + --> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0" + default-activation="lazy"> + + <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/> + + <bean id="karafInitialContextFactory" class="org.apache.karaf.jndi.KarafInitialContextFactory"/> + + <reference id="proxyManager" interface="org.apache.aries.proxy.ProxyManager"/> + + <service ref="karafInitialContextFactory" interface="javax.naming.spi.InitialContextFactory"/> + + <bean id="jndiService" class="org.apache.karaf.jndi.internal.JndiServiceImpl"> + <property name="bundleContext" ref="blueprintBundleContext"/> + <property name="proxyManager" ref="proxyManager"/> + </bean> + + <service ref="jndiService" interface="org.apache.karaf.jndi.JndiService"> + <service-properties> + <!-- bind the JNDI service itself in the JNDI context --> + <entry key="osgi.jndi.service.name" value="jndi"/> + </service-properties> + </service> + + <!-- Management --> + <bean id="jndiMBeanImpl" class="org.apache.karaf.jndi.internal.JndiMBeanImpl"> + <property name="jndiService" ref="jndiService"/> + </bean> + + <service ref="jndiMBeanImpl" auto-export="interfaces"> + <service-properties> + <entry key="jmx.objectname" value="org.apache.karaf:type=jndi,name=$[karaf.name]"/> + </service-properties> + </service> + +</blueprint> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/resources/OSGI-INF/bundle.info ---------------------------------------------------------------------- diff --git a/jndi/src/main/resources/OSGI-INF/bundle.info b/jndi/src/main/resources/OSGI-INF/bundle.info new file mode 100644 index 0000000..4a7a606 --- /dev/null +++ b/jndi/src/main/resources/OSGI-INF/bundle.info @@ -0,0 +1,19 @@ +h1. Synopsis + +${project.name} + +${project.description} + +Maven URL: +[mvn:${project.groupId}/${project.artifactId}/${project.version}] + +h1. Description + +This bundle is the core implementation of the JNDI service support. + +JNDI allows to expose any OSGi services as JNDI names. Karaf JNDI also provides a set of commands and a MBean to list +the current JNDI names, create JNDI aliases, ... + +h1. See also + +JNDI - section of the Karaf User Guide