OSGiFileLocator.java

  1. /***** BEGIN LICENSE BLOCK *****
  2.  * Version: EPL 1.0/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Eclipse Public
  5.  * License Version 1.0 (the "License"); you may not use this file
  6.  * except in compliance with the License. You may obtain a copy of
  7.  * the License at http://www.eclipse.org/legal/epl-v10.html
  8.  *
  9.  * Software distributed under the License is distributed on an "AS
  10.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11.  * implied. See the License for the specific language governing
  12.  * rights and limitations under the License.
  13.  *
  14.  * Copyright (C) 2002-2011 JRuby Community
  15.  *
  16.  * Alternatively, the contents of this file may be used under the terms of
  17.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  18.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  19.  * in which case the provisions of the GPL or the LGPL are applicable instead
  20.  * of those above. If you wish to allow use of your version of this file only
  21.  * under the terms of either the GPL or the LGPL, and not to allow others to
  22.  * use your version of this file under the terms of the EPL, indicate your
  23.  * decision by deleting the provisions above and replace them with the notice
  24.  * and other provisions required by the GPL or the LGPL. If you do not delete
  25.  * the provisions above, a recipient may use your version of this file under
  26.  * the terms of any one of the EPL, the GPL or the LGPL.
  27.  ***** END LICENSE BLOCK *****/
  28. package org.jruby.embed.osgi.utils;

  29. import java.io.File;
  30. import java.io.IOException;
  31. import java.lang.reflect.Method;
  32. import java.net.URL;
  33. import java.net.URLConnection;

  34. import org.osgi.framework.Bundle;
  35. import org.osgi.framework.BundleContext;
  36. import org.osgi.framework.BundleException;
  37. import org.osgi.framework.FrameworkUtil;

  38. /**
  39.  * Helper methods for the Ruby Runtime.
  40.  *
  41.  * @author hmalphettes
  42.  */
  43. public class OSGiFileLocator {
  44.    
  45.     public static final String JRUBY_SYMBOLIC_NAME = "org.jruby.jruby";
  46.        
  47.     public static File getFileInBundle(String symbolicName, String path) throws IOException {
  48.         Bundle bundle = getBundle(symbolicName);
  49.         if (bundle == null) {
  50.             throw new IOException("Unable to find the bundle " + symbolicName);
  51.         }
  52.         return getFileInBundle(bundle, path);
  53.     }
  54.     public static File getFileInBundle(Bundle bundle, String path) throws IOException {
  55.         URL url = null;
  56.         try {
  57.             url = getFileURL(bundle.getEntry(path));
  58.             return new File(url.getFile());
  59.         } catch (NullPointerException ne) {
  60.             throw new IOException("Unable to find the " + path + " folder in the bundle '"
  61.                     + bundle.getSymbolicName() + "'; is the org.jruby.jruby bundle unzipped? ");
  62.         } catch (Exception e) {
  63.             IOException exception = new IOException("Unable to find the " + path +
  64.                     " folder in the bundle '" + bundle.getSymbolicName() + "'");
  65.             exception.initCause(e); // Should be safe since IOException(String) should call super(String).
  66.             throw exception;
  67.         }
  68.     }

  69.     /**
  70.      * @param symbolicName
  71.      * @return The bundle with this symbolic name
  72.      */
  73.     public static Bundle getBundle(String symbolicName) {
  74.         BundleContext bc = FrameworkUtil.getBundle(OSGiFileLocator.class).getBundleContext();
  75.         if (bc == null) {
  76.             //if the bundle was not activatged then let's activate it.
  77.             try {
  78.                 FrameworkUtil.getBundle(OSGiFileLocator.class).start();
  79.             } catch (BundleException e) {
  80.                 throw new IllegalStateException("Could not start the bundle "
  81.                     + FrameworkUtil.getBundle(OSGiFileLocator.class).getSymbolicName());
  82.             }
  83.             bc = FrameworkUtil.getBundle(OSGiFileLocator.class).getBundleContext();
  84.             if (bc == null) {
  85.                 //this should never happen
  86.                 throw new IllegalStateException("The bundle "
  87.                     + FrameworkUtil.getBundle(OSGiFileLocator.class).getSymbolicName()
  88.                     + " is not activated.");
  89.             }
  90.         }
  91.         for (Bundle b : FrameworkUtil.getBundle(OSGiFileLocator.class).getBundleContext().getBundles()) {
  92.             if (b.getSymbolicName().equals(symbolicName)) {
  93.                 return b;
  94.             }
  95.         }
  96.         return null;
  97.     }
  98.    
  99.     //introspection on equinox to invoke the getLocalURL method on BundleURLConnection
  100.     private static Method BUNDLE_URL_CONNECTION_getLocalURL = null;
  101.     private static Method BUNDLE_URL_CONNECTION_getFileURL = null;
  102.     /**
  103.      * Only useful for equinox: on felix we get the file:// or jar:// url already.
  104.      * Other OSGi implementations have not been tested
  105.      * <p>
  106.      * Get a URL to the bundle entry that uses a common protocol (i.e. file:
  107.      * jar: or http: etc.).  
  108.      * </p>
  109.      * @return a URL to the bundle entry that uses a common protocol
  110.      */
  111.     public static URL getLocalURL(URL url) {
  112.         if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol())) {
  113.             try {
  114.                 URLConnection conn = url.openConnection();
  115.                 if (BUNDLE_URL_CONNECTION_getLocalURL == null &&
  116.                         conn.getClass().getName().equals(
  117.                                 "org.eclipse.osgi.framework.internal.core.BundleURLConnection")) {
  118.                     BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL");
  119.                     BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
  120.                 }
  121.                 if (BUNDLE_URL_CONNECTION_getLocalURL != null) {
  122.                     return (URL)BUNDLE_URL_CONNECTION_getLocalURL.invoke(conn);
  123.                 }
  124.             } catch (Throwable t) {
  125.                 t.printStackTrace();
  126.             }
  127.         }
  128.         return url;
  129.     }
  130.     /**
  131.      * Only useful for equinox: on felix we get the file:// url already.
  132.      * Other OSGi implementations have not been tested
  133.      * <p>
  134.      * Get a URL to the content of the bundle entry that uses the file: protocol.
  135.      * The content of the bundle entry may be downloaded or extracted to the local
  136.      * file system in order to create a file: URL.
  137.      * @return a URL to the content of the bundle entry that uses the file: protocol
  138.      * </p>
  139.      */
  140.     public static URL getFileURL(URL url)
  141.     {
  142.         if ("bundleresource".equals(url.getProtocol()) || "bundleentry".equals(url.getProtocol()))
  143.         {
  144.             try
  145.             {
  146.                 URLConnection conn = url.openConnection();
  147.                 if (BUNDLE_URL_CONNECTION_getFileURL == null &&
  148.                         conn.getClass().getName().equals(
  149.                                 "org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
  150.                 {
  151.                     BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL");
  152.                     BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);
  153.                 }
  154.                 if (BUNDLE_URL_CONNECTION_getFileURL != null)
  155.                 {
  156.                     return (URL)BUNDLE_URL_CONNECTION_getFileURL.invoke(conn);
  157.                 }
  158.             }
  159.             catch (Throwable t)
  160.             {
  161.                 t.printStackTrace();
  162.             }
  163.         }
  164.         return url;
  165.     }
  166.    
  167. }