blob: 7f7d73d9e29e579b016ec71ba4b934449420654b [file] [log] [blame]
Felix Meschbergerefb2d082008-08-19 13:18:47 +00001/*
Richard S. Hall59aef192009-04-25 14:50:37 +00002 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Felix Meschbergerefb2d082008-08-19 13:18:47 +000017package org.apache.felix.shell.remote;
18
Felix Meschbergerefb2d082008-08-19 13:18:47 +000019import org.apache.felix.shell.ShellService;
Felix Meschbergerd7c324d2008-08-19 14:10:48 +000020import org.osgi.framework.Bundle;
21import org.osgi.framework.BundleContext;
22import org.osgi.framework.Constants;
23import org.osgi.framework.InvalidSyntaxException;
24import org.osgi.framework.ServiceEvent;
25import org.osgi.framework.ServiceListener;
26import org.osgi.framework.ServiceReference;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000027import org.osgi.service.log.LogService;
28
Felix Meschbergerefb2d082008-08-19 13:18:47 +000029/**
30 * Implements a mediator pattern class for services from the OSGi container.
Felix Meschbergerefb2d082008-08-19 13:18:47 +000031 */
32class ServiceMediator
33{
Richard S. Hall59aef192009-04-25 14:50:37 +000034 private BundleContext m_bundleContext;
35 private ShellService m_felixShellService;
36 private Latch m_felixShellServiceLatch;
37 private LogService m_logService;
38 private Latch m_logServiceLatch;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000039
40 /**
41 * Returns a reference to the <tt>ShellService</tt> (Felix).
42 *
43 * @param wait time in milliseconds to wait for the reference if it isn't available.
44 * @return the reference to the <tt>ShellService</tt> as obtained from the OSGi service layer.
45 */
Richard S. Hall59aef192009-04-25 14:50:37 +000046 public ShellService getFelixShellService(long wait)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000047 {
48 try
49 {
Richard S. Hall59aef192009-04-25 14:50:37 +000050 if (wait < 0)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000051 {
Richard S. Hall59aef192009-04-25 14:50:37 +000052 m_felixShellServiceLatch.acquire();
Felix Meschbergerefb2d082008-08-19 13:18:47 +000053 }
Richard S. Hall59aef192009-04-25 14:50:37 +000054 else if (wait > 0)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000055 {
Richard S. Hall59aef192009-04-25 14:50:37 +000056 m_felixShellServiceLatch.attempt(wait);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000057 }
58 }
Richard S. Hall59aef192009-04-25 14:50:37 +000059 catch (InterruptedException e)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000060 {
Richard S. Hall59aef192009-04-25 14:50:37 +000061 e.printStackTrace(System.err);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000062 }
63
Richard S. Hall59aef192009-04-25 14:50:37 +000064 return m_felixShellService;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000065 }//getFelixShellService
66
Richard S. Hall59aef192009-04-25 14:50:37 +000067 public LogService getLogServiceLatch(long wait)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000068 {
69 try
70 {
Richard S. Hall59aef192009-04-25 14:50:37 +000071 if (wait < 0)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000072 {
Richard S. Hall59aef192009-04-25 14:50:37 +000073 m_logServiceLatch.acquire();
Felix Meschbergerefb2d082008-08-19 13:18:47 +000074 }
Richard S. Hall59aef192009-04-25 14:50:37 +000075 else if (wait > 0)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000076 {
Richard S. Hall59aef192009-04-25 14:50:37 +000077 m_logServiceLatch.attempt(wait);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000078 }
79 }
Richard S. Hall59aef192009-04-25 14:50:37 +000080 catch (InterruptedException e)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000081 {
Richard S. Hall59aef192009-04-25 14:50:37 +000082 e.printStackTrace(System.err);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000083 }
Richard S. Hall59aef192009-04-25 14:50:37 +000084 return m_logService;
Felix Meschbergerefb2d082008-08-19 13:18:47 +000085 }//getLogService
86
Richard S. Hall59aef192009-04-25 14:50:37 +000087 public void info(String msg)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000088 {
Richard S. Hall59aef192009-04-25 14:50:37 +000089 if (m_logService != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +000090 {
Richard S. Hall59aef192009-04-25 14:50:37 +000091 m_logService.log(LogService.LOG_INFO, msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000092 }
93 else
94 {
Richard S. Hall59aef192009-04-25 14:50:37 +000095 sysout(msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +000096 }
97 }//info
98
Richard S. Hall59aef192009-04-25 14:50:37 +000099 public void error(String msg, Throwable t)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000100 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000101 if (m_logService != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000102 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000103 m_logService.log(LogService.LOG_ERROR, msg, t);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000104 }
105 else
106 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000107 syserr(msg, t);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000108 }
109 }//error
110
Richard S. Hall59aef192009-04-25 14:50:37 +0000111 public void error(String msg)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000112 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000113 if (m_logService != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000114 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000115 m_logService.log(LogService.LOG_ERROR, msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000116 }
117 else
118 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000119 syserr(msg, null);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000120 }
121 }//error
122
Richard S. Hall59aef192009-04-25 14:50:37 +0000123 public void debug(String msg)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000124 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000125 if (m_logService != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000126 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000127 m_logService.log(LogService.LOG_DEBUG, msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000128 }
129 else
130 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000131 sysout(msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000132 }
133 }//debug
134
Richard S. Hall59aef192009-04-25 14:50:37 +0000135 public void warn(String msg)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000136 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000137 if (m_logService != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000138 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000139 m_logService.log(LogService.LOG_WARNING, msg);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000140 }
141 else
142 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000143 syserr(msg, null);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000144 }
145 }//warn
146
Richard S. Hall59aef192009-04-25 14:50:37 +0000147 private void sysout(String msg)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000148 {
149 //Assemble String
150 StringBuffer sbuf = new StringBuffer();
Richard S. Hall59aef192009-04-25 14:50:37 +0000151 Bundle b = m_bundleContext.getBundle();
152 sbuf.append(b.getHeaders().get(Constants.BUNDLE_NAME));
153 sbuf.append(" [");
154 sbuf.append(b.getBundleId());
155 sbuf.append("] ");
156 sbuf.append(msg);
157 System.out.println(sbuf.toString());
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000158 }//sysout
159
Richard S. Hall59aef192009-04-25 14:50:37 +0000160 private void syserr(String msg, Throwable t)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000161 {
162 //Assemble String
163 StringBuffer sbuf = new StringBuffer();
Richard S. Hall59aef192009-04-25 14:50:37 +0000164 Bundle b = m_bundleContext.getBundle();
165 sbuf.append(b.getHeaders().get(Constants.BUNDLE_NAME));
166 sbuf.append(" [");
167 sbuf.append(b.getBundleId());
168 sbuf.append("] ");
169 sbuf.append(msg);
170 System.err.println(sbuf.toString());
171 if (t != null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000172 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000173 t.printStackTrace(System.err);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000174 }
175 }//logToSystem
176
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000177 /**
178 * Activates this mediator to start tracking the required services using the
179 * OSGi service layer.
180 *
181 * @param bc the bundle's context.
182 * @return true if activated successfully, false otherwise.
183 */
Richard S. Hall59aef192009-04-25 14:50:37 +0000184 public boolean activate(BundleContext bc)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000185 {
186 //get the context
Richard S. Hall59aef192009-04-25 14:50:37 +0000187 m_bundleContext = bc;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000188
Richard S. Hall59aef192009-04-25 14:50:37 +0000189 m_felixShellServiceLatch = createWaitLatch();
190 m_logServiceLatch = createWaitLatch();
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000191
192 //prepareDefinitions listener
193 ServiceListener serviceListener = new ServiceListenerImpl();
194
Felix Meschbergerf543f372008-09-10 19:33:25 +0000195 //prepareDefinitions the filter, ShellService is required,
196 //LogService may be missing, in which case we only use the
197 // ShellService part of the filter
198 String filter = "(objectclass=" + ShellService.class.getName() + ")";
199 try
200 {
201 filter = "(|" + filter + "(objectclass=" + LogService.class.getName() + "))";
202 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000203 catch (Throwable t)
Felix Meschbergerf543f372008-09-10 19:33:25 +0000204 {
205 // ignore
206 }
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000207
208 try
209 {
210 //add the listener to the bundle context.
Richard S. Hall59aef192009-04-25 14:50:37 +0000211 bc.addServiceListener(serviceListener, filter);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000212
213 //ensure that already registered Service instances are registered with
214 //the manager
Richard S. Hall59aef192009-04-25 14:50:37 +0000215 ServiceReference[] srl = bc.getServiceReferences(null, filter);
216 for (int i = 0; srl != null && i < srl.length; i++)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000217 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000218 serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, srl[i]));
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000219 }
220 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000221 catch (InvalidSyntaxException ex)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000222 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000223 ex.printStackTrace(System.err);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000224 return false;
225 }
226 return true;
227 }//activate
228
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000229 /**
230 * Deactivates this mediator, nulling out all references.
231 * If called when the bundle is stopped, the framework should actually take
232 * care of unregistering the <tt>ServiceListener</tt>.
233 */
234 public void deactivate()
235 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000236 m_felixShellService = null;
237 m_felixShellServiceLatch = null;
238 m_bundleContext = null;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000239 }//deactivate
240
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000241 /**
242 * Creates a simple wait latch to be used for the mechanism that allows entities
243 * in the bundles to wait for references.
244 *
245 * @return a new Latch instance.
246 */
247 private Latch createWaitLatch()
248 {
249 return new Latch();
250 }//createWaitLatch
251
252 /**
253 * The <tt>ServiceListener</tt> implementation.
254 */
255 private class ServiceListenerImpl implements ServiceListener
256 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000257 public void serviceChanged(ServiceEvent ev)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000258 {
259 ServiceReference sr = ev.getServiceReference();
260 Object o = null;
Richard S. Hall59aef192009-04-25 14:50:37 +0000261 switch (ev.getType())
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000262 {
263 case ServiceEvent.REGISTERED:
Richard S. Hall59aef192009-04-25 14:50:37 +0000264 o = m_bundleContext.getService(sr);
265 if (o == null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000266 {
267 return;
268 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000269 else if (o instanceof ShellService)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000270 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000271 m_felixShellService = (ShellService) o;
272 m_felixShellServiceLatch.release();
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000273 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000274 else if (o instanceof LogService)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000275 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000276 m_logService = (LogService) o;
277 m_logServiceLatch.release();
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000278 }
279 else
280 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000281 m_bundleContext.ungetService(sr);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000282 }
283 break;
284 case ServiceEvent.UNREGISTERING:
Richard S. Hall59aef192009-04-25 14:50:37 +0000285 o = m_bundleContext.getService(sr);
286 if (o == null)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000287 {
288 return;
289 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000290 else if (o instanceof ShellService)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000291 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000292 m_felixShellService = null;
293 m_felixShellServiceLatch = createWaitLatch();
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000294 }
Richard S. Hall59aef192009-04-25 14:50:37 +0000295 else if (o instanceof LogService)
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000296 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000297 m_logService = null;
298 m_logServiceLatch = createWaitLatch();
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000299 }
300 else
301 {
Richard S. Hall59aef192009-04-25 14:50:37 +0000302 m_bundleContext.ungetService(sr);
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000303 }
304 break;
305 }
306 }
307 }//inner class ServiceListenerImpl
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000308 public static long WAIT_UNLIMITED = -1;
309 public static long NO_WAIT = 0;
Felix Meschbergerefb2d082008-08-19 13:18:47 +0000310}//class ServiceMediator