View Javadoc

1   /*
2    * Copyright 2006-2009 the original author or authors.
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  
17  package org.springframework.osgi.extender.internal.dependencies.startup;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  import java.util.concurrent.atomic.AtomicInteger;
22  import java.util.regex.Matcher;
23  import java.util.regex.Pattern;
24  
25  import org.osgi.framework.BundleContext;
26  import org.osgi.framework.Filter;
27  import org.osgi.framework.InvalidSyntaxException;
28  import org.osgi.framework.ServiceEvent;
29  import org.springframework.osgi.service.importer.DefaultOsgiServiceDependency;
30  import org.springframework.osgi.service.importer.OsgiServiceDependency;
31  import org.springframework.osgi.util.OsgiServiceReferenceUtils;
32  import org.springframework.util.ObjectUtils;
33  
34  /**
35   * Holder/helper class representing an OSGi service dependency
36   * 
37   * @author Costin Leau
38   * @author Hal Hildebrand
39   * @author Andy Piper
40   */
41  class MandatoryServiceDependency implements OsgiServiceDependency {
42  	// match the class inside object class (and use a non backing reference group)
43  	private static final Pattern PATTERN = Pattern.compile("objectClass=(?:[^\\)]+)");
44  
45  	protected final BundleContext bundleContext;
46  
47  	private OsgiServiceDependency serviceDependency;
48  	private final AtomicInteger matchingServices = new AtomicInteger(0);
49  	protected final String filterAsString;
50  	private final String[] classes;
51  
52  	MandatoryServiceDependency(BundleContext bc, Filter serviceFilter, boolean isMandatory, String beanName) {
53  		this(bc, new DefaultOsgiServiceDependency(beanName, serviceFilter, isMandatory));
54  	}
55  
56  	MandatoryServiceDependency(BundleContext bc, OsgiServiceDependency dependency) {
57  		bundleContext = bc;
58  		serviceDependency = dependency;
59  		this.filterAsString = dependency.getServiceFilter().toString();
60  		this.classes = extractObjectClassFromFilter(filterAsString);
61  	}
62  
63  	boolean matches(ServiceEvent event) {
64  		return serviceDependency.getServiceFilter().match(event.getServiceReference());
65  	}
66  
67  	boolean isServicePresent() {
68  		return (!serviceDependency.isMandatory() || OsgiServiceReferenceUtils.isServicePresent(bundleContext,
69  				filterAsString));
70  	}
71  
72  	public String toString() {
73  		return "Dependency on [" + filterAsString + "] (from bean [" + serviceDependency.getBeanName() + "])";
74  	}
75  
76  	public Filter getServiceFilter() {
77  		return serviceDependency.getServiceFilter();
78  	}
79  
80  	public String getBeanName() {
81  		return serviceDependency.getBeanName();
82  	}
83  
84  	public boolean isMandatory() {
85  		return serviceDependency.isMandatory();
86  	}
87  
88  	public boolean equals(Object o) {
89  		if (this == o)
90  			return true;
91  		if (o == null || getClass() != o.getClass())
92  			return false;
93  
94  		final MandatoryServiceDependency that = (MandatoryServiceDependency) o;
95  
96  		return (serviceDependency.equals(that.serviceDependency));
97  	}
98  
99  	public int hashCode() {
100 		int result = MandatoryServiceDependency.class.hashCode();
101 		result = 29 * result + serviceDependency.hashCode();
102 		return result;
103 	}
104 
105 	public OsgiServiceDependency getServiceDependency() {
106 		return serviceDependency;
107 	}
108 
109 	/**
110 	 * Adds another matching service.
111 	 * 
112 	 * @return the counter after adding the service.
113 	 */
114 	int increment() {
115 		return matchingServices.incrementAndGet();
116 	}
117 
118 	/**
119 	 * Removes a matching service.
120 	 * 
121 	 * @return the counter after substracting the service.
122 	 */
123 	int decrement() {
124 		return matchingServices.decrementAndGet();
125 	}
126 
127 	private static String[] extractObjectClassFromFilter(String filterString) {
128 		List<String> matches = null;
129 		Matcher matcher = PATTERN.matcher(filterString);
130 		while (matcher.find()) {
131 			if (matches == null) {
132 				matches = new ArrayList<String>(4);
133 			}
134 
135 			matches.add(matcher.group());
136 		}
137 
138 		return (matches == null ? new String[0] : matches.toArray(new String[matches.size()]));
139 	}
140 }