blob: 8719b3c0d35fbe301158322e7272dd471796adb9 [file] [log] [blame]
Marcel Offermansb264a2a2008-11-25 00:09:57 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
Marcel Offermansb20ea202008-09-18 21:18:03 +000019package org.apache.felix.dependencymanager.shell;
20
21import java.io.PrintStream;
Marcel Offermansb264a2a2008-11-25 00:09:57 +000022import java.util.ArrayList;
Marcel Offermansb20ea202008-09-18 21:18:03 +000023import java.util.Arrays;
24import java.util.Comparator;
Marcel Offermansb264a2a2008-11-25 00:09:57 +000025import java.util.StringTokenizer;
Marcel Offermansb20ea202008-09-18 21:18:03 +000026
27import org.apache.felix.dependencymanager.ServiceComponent;
28import org.apache.felix.dependencymanager.ServiceComponentDependency;
29import org.apache.felix.shell.Command;
Marcel Offermansb264a2a2008-11-25 00:09:57 +000030import org.osgi.framework.Bundle;
Marcel Offermansb20ea202008-09-18 21:18:03 +000031import org.osgi.framework.BundleContext;
32import org.osgi.framework.InvalidSyntaxException;
33import org.osgi.framework.ServiceReference;
34
Marcel Offermansb264a2a2008-11-25 00:09:57 +000035/**
36 * Shell command for showing all services and dependencies that are managed
37 * by the dependency manager.
38 *
39 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
40 */
Marcel Offermansb20ea202008-09-18 21:18:03 +000041public class DMCommand implements Command {
Marcel Offermansb264a2a2008-11-25 00:09:57 +000042 private static final BundleIdSorter SORTER = new BundleIdSorter();
Marcel Offermansb20ea202008-09-18 21:18:03 +000043 private final BundleContext m_context;
44
45 public DMCommand(BundleContext context) {
46 m_context = context;
47 }
48
49 public void execute(String line, PrintStream out, PrintStream err) {
Marcel Offermansb264a2a2008-11-25 00:09:57 +000050 boolean nodeps = false;
51 boolean notavail = false;
52 boolean compact = false;
53 ArrayList ids = new ArrayList();
54
55 // parse the command line
56 StringTokenizer st = new StringTokenizer(line);
57 if (st.hasMoreTokens()) {
58 st.nextToken();
59 while (st.hasMoreTokens()) {
60 String token = st.nextToken();
61 if ("nodeps".equals(token)) {
62 nodeps = true;
63 }
64 else if ("notavail".equals(token)) {
65 notavail = true;
66 }
67 else if ("compact".equals(token)) {
68 compact = true;
69 }
70 else {
71 try {
72 ids.add(Long.valueOf(token));
73 }
74 catch (NumberFormatException e) {
75 // if it's not a number, we abort with an error
76 err.println("Argument " + token + " is not a valid number.");
77 return;
78 }
79 }
80 }
81 // lookup all dependency manager service components
82 try {
83 ServiceReference[] references = m_context.getServiceReferences(ServiceComponent.class.getName(), null);
84 // show their state
85 if (references != null) {
86 Arrays.sort(references, SORTER);
87 long lastBundleId = -1;
88 for (int i = 0; i < references.length; i++) {
89 ServiceReference ref = references[i];
90 ServiceComponent sc = (ServiceComponent) m_context.getService(ref);
91 if (sc != null) {
92 String name = sc.getName();
93 int state = sc.getState();
94 Bundle bundle = ref.getBundle();
95 long bundleId = bundle.getBundleId();
96 if (ids.size() == 0 || ids.contains(Long.valueOf(bundleId))) {
97 if (!notavail || (notavail && sc.getState() == ServiceComponent.STATE_UNREGISTERED)) {
98 if (lastBundleId != bundleId) {
99 lastBundleId = bundleId;
100 if (compact) {
101 out.println("[" + bundleId + "] " + compactName(bundle.getSymbolicName()));
102 }
103 else {
104 out.println("[" + bundleId + "] " + bundle.getSymbolicName());
105 }
106 }
107 if (compact) {
108 out.print(" " + compactName(name) + " " + compactState(ServiceComponent.STATE_NAMES[state]));
109 }
110 else {
111 out.println(" " + name + " " + ServiceComponent.STATE_NAMES[state]);
112 }
113 if (!nodeps) {
114 ServiceComponentDependency[] dependencies = sc.getComponentDependencies();
115 if (dependencies != null && dependencies.length > 0) {
116 if (compact) {
117 out.print('(');
118 }
119 for (int j = 0; j < dependencies.length; j++) {
120 ServiceComponentDependency dep = dependencies[j];
121 String depName = dep.getName();
122 String depType = dep.getType();
123 int depState = dep.getState();
124 if (compact) {
125 if (j > 0) {
126 out.print(' ');
127 }
128 out.print(compactName(depName) + " " + compactState(depType) + " " + compactState(ServiceComponentDependency.STATE_NAMES[depState]));
129 }
130 else {
131 out.println(" " + depName + " " + depType + " " + ServiceComponentDependency.STATE_NAMES[depState]);
132 }
133 }
134 if (compact) {
135 out.print(')');
136 }
137 }
138 }
139 if (compact) {
140 out.println();
141 }
Marcel Offermansb20ea202008-09-18 21:18:03 +0000142 }
143 }
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000144 m_context.ungetService(ref);
Marcel Offermansb20ea202008-09-18 21:18:03 +0000145 }
146 }
147 }
148 }
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000149 catch (InvalidSyntaxException e) {
150 // very weird since I'm not specifying a filter
151 e.printStackTrace(err);
152 }
Marcel Offermansb20ea202008-09-18 21:18:03 +0000153 }
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000154 else {
155 err.println("Invalid command line: " + line);
Marcel Offermansb20ea202008-09-18 21:18:03 +0000156 }
157 }
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000158
159 /**
160 * Compact names that look like state strings. State strings consist of
161 * one or more words. Each word will be shortened to the first letter,
162 * all letters concatenated and uppercased.
163 */
164 private String compactState(String input) {
165 StringBuffer output = new StringBuffer();
166 StringTokenizer st = new StringTokenizer(input);
167 while (st.hasMoreTokens()) {
168 output.append(st.nextToken().toUpperCase().charAt(0));
169 }
170 return output.toString();
171 }
172
173 /**
174 * Compacts names that look like fully qualified class names. All packages
175 * will be shortened to the first letter, except for the last one. So
176 * something like "org.apache.felix.MyClass" will become "o.a.f.MyClass".
177 */
178 private String compactName(String input) {
179 StringBuffer output = new StringBuffer();
180 int lastIndex = 0;
181 for (int i = 0; i < input.length(); i++) {
182 char c = input.charAt(i);
183 switch (c) {
184 case '.':
185 output.append(input.charAt(lastIndex));
186 output.append('.');
187 lastIndex = i + 1;
188 break;
189 case ' ':
190 case ',':
191 if (lastIndex < i) {
192 output.append(input.substring(lastIndex, i));
193 }
194 output.append(c);
195 lastIndex = i + 1;
196 break;
197 }
198 }
199 if (lastIndex < input.length()) {
200 output.append(input.substring(lastIndex));
201 }
202 return output.toString();
203 }
Marcel Offermansb20ea202008-09-18 21:18:03 +0000204
205 public String getName() {
206 return "dm";
207 }
208
209 public String getShortDescription() {
210 return "list dependency manager component diagnostics.";
211 }
212
213 public String getUsage() {
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000214 return "dm [nodeps] [notavail] [compact] [<bundleid> ...]";
Marcel Offermansb20ea202008-09-18 21:18:03 +0000215 }
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000216}
Marcel Offermansb20ea202008-09-18 21:18:03 +0000217
Marcel Offermansb264a2a2008-11-25 00:09:57 +0000218final class BundleIdSorter implements Comparator {
219 public int compare(Object o1, Object o2) {
220 ServiceReference r1 = (ServiceReference) o1;
221 ServiceReference r2 = (ServiceReference) o2;
222 long id1 = r1.getBundle().getBundleId();
223 long id2 = r2.getBundle().getBundleId();
224 return id1 > id2 ? 1 : -1;
225 }
Marcel Offermansb20ea202008-09-18 21:18:03 +0000226}