blob: 6ea4bacffb928f2948abc4dc9a3ca5107731cbbb [file] [log] [blame]
Richard S. Hallbad49dc2007-07-13 16:08:06 +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 */
19package org.apache.felix.example.servicebased.host;
20
Richard S. Hall57376bf2012-03-06 19:19:04 +000021import javax.swing.Icon;
22import javax.swing.SwingUtilities;
Richard S. Hallbad49dc2007-07-13 16:08:06 +000023import org.apache.felix.example.servicebased.host.service.SimpleShape;
Richard S. Hall57376bf2012-03-06 19:19:04 +000024import org.osgi.framework.BundleContext;
25import org.osgi.framework.ServiceReference;
26import org.osgi.util.tracker.ServiceTracker;
Richard S. Hallbad49dc2007-07-13 16:08:06 +000027
28/**
29 * Extends the <tt>ServiceTracker</tt> to create a tracker for
30 * <tt>SimpleShape</tt> services. The tracker is responsible for
31 * listener for the arrival/departure of <tt>SimpleShape</tt>
32 * services and informing the application about the availability
33 * of shapes. This tracker forces all notifications to be processed
34 * on the Swing event thread to avoid synchronization and redraw
35 * issues.
36**/
Richard S. Hall3c1c0882012-03-13 17:32:01 +000037public class ShapeTracker extends ServiceTracker<SimpleShape, SimpleShape>
Richard S. Hallbad49dc2007-07-13 16:08:06 +000038{
Richard S. Hallb0eb11c2007-07-25 18:57:27 +000039 // The bundle context used for tracking.
Richard S. Hall57376bf2012-03-06 19:19:04 +000040 private final BundleContext m_context;
Richard S. Hallbad49dc2007-07-13 16:08:06 +000041 // The application object to notify.
Richard S. Hall57376bf2012-03-06 19:19:04 +000042 private final DrawingFrame m_frame;
Richard S. Hallbad49dc2007-07-13 16:08:06 +000043
44 /**
45 * Constructs a tracker that uses the specified bundle context to
46 * track services and notifies the specified application object about
47 * changes.
48 * @param context The bundle context to be used by the tracker.
49 * @param frame The application object to notify about service changes.
50 **/
51 public ShapeTracker(BundleContext context, DrawingFrame frame)
52 {
53 super(context, SimpleShape.class.getName(), null);
Richard S. Hallb0eb11c2007-07-25 18:57:27 +000054 m_context = context;
Richard S. Hallbad49dc2007-07-13 16:08:06 +000055 m_frame = frame;
56 }
57
58 /**
59 * Overrides the <tt>ServiceTracker</tt> functionality to inform
60 * the application object about the added service.
61 * @param ref The service reference of the added service.
62 * @return The service object to be used by the tracker.
63 **/
Richard S. Hall57376bf2012-03-06 19:19:04 +000064 @Override
Richard S. Hall3c1c0882012-03-13 17:32:01 +000065 public SimpleShape addingService(ServiceReference<SimpleShape> ref)
Richard S. Hallbad49dc2007-07-13 16:08:06 +000066 {
Richard S. Hallb0eb11c2007-07-25 18:57:27 +000067 SimpleShape shape = new DefaultShape(m_context, ref);
Richard S. Hall57376bf2012-03-06 19:19:04 +000068 processShapeOnEventThread(ShapeEvent.ADDED, ref, shape);
Richard S. Hallbad49dc2007-07-13 16:08:06 +000069 return shape;
70 }
71
72 /**
73 * Overrides the <tt>ServiceTracker</tt> functionality to inform
74 * the application object about the modified service.
75 * @param ref The service reference of the modified service.
76 * @param svc The service object of the modified service.
77 **/
Richard S. Hall57376bf2012-03-06 19:19:04 +000078 @Override
Richard S. Hall3c1c0882012-03-13 17:32:01 +000079 public void modifiedService(ServiceReference<SimpleShape> ref, SimpleShape svc)
Richard S. Hallbad49dc2007-07-13 16:08:06 +000080 {
Richard S. Hall3c1c0882012-03-13 17:32:01 +000081 processShapeOnEventThread(ShapeEvent.MODIFIED, ref, svc);
Richard S. Hallbad49dc2007-07-13 16:08:06 +000082 }
83
84 /**
85 * Overrides the <tt>ServiceTracker</tt> functionality to inform
86 * the application object about the removed service.
87 * @param ref The service reference of the removed service.
88 * @param svc The service object of the removed service.
89 **/
Richard S. Hall57376bf2012-03-06 19:19:04 +000090 @Override
Richard S. Hall3c1c0882012-03-13 17:32:01 +000091 public void removedService(ServiceReference<SimpleShape> ref, SimpleShape svc)
Richard S. Hallbad49dc2007-07-13 16:08:06 +000092 {
Richard S. Hall3c1c0882012-03-13 17:32:01 +000093 processShapeOnEventThread(ShapeEvent.REMOVED, ref, svc);
Richard S. Hallb0eb11c2007-07-25 18:57:27 +000094 ((DefaultShape) svc).dispose();
Richard S. Hallbad49dc2007-07-13 16:08:06 +000095 }
96
97 /**
98 * Processes a received service notification from the <tt>ServiceTracker</tt>,
99 * forcing the processing of the notification onto the Swing event thread
100 * if it is not already on it.
Richard S. Hall57376bf2012-03-06 19:19:04 +0000101 * @param event The type of action associated with the notification.
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000102 * @param ref The service reference of the corresponding service.
103 * @param shape The service object of the corresponding service.
104 **/
105 private void processShapeOnEventThread(
Richard S. Hall3c1c0882012-03-13 17:32:01 +0000106 ShapeEvent event, ServiceReference<SimpleShape> ref, SimpleShape shape)
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000107 {
108 try
109 {
110 if (SwingUtilities.isEventDispatchThread())
111 {
Richard S. Hall57376bf2012-03-06 19:19:04 +0000112 processShape(event, ref, shape);
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000113 }
114 else
115 {
Richard S. Hall57376bf2012-03-06 19:19:04 +0000116 SwingUtilities.invokeAndWait(new ShapeRunnable(event, ref, shape));
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000117 }
118 }
119 catch (Exception ex)
120 {
121 ex.printStackTrace();
122 }
123 }
124
125 /**
126 * Actually performs the processing of the service notification. Invokes
127 * the appropriate callback method on the application object depending on
128 * the action type of the notification.
Richard S. Hall57376bf2012-03-06 19:19:04 +0000129 * @param event The type of action associated with the notification.
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000130 * @param ref The service reference of the corresponding service.
131 * @param shape The service object of the corresponding service.
132 **/
Richard S. Hall3c1c0882012-03-13 17:32:01 +0000133 private void processShape(ShapeEvent event, ServiceReference<SimpleShape> ref, SimpleShape shape)
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000134 {
135 String name = (String) ref.getProperty(SimpleShape.NAME_PROPERTY);
136
Richard S. Hall57376bf2012-03-06 19:19:04 +0000137 switch (event)
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000138 {
139 case MODIFIED:
140 m_frame.removeShape(name);
141 // Purposely let this fall through to the 'add' case to
142 // reload the service.
143
144 case ADDED:
145 Icon icon = (Icon) ref.getProperty(SimpleShape.ICON_PROPERTY);
146 m_frame.addShape(name, icon, shape);
147 break;
148
149 case REMOVED:
150 m_frame.removeShape(name);
151 break;
152 }
153 }
154
155 /**
156 * Simple class used to process service notification handling on the
157 * Swing event thread.
158 **/
159 private class ShapeRunnable implements Runnable
160 {
Richard S. Hall57376bf2012-03-06 19:19:04 +0000161 private final ShapeEvent m_event;
Richard S. Hall3c1c0882012-03-13 17:32:01 +0000162 private final ServiceReference<SimpleShape> m_ref;
Richard S. Hall57376bf2012-03-06 19:19:04 +0000163 private final SimpleShape m_shape;
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000164
165 /**
166 * Constructs an object with the specified action, service reference,
167 * and service object for processing on the Swing event thread.
Richard S. Hall57376bf2012-03-06 19:19:04 +0000168 * @param event The type of action associated with the notification.
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000169 * @param ref The service reference of the corresponding service.
170 * @param shape The service object of the corresponding service.
171 **/
Richard S. Hall3c1c0882012-03-13 17:32:01 +0000172 public ShapeRunnable(ShapeEvent event, ServiceReference<SimpleShape> ref, SimpleShape shape)
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000173 {
Richard S. Hall57376bf2012-03-06 19:19:04 +0000174 m_event = event;
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000175 m_ref = ref;
176 m_shape = shape;
177 }
178
179 /**
180 * Calls the <tt>processShape()</tt> method.
181 **/
Richard S. Hall3c1c0882012-03-13 17:32:01 +0000182 @Override
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000183 public void run()
184 {
Richard S. Hall57376bf2012-03-06 19:19:04 +0000185 processShape(m_event, m_ref, m_shape);
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000186 }
187 }
Richard S. Hall57376bf2012-03-06 19:19:04 +0000188
189 private static enum ShapeEvent
190 {
191 ADDED,
192 MODIFIED,
193 REMOVED
194 }
Richard S. Hallbad49dc2007-07-13 16:08:06 +0000195}