blob: ab41181e7f4aa45a8075cc25ac2a62a94dcefa1f [file] [log] [blame]
Felix Meschbergere7f513f2012-07-02 14:00:02 +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.cm.impl.helper;
20
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.Dictionary;
25import java.util.List;
26
27import org.apache.felix.cm.impl.CaseInsensitiveDictionary;
28import org.apache.felix.cm.impl.ConfigurationImpl;
29import org.apache.felix.cm.impl.ConfigurationManager;
30import org.apache.felix.cm.impl.RankingComparator;
31import org.osgi.framework.Constants;
32import org.osgi.framework.ServiceReference;
33import org.osgi.service.log.LogService;
34import org.osgi.util.tracker.ServiceTracker;
35
36/**
37 * The <code>BaseTracker</code> is the base class for tracking
38 * <code>ManagedService</code> and <code>ManagedServiceFactory</code>
39 * services. It maps their <code>ServiceRegistration</code> to the
40 * {@link ConfigurationMap} mapping their service PIDs to provided
41 * configuration.
42 */
43public abstract class BaseTracker<S> extends ServiceTracker<S, ConfigurationMap>
44{
45 protected final ConfigurationManager cm;
46
47
48 protected BaseTracker( ConfigurationManager cm, Class<S> type )
49 {
50 super( cm.getBundleContext(), type.getName(), null );
51 this.cm = cm;
52 open();
53 }
54
55
56 public ConfigurationMap addingService( ServiceReference<S> reference )
57 {
58 final String[] pids = getServicePid( reference );
59 configure( reference, pids );
60 return new ConfigurationMap( pids );
61 }
62
63
64 @Override
65 public void modifiedService( ServiceReference<S> reference, ConfigurationMap service )
66 {
67 String[] pids = getServicePid( reference );
68 if ( service.isDifferentPids( pids ) )
69 {
70 configure( reference, pids );
71 service.setConfiguredPids( pids );
72 }
73 }
74
75
76// public void removedService( ServiceReference<ManagedServiceFactory> reference,
77// ServiceHolder<ManagedServiceFactory> holder )
78// {
79// // nothing really to do
80// }
81
82
83 // cm.configure( pids, reference, msf);
84 protected void configure( ServiceReference<S> reference, String[] pids )
85 {
86 if ( pids != null )
87 {
88 S service = getRealService( reference );
89 if ( service != null )
90 {
91 try
92 {
93 if ( this.cm.isLogEnabled( LogService.LOG_DEBUG ) )
94 {
95 this.cm.log( LogService.LOG_DEBUG, "configure(ManagedService {0})", new Object[]
96 { ConfigurationManager.toString( reference ) } );
97 }
98
99 for ( int i = 0; i < pids.length; i++ )
100 {
101 this.cm.configure( pids[i], reference, service, isFactory() );
102 }
103 }
104 finally
105 {
106 ungetRealService( reference );
107 }
108 }
109 }
110 }
111
112
113 public final List<ServiceReference<S>> getServices( final TargetedPID pid )
114 {
115 ServiceReference<S>[] refs = this.getServiceReferences();
116 if ( refs != null )
117 {
118 ArrayList<ServiceReference<S>> result = new ArrayList<ServiceReference<S>>( refs.length );
119 for ( ServiceReference<S> ref : refs )
120 {
121 if ( pid.matchesTarget( ref ) )
122 {
123 ConfigurationMap map = this.getService( ref );
124 if ( map != null && map.accepts( pid.getServicePid() ) )
125 {
126 result.add( ref );
127 }
128 }
129 }
130
131 if ( result.size() > 1 )
132 {
133 Collections.sort( result, RankingComparator.SRV_RANKING );
134 }
135
136 return result;
137 }
138
139 return Collections.emptyList();
140 }
141
142
143 protected abstract boolean isFactory();
144
145 // Updates
Felix Meschbergeraccd9012012-07-02 15:18:08 +0000146 public abstract void provideConfiguration( ServiceReference<S> service, ConfigurationImpl config, Dictionary<String, ?> properties );
Felix Meschbergere7f513f2012-07-02 14:00:02 +0000147
148
Felix Meschbergeraccd9012012-07-02 15:18:08 +0000149 public abstract void removeConfiguration( ServiceReference<S> service, ConfigurationImpl config );
Felix Meschbergere7f513f2012-07-02 14:00:02 +0000150
151
152 protected final S getRealService( ServiceReference<S> reference )
153 {
154 return this.context.getService( reference );
155 }
156
157
158 protected final void ungetRealService( ServiceReference<S> reference )
159 {
160 this.context.ungetService( reference );
161 }
162
163 protected final Dictionary getProperties( Dictionary<String, ?> rawProperties, String targetPid, ServiceReference service )
164 {
165 Dictionary props = new CaseInsensitiveDictionary( rawProperties );
166 this.cm.callPlugins( props, targetPid, service, null /* config */ );
167 return props;
168 }
169
170 /**
171 * Returns the <code>service.pid</code> property of the service reference as
172 * an array of strings or <code>null</code> if the service reference does
173 * not have a service PID property.
174 * <p>
175 * The service.pid property may be a single string, in which case a single
176 * element array is returned. If the property is an array of string, this
177 * array is returned. If the property is a collection it is assumed to be a
178 * collection of strings and the collection is converted to an array to be
179 * returned. Otherwise (also if the property is not set) <code>null</code>
180 * is returned.
181 *
182 * @throws NullPointerException
183 * if reference is <code>null</code>
184 * @throws ArrayStoreException
185 * if the service pid is a collection and not all elements are
186 * strings.
187 */
188 private static String[] getServicePid( ServiceReference reference )
189 {
190 Object pidObj = reference.getProperty( Constants.SERVICE_PID );
191 if ( pidObj instanceof String )
192 {
193 return new String[]
194 { ( String ) pidObj };
195 }
196 else if ( pidObj instanceof String[] )
197 {
198 return ( String[] ) pidObj;
199 }
200 else if ( pidObj instanceof Collection )
201 {
202 Collection pidCollection = ( Collection ) pidObj;
203 return ( String[] ) pidCollection.toArray( new String[pidCollection.size()] );
204 }
205
206 return null;
207 }
208
209}