| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.struts2.osgi; |
| |
| import com.opensymphony.xwork2.ActionContext; |
| import com.opensymphony.xwork2.ActionInvocation; |
| import com.opensymphony.xwork2.ActionProxy; |
| import com.opensymphony.xwork2.config.entities.ActionConfig; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.struts2.osgi.host.OsgiHost; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Helper class that find resources and loads classes from the list of bundles |
| */ |
| public class DefaultBundleAccessor implements BundleAccessor { |
| |
| private static DefaultBundleAccessor self; |
| private static final Logger LOG = LogManager.getLogger(DefaultBundleAccessor.class); |
| |
| private BundleContext bundleContext; |
| private Map<String, String> packageToBundle = new HashMap<>(); |
| private Map<Bundle, Set<String>> packagesByBundle = new HashMap<>(); |
| private OsgiHost osgiHost; |
| |
| public DefaultBundleAccessor() { |
| self = this; |
| } |
| |
| public static DefaultBundleAccessor getInstance() { |
| return self; |
| } |
| |
| public Object getService(ServiceReference ref) { |
| return bundleContext != null ? bundleContext.getService(ref) : null; |
| } |
| |
| public ServiceReference getServiceReference(String className) { |
| return bundleContext != null ? bundleContext.getServiceReference(className) : null; |
| } |
| |
| public ServiceReference[] getAllServiceReferences(String className) { |
| if (bundleContext != null) { |
| try { |
| return bundleContext.getServiceReferences(className, null); |
| } catch (InvalidSyntaxException e) { |
| //cannot happen we are passing null as the param |
| if (LOG.isErrorEnabled()) { |
| LOG.error("Invalid syntax for service lookup", e); |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| public ServiceReference[] getServiceReferences(String className, String params) throws InvalidSyntaxException { |
| return bundleContext != null ? bundleContext.getServiceReferences(className, params) : null; |
| } |
| |
| /** |
| * Add as Bundle -> Package mapping |
| * @param bundle the bundle where the package was loaded from |
| * @param packageName the anme of the loaded package |
| */ |
| public void addPackageFromBundle(Bundle bundle, String packageName) { |
| this.packageToBundle.put(packageName, bundle.getSymbolicName()); |
| Set<String> pkgs = packagesByBundle.get(bundle); |
| if (pkgs == null) { |
| pkgs = new HashSet<>(); |
| packagesByBundle.put(bundle, pkgs); |
| } |
| pkgs.add(packageName); |
| } |
| |
| public Class<?> loadClass(String className) throws ClassNotFoundException { |
| Bundle bundle = getCurrentBundle(); |
| if (bundle != null) { |
| Class cls = bundle.loadClass(className); |
| LOG.trace("Located class [{}] in bundle [{}]", className, bundle.getSymbolicName()); |
| return cls; |
| } |
| |
| throw new ClassNotFoundException("Unable to find class " + className); |
| } |
| |
| private Bundle getCurrentBundle() { |
| ActionContext ctx = ActionContext.getContext(); |
| String bundleName = (String) ctx.get(CURRENT_BUNDLE_NAME); |
| if (bundleName == null) { |
| ActionInvocation inv = ctx.getActionInvocation(); |
| ActionProxy proxy = inv.getProxy(); |
| ActionConfig actionConfig = proxy.getConfig(); |
| bundleName = packageToBundle.get(actionConfig.getPackageName()); |
| } |
| if (bundleName != null) { |
| return osgiHost.getActiveBundles().get(bundleName); |
| } |
| return null; |
| } |
| |
| public List<URL> loadResources(String name) throws IOException { |
| return loadResources(name, false); |
| } |
| |
| public List<URL> loadResources(String name, boolean translate) throws IOException { |
| Bundle bundle = getCurrentBundle(); |
| if (bundle != null) { |
| List<URL> resources = new ArrayList<>(); |
| Enumeration e = bundle.getResources(name); |
| if (e != null) { |
| while (e.hasMoreElements()) { |
| resources.add(translate ? OsgiUtil.translateBundleURLToJarURL((URL) e.nextElement(), getCurrentBundle()) : (URL) e.nextElement()); |
| } |
| } |
| return resources; |
| } |
| |
| return null; |
| } |
| |
| public URL loadResourceFromAllBundles(String name) throws IOException { |
| for (Map.Entry<String, Bundle> entry : osgiHost.getActiveBundles().entrySet()) { |
| Enumeration e = entry.getValue().getResources(name); |
| if (e != null && e.hasMoreElements()) { |
| return (URL) e.nextElement(); |
| } |
| } |
| |
| return null; |
| } |
| |
| public InputStream loadResourceFromAllBundlesAsStream(String name) throws IOException { |
| URL url = loadResourceFromAllBundles(name); |
| if (url != null) { |
| return url.openStream(); |
| } |
| return null; |
| } |
| |
| public URL loadResource(String name) { |
| return loadResource(name, false); |
| } |
| |
| public URL loadResource(String name, boolean translate) { |
| Bundle bundle = getCurrentBundle(); |
| if (bundle != null) { |
| URL url = bundle.getResource(name); |
| try { |
| return translate ? OsgiUtil.translateBundleURLToJarURL(url, getCurrentBundle()) : url; |
| } catch (Exception e) { |
| if (LOG.isErrorEnabled()) { |
| LOG.error("Unable to translate bundle URL to jar URL", e); |
| } |
| |
| return null; |
| } |
| } |
| |
| return null; |
| } |
| |
| public Set<String> getPackagesByBundle(Bundle bundle) { |
| return packagesByBundle.get(bundle); |
| } |
| |
| public InputStream loadResourceAsStream(String name) throws IOException { |
| URL url = loadResource(name); |
| if (url != null) { |
| return url.openStream(); |
| } |
| return null; |
| } |
| |
| public void setBundleContext(BundleContext bundleContext) { |
| this.bundleContext = bundleContext; |
| } |
| |
| public void setOsgiHost(OsgiHost osgiHost) { |
| this.osgiHost = osgiHost; |
| } |
| |
| } |