blob: 504552e9417ac346a2fab9db5fdfed78d138b279 [file] [log] [blame]
Pierre De Rop19476fe2010-05-23 08:13:58 +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.dm.impl;
20
21import java.util.ArrayList;
22import java.util.Enumeration;
23import java.util.List;
24import java.util.Properties;
25
Marcel Offermansa8818d52011-03-09 10:03:35 +000026import org.apache.felix.dm.Component;
27import org.apache.felix.dm.ComponentStateListener;
Marcel Offermans8b93efa2010-07-02 18:27:21 +000028import org.apache.felix.dm.Dependency;
Pierre De Rop19476fe2010-05-23 08:13:58 +000029import org.apache.felix.dm.DependencyManager;
Marcel Offermans8b93efa2010-07-02 18:27:21 +000030import org.apache.felix.dm.ServiceDependency;
Pierre De Rop19476fe2010-05-23 08:13:58 +000031import org.osgi.framework.Constants;
32import org.osgi.framework.ServiceReference;
33
34/**
35 * Aspect Service implementation. This class extends the FilterService in order to catch
36 * some Service methods for configuring actual aspect service implementation.
Marcel Offermans5be5f142011-04-26 10:47:12 +000037 *
38 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
Pierre De Rop19476fe2010-05-23 08:13:58 +000039 */
Marcel Offermans129a7a52010-08-20 12:18:59 +000040public class AspectServiceImpl extends FilterService {
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000041 public AspectServiceImpl(DependencyManager dm, Class aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove, String swap)
Pierre De Rop19476fe2010-05-23 08:13:58 +000042 {
Marcel Offermansfaaed472010-09-08 10:07:32 +000043 super(dm.createComponent()); // This service will be filtered by our super class, allowing us to take control.
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000044 m_component.setImplementation(new AspectImpl(aspectInterface, aspectFilter, ranking, autoConfig, add, change, remove, swap))
Marcel Offermans129a7a52010-08-20 12:18:59 +000045 .add(dm.createServiceDependency()
46 .setService(aspectInterface, createDependencyFilterForAspect(aspectFilter))
47 .setAutoConfig(false)
48 .setCallbacks("added", "removed"));
Pierre De Rop19476fe2010-05-23 08:13:58 +000049 }
50
Marcel Offermans129a7a52010-08-20 12:18:59 +000051 private String createDependencyFilterForAspect(String filter) {
Pierre De Rop19476fe2010-05-23 08:13:58 +000052 // we only want to match services which are not themselves aspects
53 if (filter == null || filter.length() == 0) {
54 return "(!(" + DependencyManager.ASPECT + "=*))";
55 }
56 else {
57 return "(&(!(" + DependencyManager.ASPECT + "=*))" + filter + ")";
58 }
59 }
60
61 /**
62 * This class is the Aspect Implementation. It will create the actual Aspect Service, and
63 * will use the Aspect Service parameters provided by our enclosing class.
64 */
65 class AspectImpl extends AbstractDecorator {
66 private final Class m_aspectInterface; // the service decorated by this aspect
67 private final String m_aspectFilter; // the service filter decorated by this aspect
68 private final int m_ranking; // the aspect ranking
Marcel Offermansa8818d52011-03-09 10:03:35 +000069 private final String m_autoConfig; // the aspect impl field name where to inject decorated service
70 private final String m_add;
71 private final String m_change;
72 private final String m_remove;
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000073 private final String m_swap;
Pierre De Rop19476fe2010-05-23 08:13:58 +000074
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000075 public AspectImpl(Class aspectInterface, String aspectFilter, int ranking, String autoConfig, String add, String change, String remove, String swap) {
Pierre De Rop19476fe2010-05-23 08:13:58 +000076 m_aspectInterface = aspectInterface;
77 m_aspectFilter = aspectFilter;
78 m_ranking = ranking;
Marcel Offermansa8818d52011-03-09 10:03:35 +000079 m_autoConfig = autoConfig;
80 m_add = add;
81 m_change = change;
82 m_remove = remove;
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000083 m_swap = swap;
Pierre De Rop19476fe2010-05-23 08:13:58 +000084 }
85
Marcel Offermansfaaed472010-09-08 10:07:32 +000086 public Component createService(Object[] params) {
Marcel Offermans66df0b82011-04-27 21:48:41 +000087 List dependencies = m_component.getDependencies();
Pierre De Rop19476fe2010-05-23 08:13:58 +000088 // remove our internal dependency
89 dependencies.remove(0);
Marcel Offermans129a7a52010-08-20 12:18:59 +000090 // replace it with one that points to the specific service that just was passed in
Pierre De Rop19476fe2010-05-23 08:13:58 +000091 Properties serviceProperties = getServiceProperties(params);
92 String[] serviceInterfaces = getServiceInterfaces();
Marcel Offermansa8818d52011-03-09 10:03:35 +000093 ServiceReference ref = (ServiceReference) params[0];
94 ServiceDependency dependency = m_manager.createServiceDependency().setService(m_aspectInterface, createAspectFilter(ref)).setRequired(true);
95 if (m_autoConfig != null) {
96 dependency.setAutoConfig(m_autoConfig);
97 }
Xander Uiterlindenb64a8e22012-04-03 14:42:23 +000098 if (m_add != null || m_change != null || m_remove != null || m_swap != null) {
99 dependency.setCallbacks(m_add, m_change, m_remove, m_swap);
Marcel Offermansa8818d52011-03-09 10:03:35 +0000100 }
Marcel Offermansfaaed472010-09-08 10:07:32 +0000101 Component service = m_manager.createComponent()
Pierre De Rop19476fe2010-05-23 08:13:58 +0000102 .setInterface(serviceInterfaces, serviceProperties)
103 .setImplementation(m_serviceImpl)
104 .setFactory(m_factory, m_factoryCreateMethod) // if not set, no effect
105 .setComposition(m_compositionInstance, m_compositionMethod) // if not set, no effect
106 .setCallbacks(m_callbackObject, m_init, m_start, m_stop, m_destroy) // if not set, no effect
Marcel Offermansa8818d52011-03-09 10:03:35 +0000107 .add(dependency);
Marcel Offermansb1959f42010-07-01 12:23:51 +0000108
Marcel Offermans66df0b82011-04-27 21:48:41 +0000109 configureAutoConfigState(service, m_component);
Marcel Offermans3d921212010-08-09 13:37:02 +0000110
Marcel Offermanse9c13d92010-07-01 14:01:02 +0000111 for (int i = 0; i < dependencies.size(); i++) {
112 service.add(((Dependency) dependencies.get(i)).createCopy());
Marcel Offermansb1959f42010-07-01 12:23:51 +0000113 }
114
Marcel Offermans129a7a52010-08-20 12:18:59 +0000115 for (int i = 0; i < m_stateListeners.size(); i++) {
Marcel Offermansfaaed472010-09-08 10:07:32 +0000116 service.addStateListener((ComponentStateListener) m_stateListeners.get(i));
Pierre De Rop19476fe2010-05-23 08:13:58 +0000117 }
118 return service;
119 }
120
121 private Properties getServiceProperties(Object[] params) {
122 ServiceReference ref = (ServiceReference) params[0];
Pierre De Rop19476fe2010-05-23 08:13:58 +0000123 Properties props = new Properties();
Pierre De Rop19476fe2010-05-23 08:13:58 +0000124 String[] keys = ref.getPropertyKeys();
125 for (int i = 0; i < keys.length; i++) {
Marcel Offermans129a7a52010-08-20 12:18:59 +0000126 String key = keys[i];
127 if (key.equals(Constants.SERVICE_ID) || key.equals(Constants.SERVICE_RANKING) || key.equals(DependencyManager.ASPECT) || key.equals(Constants.OBJECTCLASS)) {
128 // do not copy these
129 }
130 else {
131 props.put(key, ref.getProperty(key));
132 }
Pierre De Rop19476fe2010-05-23 08:13:58 +0000133 }
134 if (m_serviceProperties != null) {
135 Enumeration e = m_serviceProperties.keys();
136 while (e.hasMoreElements()) {
137 Object key = e.nextElement();
138 props.put(key, m_serviceProperties.get(key));
139 }
140 }
Marcel Offermans129a7a52010-08-20 12:18:59 +0000141 // finally add our aspect property
142 props.put(DependencyManager.ASPECT, ref.getProperty(Constants.SERVICE_ID));
143 // and the ranking
144 props.put(Constants.SERVICE_RANKING, Integer.valueOf(m_ranking));
Pierre De Rop19476fe2010-05-23 08:13:58 +0000145 return props;
146 }
147
Marcel Offermans129a7a52010-08-20 12:18:59 +0000148 private String[] getServiceInterfaces() {
Pierre De Rop19476fe2010-05-23 08:13:58 +0000149 List serviceNames = new ArrayList();
150 // Of course, we provide the aspect interface.
151 serviceNames.add(m_aspectInterface.getName());
152 // But also append additional aspect implementation interfaces.
153 if (m_serviceInterfaces != null) {
154 for (int i = 0; i < m_serviceInterfaces.length; i ++) {
Marcel Offermans129a7a52010-08-20 12:18:59 +0000155 if (!m_serviceInterfaces[i].equals(m_aspectInterface.getName())) {
Pierre De Rop19476fe2010-05-23 08:13:58 +0000156 serviceNames.add(m_serviceInterfaces[i]);
157 }
158 }
159 }
160 return (String[]) serviceNames.toArray(new String[serviceNames.size()]);
161 }
162
Marcel Offermans129a7a52010-08-20 12:18:59 +0000163 private String createAspectFilter(ServiceReference ref) {
164 Long sid = (Long) ref.getProperty(Constants.SERVICE_ID);
165 return "(&(|(!(" + Constants.SERVICE_RANKING + "=*))(" + Constants.SERVICE_RANKING + "<=" + (m_ranking - 1) + "))(|(" + Constants.SERVICE_ID + "=" + sid + ")(" + DependencyManager.ASPECT + "=" + sid + ")))";
166 }
Pierre De Rop19476fe2010-05-23 08:13:58 +0000167 }
168}