alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Struts example source code file (FelixOsgiHost.java)

This example Struts source code file (FelixOsgiHost.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Struts tags/keywords

arraylist, bundle, bundle, exception, felix, io, jar, list, list, map, map, network, properties, regex, resourcefinder, security, string, string, unable, util

The Struts FelixOsgiHost.java source code

/*
 * $Id$
 *
 * 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.config.ConfigurationException;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.URLUtil;
import com.opensymphony.xwork2.util.finder.ResourceFinder;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.ActionContext;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.framework.Felix;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.main.AutoActivator;
import org.apache.felix.main.Main;
import org.apache.felix.shell.ShellService;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsException;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.Constants;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleListener;
import org.osgi.framework.BundleEvent;
import org.osgi.util.tracker.ServiceTracker;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Apache felix implementation of an OsgiHost
 * See http://felix.apache.org/site/apache-felix-framework-launching-and-embedding.html
 * <br/>
 * Servlet config params:
 * <p>struts.osgi.clearBundleCache: Defaults to "true" delete installed bundles when the comntainer starts

* <p>struts.osgi.logLevel: Defaults to "1". Felix log level. 1 = error, 2 = warning, 3 = information, and 4 = debug

* <p>struts.osgi.runLevel: Defaults to "3". Run level to start the container.

*/ public class FelixOsgiHost implements OsgiHost { private static final Logger LOG = LoggerFactory.getLogger(FelixOsgiHost.class); private Felix felix; private static final Pattern versionPattern = Pattern.compile("([\\d])+[\\.-]"); private ServletContext servletContext; protected void startFelix() { //load properties from felix embedded file Properties configProps = getProperties("default.properties"); // Copy framework properties from the system properties. Main.copySystemProperties(configProps); replaceSystemPackages(configProps); //struts, xwork and felix exported packages Properties strutsConfigProps = getProperties("struts-osgi.properties"); addExportedPackages(strutsConfigProps, configProps); //find bundles and adde em to autostart property addAutoStartBundles(configProps); // Bundle cache String storageDir = System.getProperty("java.io.tmpdir") + ".felix-cache"; configProps.setProperty(Constants.FRAMEWORK_STORAGE, storageDir); if (LOG.isDebugEnabled()) LOG.debug("Storing bundles at [#0]", storageDir); String cleanBundleCache = getServletContextParam("struts.osgi.clearBundleCache", "true"); if ("true".equalsIgnoreCase(cleanBundleCache)) { if (LOG.isDebugEnabled()) LOG.debug("Clearing bundle cache"); configProps.put(FelixConstants.FRAMEWORK_STORAGE_CLEAN, FelixConstants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT); } //other properties configProps.put(FelixConstants.SERVICE_URLHANDLERS_PROP, "false"); configProps.put(FelixConstants.LOG_LEVEL_PROP, getServletContextParam("struts.osgi.logLevel", "1")); configProps.put(FelixConstants.BUNDLE_CLASSPATH, "."); configProps.put(FelixConstants.FRAMEWORK_BEGINNING_STARTLEVEL, getServletContextParam("struts.osgi.runLevel", "3")); try { List<BundleActivator> list = new ArrayList(); list.add(new AutoActivator(configProps)); configProps.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list); felix = new Felix(configProps); felix.start(); if (LOG.isTraceEnabled()) LOG.trace("Apache Felix is running"); } catch (Exception ex) { throw new ConfigurationException("Couldn't start Apache Felix", ex); } addSpringOSGiSupport(); //add the bundle context to the ServletContext servletContext.setAttribute(OSGI_BUNDLE_CONTEXT, felix.getBundleContext()); } /** * Gets a param from the ServletContext, returning the default value if the param is not set * * @param paramName the name of the param to get from the ServletContext * @param defaultValue value to return if the param is not set * @return */ private String getServletContextParam(String paramName, String defaultValue) { return StringUtils.defaultString(this.servletContext.getInitParameter(paramName), defaultValue); } protected void addAutoStartBundles(Properties configProps) { //starts system bundles in level 1 List<String> bundleJarsLevel1 = new ArrayList(); bundleJarsLevel1.add(getJarUrl(ShellService.class)); bundleJarsLevel1.add(getJarUrl(ServiceTracker.class)); configProps.put(AutoActivator.AUTO_START_PROP + ".1", StringUtils.join(bundleJarsLevel1, " ")); //get a list of directories under /bundles with numeric names (the runlevel) Map<String, String> runLevels = getRunLevelDirs("bundles"); if (runLevels.isEmpty()) { //there are no run level dirs, search for bundles in that dir List<String> bundles = getBundlesInDir("bundles"); if (!bundles.isEmpty()) configProps.put(AutoActivator.AUTO_START_PROP + ".2", StringUtils.join(bundles, " ")); } else { for (String runLevel : runLevels.keySet()) { if ("1".endsWith(runLevel)) throw new StrutsException("Run level dirs must be greater than 1. Run level 1 is reserved for the Felix bundles"); List<String> bundles = getBundlesInDir(runLevels.get(runLevel)); configProps.put(AutoActivator.AUTO_START_PROP + "." + runLevel, StringUtils.join(bundles, " ")); } } } /** * Return a list of directories under a directory whose name is a number */ protected Map<String, String> getRunLevelDirs(String dir) { Map<String, String> dirs = new HashMap(); try { ResourceFinder finder = new ResourceFinder(); URL url = finder.find("bundles"); if (url != null) { if ("file".equals(url.getProtocol())) { File bundlesDir = new File(url.toURI()); String[] runLevelDirs = bundlesDir.list(new FilenameFilter() { public boolean accept(File file, String name) { try { return file.isDirectory() && Integer.valueOf(name) > 0; } catch (NumberFormatException ex) { //the name is not a number return false; } } }); if (runLevelDirs != null && runLevelDirs.length > 0) { //add all the dirs to the list for (String runLevel : runLevelDirs) dirs.put(runLevel, StringUtils.chomp(dir, "/") + "/" + runLevel); } else if (LOG.isDebugEnabled()) { LOG.debug("No run level directories found under the [#0] directory", dir); } } else if (LOG.isWarnEnabled()) LOG.warn("Unable to read [#0] directory", dir); } else if (LOG.isWarnEnabled()) LOG.warn("The [#0] directory was not found", dir); } catch (Exception e) { if (LOG.isWarnEnabled()) LOG.warn("Unable load bundles from the [#0] directory", e, dir); } return dirs; } protected List<String> getBundlesInDir(String dir) { List<String> bundleJars = new ArrayList(); try { ResourceFinder finder = new ResourceFinder(); URL url = finder.find(dir); if (url != null) { if ("file".equals(url.getProtocol())) { File bundlesDir = new File(url.toURI()); File[] bundles = bundlesDir.listFiles(new FilenameFilter() { public boolean accept(File file, String name) { return StringUtils.endsWith(name, ".jar"); } }); if (bundles != null && bundles.length > 0) { //add all the bundles to the list for (File bundle : bundles) { String externalForm = bundle.toURI().toURL().toExternalForm(); if (LOG.isDebugEnabled()) LOG.debug("Adding bundle [#0]", externalForm); bundleJars.add(externalForm); } } else if (LOG.isDebugEnabled()) { LOG.debug("No bundles found under the [#0] directory", dir); } } else if (LOG.isWarnEnabled()) LOG.warn("Unable to read [#0] directory", dir); } else if (LOG.isWarnEnabled()) LOG.warn("The [#0] directory was not found", dir); } catch (Exception e) { if (LOG.isWarnEnabled()) LOG.warn("Unable load bundles from the [#0] directory", e, dir); } return bundleJars; } protected void addSpringOSGiSupport() { // see the javadoc for org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext for more details // OsgiBundleXmlWebApplicationContext expects the the BundleContext to be set in the ServletContext under the attribute // OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE try { Class clazz = Class.forName("org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext"); String key = (String) clazz.getDeclaredField("BUNDLE_CONTEXT_ATTRIBUTE").get(null); servletContext.setAttribute(key, felix.getBundleContext()); } catch (ClassNotFoundException e) { if (LOG.isDebugEnabled()) { LOG.debug("Spring OSGi support is not enabled"); } } catch (Exception e) { if (LOG.isErrorEnabled()) { LOG.error("The API of Spring OSGi has changed and the field [#0] is no longer available. The OSGi plugin needs to be updated", e, "org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext.BUNDLE_CONTEXT_ATTRIBUTE"); } } } protected String getJarUrl(Class clazz) { ProtectionDomain protectionDomain = clazz.getProtectionDomain(); CodeSource codeSource = protectionDomain.getCodeSource(); URL loc = codeSource.getLocation(); return loc.toString(); } protected void replaceSystemPackages(Properties properties) { //Felix has a way to load the config file and substitution expressions //but the method does not have a way to specify the file (other than in an env variable) //${jre-${java.specification.version}} String systemPackages = (String) properties.get(Constants.FRAMEWORK_SYSTEMPACKAGES); String jreVersion = "jre-" + System.getProperty("java.version").substring(0, 3); systemPackages = systemPackages.replace("${jre-${java.specification.version}}", (String) properties.get(jreVersion)); properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages); } /* Find subpackages of the packages defined in the property file and export them */ protected void addExportedPackages(Properties strutsConfigProps, Properties configProps) { String[] rootPackages = StringUtils.split((String) strutsConfigProps.get("scanning.package.includes"), ","); ResourceFinder finder = new ResourceFinder(StringUtils.EMPTY); List<String> exportedPackages = new ArrayList(); //build a list of subpackages for (String rootPackage : rootPackages) { try { String version = null; if (rootPackage.indexOf(";") > 0) { String[] splitted = rootPackage.split(";"); rootPackage = splitted[0]; version = splitted[1]; } Map<URL, Set subpackagesMap = finder.findPackagesMap(StringUtils.replace(rootPackage.trim(), ".", "/")); for (Map.Entry<URL, Set entry : subpackagesMap.entrySet()) { URL url = entry.getKey(); Set<String> packages = entry.getValue(); //get version if not set if (StringUtils.isBlank(version)) version = getVersion(url); if (packages != null) { for (String subpackage : packages) { exportedPackages.add(subpackage + "; version=" + version); } } } } catch (IOException e) { if (LOG.isErrorEnabled()) LOG.error("Unable to find subpackages of [#0]", e, rootPackage); } } //make a string with the exported packages and add it to the system properties if (!exportedPackages.isEmpty()) { String systemPackages = (String) configProps.get(Constants.FRAMEWORK_SYSTEMPACKAGES); systemPackages = StringUtils.chomp(systemPackages, ",") + "," + StringUtils.join(exportedPackages, ","); configProps.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemPackages); } } /** * Gets the version used to export the packages. it tries to get it from MANIFEST.MF, or the file name */ protected String getVersion(URL url) { if ("jar".equals(url.getProtocol())) { try { JarFile jarFile = new JarFile(new File(URLUtil.normalizeToFileProtocol(url).toURI())); Manifest manifest = jarFile.getManifest(); if (manifest != null) { String version = manifest.getMainAttributes().getValue("Bundle-Version"); if (StringUtils.isNotBlank(version)) { return getVersionFromString(version); } } else { //try to get the version from the file name return getVersionFromString(jarFile.getName()); } } catch (Exception e) { if (LOG.isErrorEnabled()) LOG.error("Unable to extract version from [#0], defaulting to '1.0.0'", url.toExternalForm()); } } return "1.0.0"; } /** * Extracts numbers followed by "." or "-" from the string and joins them with "." */ protected static String getVersionFromString(String str) { Matcher matcher = versionPattern.matcher(str); List<String> parts = new ArrayList(); while (matcher.find()) { parts.add(matcher.group(1)); } //default if (parts.size() == 0) return "1.0.0"; while (parts.size() < 3) parts.add("0"); return StringUtils.join(parts, "."); } protected Properties getProperties(String fileName) { ResourceFinder finder = new ResourceFinder(""); try { return finder.findProperties(fileName); } catch (IOException e) { if (LOG.isErrorEnabled()) LOG.error("Unable to read property file [#]", fileName); return new Properties(); } } /** * This bundle map will not change, but the status of the bundles can change over time. * Use getActiveBundles() for active bundles */ public Map<String, Bundle> getBundles() { Map<String, Bundle> bundles = new HashMap(); for (Bundle bundle : felix.getBundleContext().getBundles()) { bundles.put(bundle.getSymbolicName(), bundle); } return Collections.unmodifiableMap(bundles); } public Map<String, Bundle> getActiveBundles() { Map<String, Bundle> bundles = new HashMap(); for (Bundle bundle : felix.getBundleContext().getBundles()) { if (bundle.getState() == Bundle.ACTIVE) bundles.put(bundle.getSymbolicName(), bundle); } return Collections.unmodifiableMap(bundles); } public BundleContext getBundleContext() { return felix.getBundleContext(); } public void destroy() throws Exception { felix.stop(); if (LOG.isTraceEnabled()) LOG.trace("Apache Felix has stopped"); } public void init(ServletContext servletContext) { this.servletContext = servletContext; startFelix(); } }

Other Struts examples (source code examples)

Here is a short list of links related to this Struts FelixOsgiHost.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.