View Javadoc

1   /*
2    * $Id$
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.osgi;
23  
24  import java.io.IOException;
25  import java.io.InputStream;
26  import java.net.URL;
27  import java.net.MalformedURLException;
28  import java.util.*;
29  import java.util.Map.Entry;
30  
31  import org.osgi.framework.Bundle;
32  import org.osgi.framework.BundleContext;
33  import org.osgi.framework.InvalidSyntaxException;
34  import org.osgi.framework.ServiceReference;
35  
36  import com.opensymphony.xwork2.util.logging.Logger;
37  import com.opensymphony.xwork2.util.logging.LoggerFactory;
38  import com.opensymphony.xwork2.ActionContext;
39  import com.opensymphony.xwork2.ActionInvocation;
40  import com.opensymphony.xwork2.ActionProxy;
41  import com.opensymphony.xwork2.inject.Inject;
42  import com.opensymphony.xwork2.config.entities.ActionConfig;
43  
44  /***
45   * Helper class that find resources and loads classes from the list of bundles
46   */
47  public class DefaultBundleAccessor implements BundleAccessor {
48  
49      private static DefaultBundleAccessor self;
50      private static final Logger LOG = LoggerFactory.getLogger(DefaultBundleAccessor.class);
51  
52      private BundleContext bundleContext;
53      private Map<String, String> packageToBundle = new HashMap<String, String>();
54      private Map<Bundle, Set<String>> packagesByBundle = new HashMap<Bundle, Set<String>>();
55      private OsgiHost osgiHost;
56  
57      public DefaultBundleAccessor() {
58          self = this;
59      }
60  
61      public static DefaultBundleAccessor getInstance() {
62          return self;
63      }
64  
65      public Object getService(ServiceReference ref) {
66          return bundleContext != null ? bundleContext.getService(ref) : null;
67      }
68  
69      public ServiceReference getServiceReference(String className) {
70          return bundleContext != null ? bundleContext.getServiceReference(className) : null;
71      }
72  
73      public ServiceReference[] getAllServiceReferences(String className) {
74          if (bundleContext != null) {
75              try {
76                  return bundleContext.getServiceReferences(className, null);
77              } catch (InvalidSyntaxException e) {
78                  //cannot happen we are passing null as the param
79                  if (LOG.isErrorEnabled())
80                      LOG.error("Invalid syntax for service lookup", e);
81              }
82          }
83  
84          return null;
85      }
86  
87      public ServiceReference[] getServiceReferences(String className, String params) throws InvalidSyntaxException {
88          return bundleContext != null ? bundleContext.getServiceReferences(className, params) : null;
89      }
90  
91      /***
92       *  Add as Bundle -> Package mapping 
93       * @param bundle the bundle where the package was loaded from
94       * @param packageName the anme of the loaded package
95       */
96      public void addPackageFromBundle(Bundle bundle, String packageName) {
97          this.packageToBundle.put(packageName, bundle.getSymbolicName());
98          Set<String> pkgs = packagesByBundle.get(bundle);
99          if (pkgs == null) {
100             pkgs = new HashSet<String>();
101             packagesByBundle.put(bundle, pkgs);
102         }
103         pkgs.add(packageName);
104     }
105 
106     public Class<?> loadClass(String className) throws ClassNotFoundException {
107         Bundle bundle = getCurrentBundle();
108         if (bundle != null) {
109             Class cls = bundle.loadClass(className);
110             if (LOG.isTraceEnabled())
111                 LOG.trace("Located class [#0] in bundle [#1]", className, bundle.getSymbolicName());
112             return cls;
113         }
114 
115         throw new ClassNotFoundException("Unable to find class " + className);
116     }
117 
118     private Bundle getCurrentBundle() {
119         ActionContext ctx = ActionContext.getContext();
120         String bundleName = (String) ctx.get(CURRENT_BUNDLE_NAME);
121         if (bundleName == null) {
122             ActionInvocation inv = ctx.getActionInvocation();
123             ActionProxy proxy = inv.getProxy();
124             ActionConfig actionConfig = proxy.getConfig();
125             bundleName = packageToBundle.get(actionConfig.getPackageName());
126         }
127         if (bundleName != null) {
128             return osgiHost.getActiveBundles().get(bundleName);
129         }
130         return null;
131     }
132 
133     public List<URL> loadResources(String name) throws IOException {
134         return loadResources(name, false);
135     }
136 
137     public List<URL> loadResources(String name, boolean translate) throws IOException {
138         Bundle bundle = getCurrentBundle();
139         if (bundle != null) {
140             List<URL> resources = new ArrayList<URL>();
141             Enumeration e = bundle.getResources(name);
142             while (e.hasMoreElements()) {
143                 resources.add(translate ? OsgiUtil.translateBundleURLToJarURL((URL) e.nextElement(), getCurrentBundle()) : (URL) e.nextElement());
144             }
145             return resources;
146         }
147 
148         return null;
149     }
150 
151     public URL loadResourceFromAllBundles(String name) throws IOException {
152         for (Map.Entry<String, Bundle> entry : osgiHost.getActiveBundles().entrySet()) {
153             Enumeration e = entry.getValue().getResources(name);
154             if (e.hasMoreElements()) {
155                 return (URL) e.nextElement();
156             }
157         }
158 
159         return null;
160     }
161 
162     public InputStream loadResourceFromAllBundlesAsStream(String name) throws IOException {
163         URL url = loadResourceFromAllBundles(name);
164         if (url != null) {
165             return url.openStream();
166         }
167         return null;
168     }
169 
170     public URL loadResource(String name) {
171         return loadResource(name, false);
172     }
173 
174     public URL loadResource(String name, boolean translate) {
175         Bundle bundle = getCurrentBundle();
176         if (bundle != null) {
177             URL url = bundle.getResource(name);
178             try {
179                 return translate ? OsgiUtil.translateBundleURLToJarURL(url, getCurrentBundle()) : url;
180             } catch (Exception e) {
181                 if (LOG.isErrorEnabled()) {
182                     LOG.error("Unable to translate bundle URL to jar URL", e);
183                 }
184 
185                 return null;
186             }
187         }
188 
189         return null;
190     }
191 
192     public Set<String> getPackagesByBundle(Bundle bundle) {
193         return packagesByBundle.get(bundle);
194     }
195 
196     public InputStream loadResourceAsStream(String name) throws IOException {
197         URL url = loadResource(name);
198         if (url != null) {
199             return url.openStream();
200         }
201         return null;
202     }
203 
204     public void setBundleContext(BundleContext bundleContext) {
205         this.bundleContext = bundleContext;
206     }
207 
208     public void setOsgiHost(OsgiHost osgiHost) {
209         this.osgiHost = osgiHost;
210     }
211 }