View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.ui.workbench.osgi;
17  
18  import java.util.ArrayList;
19  import java.util.Comparator;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  import java.util.Set;
24  import java.util.TreeMap;
25  import java.util.TreeSet;
26  
27  import org.argeo.cms.ui.workbench.WorkbenchUiPlugin;
28  import org.argeo.eclipse.ui.TreeParent;
29  import org.eclipse.jface.viewers.ITreeContentProvider;
30  import org.eclipse.jface.viewers.LabelProvider;
31  import org.eclipse.jface.viewers.TreeViewer;
32  import org.eclipse.jface.viewers.Viewer;
33  import org.eclipse.swt.SWT;
34  import org.eclipse.swt.widgets.Composite;
35  import org.eclipse.ui.part.ViewPart;
36  import org.osgi.framework.Bundle;
37  import org.osgi.framework.BundleContext;
38  import org.osgi.framework.ServiceReference;
39  import org.osgi.service.packageadmin.ExportedPackage;
40  import org.osgi.service.packageadmin.PackageAdmin;
41  
42  /** <b>Experimental</b> The OSGi runtime from a module perspective. */
43  @SuppressWarnings({ "deprecation", "rawtypes", "unchecked" })
44  public class MultiplePackagesView extends ViewPart {
45  	private TreeViewer viewer;
46  	private PackageAdmin packageAdmin;
47  	private Comparator<ExportedPackage> epc = new Comparator<ExportedPackage>() {
48  		public int compare(ExportedPackage o1, ExportedPackage o2) {
49  			if (!o1.getName().equals(o2.getName()))
50  				return o1.getName().compareTo(o2.getName());
51  			else
52  				return o1.getVersion().compareTo(o2.getVersion());
53  		}
54  	};
55  
56  	@Override
57  	public void createPartControl(Composite parent) {
58  		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
59  		viewer.setContentProvider(new ModulesContentProvider());
60  		viewer.setLabelProvider(new LabelProvider());
61  		viewer.setInput(WorkbenchUiPlugin.getDefault().getBundle()
62  				.getBundleContext());
63  	}
64  
65  	@Override
66  	public void setFocus() {
67  		viewer.getTree().setFocus();
68  	}
69  
70  	private class ModulesContentProvider implements ITreeContentProvider {
71  		private static final long serialVersionUID = 3819934804640641721L;
72  
73  		public Object[] getElements(Object inputElement) {
74  			return getChildren(inputElement);
75  		}
76  
77  		public Object[] getChildren(Object parentElement) {
78  			if (parentElement instanceof BundleContext) {
79  				BundleContext bundleContext = (BundleContext) parentElement;
80  				Bundle[] bundles = bundleContext.getBundles();
81  
82  				// scan packages
83  				ServiceReference paSr = bundleContext
84  						.getServiceReference(PackageAdmin.class.getName());
85  				// TODO: make a cleaner referencing
86  				packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
87  
88  				Map<Bundle, Set<ExportedPackage>> imported = new HashMap<Bundle, Set<ExportedPackage>>();
89  				Map<String, Set<ExportedPackage>> packages = new TreeMap<String, Set<ExportedPackage>>();
90  				for (Bundle bundle : bundles) {
91  					processBundle(bundle, imported, packages);
92  				}
93  
94  				List<MultiplePackagesNode> multiplePackages = new ArrayList<MultiplePackagesNode>();
95  				for (String packageName : packages.keySet()) {
96  					Set<ExportedPackage> pkgs = packages.get(packageName);
97  					if (pkgs.size() > 1) {
98  						MultiplePackagesNode mpn = new MultiplePackagesNode(
99  								packageName, pkgs);
100 						multiplePackages.add(mpn);
101 					}
102 				}
103 
104 				return multiplePackages.toArray();
105 			} else if (parentElement instanceof TreeParent) {
106 				return ((TreeParent) parentElement).getChildren();
107 			} else {
108 				return null;
109 			}
110 		}
111 
112 		protected void processBundle(Bundle bundle,
113 				Map<Bundle, Set<ExportedPackage>> imported,
114 				Map<String, Set<ExportedPackage>> packages) {
115 			ExportedPackage[] pkgs = packageAdmin.getExportedPackages(bundle);
116 			if (pkgs == null)
117 				return;
118 			for (ExportedPackage pkg : pkgs) {
119 				if (!packages.containsKey(pkg.getName()))
120 					packages.put(pkg.getName(), new TreeSet<ExportedPackage>(
121 							epc));
122 				Set<ExportedPackage> expPackages = packages.get(pkg.getName());
123 				expPackages.add(pkg);
124 
125 				// imported
126 				for (Bundle b : pkg.getImportingBundles()) {
127 					if (bundle.getBundleId() != b.getBundleId()) {
128 						if (!imported.containsKey(b)) {
129 							imported.put(b, new TreeSet<ExportedPackage>(epc));
130 						}
131 						Set<ExportedPackage> impPackages = imported.get(b);
132 						impPackages.add(pkg);
133 					}
134 				}
135 			}
136 		}
137 
138 		public Object getParent(Object element) {
139 			// TODO Auto-generated method stub
140 			return null;
141 		}
142 
143 		public boolean hasChildren(Object element) {
144 			if (element instanceof TreeParent) {
145 				return ((TreeParent) element).hasChildren();
146 			}
147 			return false;
148 		}
149 
150 		public void dispose() {
151 		}
152 
153 		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
154 		}
155 	}
156 
157 	private class MultiplePackagesNode extends TreeParent {
158 		public MultiplePackagesNode(String packageName,
159 				Set<ExportedPackage> exportedPackages) {
160 			super(packageName);
161 			for (ExportedPackage pkg : exportedPackages) {
162 				addChild(new ExportedPackageNode(pkg));
163 			}
164 		}
165 	}
166 
167 	private class ExportedPackageNode extends TreeParent {
168 		public ExportedPackageNode(ExportedPackage exportedPackage) {
169 			super(exportedPackage.getName() + " - "
170 					+ exportedPackage.getVersion() + " ("
171 					+ exportedPackage.getExportingBundle() + ")");
172 			for (Bundle bundle : exportedPackage.getImportingBundles()) {
173 				addChild(new BundleNode(bundle, true));
174 			}
175 		}
176 	}
177 }