001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018 package org.apache.activemq.karaf.commands;
019
020 import org.apache.felix.gogo.commands.Action;
021 import org.apache.felix.gogo.commands.Argument;
022 import org.apache.felix.gogo.commands.basic.AbstractCommand;
023 import org.apache.felix.gogo.commands.basic.ActionPreparator;
024 import org.apache.felix.gogo.commands.basic.DefaultActionPreparator;
025 import org.apache.karaf.shell.console.BlueprintContainerAware;
026 import org.apache.karaf.shell.console.BundleContextAware;
027 import org.apache.karaf.shell.console.CompletableFunction;
028 import org.apache.karaf.shell.console.Completer;
029 import org.apache.karaf.shell.console.commands.GenericType;
030 import org.osgi.framework.BundleContext;
031 import org.osgi.service.blueprint.container.BlueprintContainer;
032 import org.osgi.service.blueprint.container.Converter;
033 import org.osgi.service.command.CommandSession;
034
035 import java.lang.reflect.Field;
036 import java.lang.reflect.Type;
037 import java.util.ArrayList;
038 import java.util.HashMap;
039 import java.util.Iterator;
040 import java.util.List;
041 import java.util.Map;
042
043 /**
044 * Base command to process options and wrap native ActiveMQ console commands.
045 */
046 public class ActiveMQCommand extends AbstractCommand implements CompletableFunction
047 {
048 protected BlueprintContainer blueprintContainer;
049 protected Converter blueprintConverter;
050 protected String actionId;
051 protected List<Completer> completers;
052
053 public void setBlueprintContainer(BlueprintContainer blueprintContainer) {
054 this.blueprintContainer = blueprintContainer;
055 }
056
057 public void setBlueprintConverter(Converter blueprintConverter) {
058 this.blueprintConverter = blueprintConverter;
059 }
060
061 public void setActionId(String actionId) {
062 this.actionId = actionId;
063 }
064
065 public List<Completer> getCompleters() {
066 return completers;
067 }
068
069 public void setCompleters(List<Completer> completers) {
070 this.completers = completers;
071 }
072
073 @Override
074 protected ActionPreparator getPreparator() throws Exception {
075 return new ActiveMQActionPreparator();
076 }
077
078 class ActiveMQActionPreparator extends DefaultActionPreparator {
079 @Override
080 public boolean prepare(Action action, CommandSession session, List<Object> params) throws Exception
081 {
082 Map<Argument, Field> arguments = new HashMap<Argument, Field>();
083 List<Argument> orderedArguments = new ArrayList<Argument>();
084 // Introspect
085 for (Class type = action.getClass(); type != null; type = type.getSuperclass()) {
086 for (Field field : type.getDeclaredFields()) {
087 Argument argument = field.getAnnotation(Argument.class);
088 if (argument != null) {
089 arguments.put(argument, field);
090 int index = argument.index();
091 while (orderedArguments.size() <= index) {
092 orderedArguments.add(null);
093 }
094 if (orderedArguments.get(index) != null) {
095 throw new IllegalArgumentException("Duplicate argument index: " + index);
096 }
097 orderedArguments.set(index, argument);
098 }
099 }
100 }
101 // Check indexes are correct
102 for (int i = 0; i < orderedArguments.size(); i++) {
103 if (orderedArguments.get(i) == null) {
104 throw new IllegalArgumentException("Missing argument for index: " + i);
105 }
106 }
107 // Populate
108 Map<Argument, Object> argumentValues = new HashMap<Argument, Object>();
109 int argIndex = 0;
110 for (Iterator<Object> it = params.iterator(); it.hasNext();) {
111 Object param = it.next();
112 if (argIndex >= orderedArguments.size()) {
113 throw new IllegalArgumentException("Too many arguments specified");
114 }
115 Argument argument = orderedArguments.get(argIndex);
116 if (!argument.multiValued()) {
117 argIndex++;
118 }
119 if (argument.multiValued()) {
120 List<Object> l = (List<Object>) argumentValues.get(argument);
121 if (l == null) {
122 l = new ArrayList<Object>();
123 argumentValues.put(argument, l);
124 }
125 l.add(param);
126 } else {
127 argumentValues.put(argument, param);
128 }
129 }
130
131 for (Map.Entry<Argument, Object> entry : argumentValues.entrySet()) {
132 Field field = arguments.get(entry.getKey());
133 Object value = convert(action, session, entry.getValue(), field.getGenericType());
134 field.setAccessible(true);
135 field.set(action, value);
136 }
137 return true;
138 }
139
140 @Override
141 protected Object convert(Action action, CommandSession commandSession, Object o, Type type) throws Exception {
142 return blueprintConverter.convert(o, new GenericType(type));
143 }
144 }
145
146 public Action createNewAction() {
147 Action action = (Action) blueprintContainer.getComponentInstance(actionId);
148 if (action instanceof BlueprintContainerAware) {
149 ((BlueprintContainerAware) action).setBlueprintContainer(blueprintContainer);
150 }
151 if (action instanceof BundleContextAware) {
152 BundleContext context = (BundleContext) blueprintContainer.getComponentInstance("blueprintBundleContext");
153 ((BundleContextAware) action).setBundleContext(context);
154 }
155 return action;
156 }
157
158 }