001/* 002 * (C) Copyright 2006-2018 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * $Id$ 019 */ 020 021package org.nuxeo.osgi; 022 023import java.io.File; 024import java.io.IOException; 025import java.util.Map; 026import java.util.Properties; 027import java.util.concurrent.ConcurrentHashMap; 028 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.nuxeo.common.Environment; 032import org.nuxeo.common.collections.ListenerList; 033import org.nuxeo.osgi.services.PackageAdminImpl; 034import org.osgi.framework.Bundle; 035import org.osgi.framework.BundleEvent; 036import org.osgi.framework.BundleException; 037import org.osgi.framework.BundleListener; 038import org.osgi.framework.Constants; 039import org.osgi.framework.FrameworkEvent; 040import org.osgi.framework.FrameworkListener; 041import org.osgi.framework.ServiceEvent; 042import org.osgi.framework.ServiceListener; 043import org.osgi.framework.ServiceRegistration; 044import org.osgi.service.packageadmin.PackageAdmin; 045 046/** 047 * @author <a href="mailto:[email protected]">Bogdan Stefanescu</a> 048 */ 049public class OSGiAdapter { 050 051 private static final Log log = LogFactory.getLog(OSGiAdapter.class); 052 053 protected final File workingDir; 054 055 protected final File dataDir; 056 057 protected File idTableFile; 058 059 protected BundleIdGenerator bundleIds; 060 061 protected ListenerList frameworkListeners; 062 063 protected ListenerList bundleListeners; 064 065 protected ListenerList serviceListeners; 066 067 protected Map<String, ServiceRegistration> services; 068 069 protected BundleRegistry registry; 070 071 protected Properties properties; 072 073 protected SystemBundle systemBundle; 074 075 public OSGiAdapter(File workingDir) { 076 this(workingDir, 077 new File(System.getProperty(Environment.NUXEO_DATA_DIR, workingDir + File.separator + "data")), 078 new Properties()); 079 } 080 081 public OSGiAdapter(File workingDir, File dataDir, Properties properties) { 082 services = new ConcurrentHashMap<String, ServiceRegistration>(); 083 this.workingDir = workingDir; 084 this.dataDir = dataDir; 085 this.dataDir.mkdirs(); 086 this.workingDir.mkdirs(); 087 initialize(properties); 088 } 089 090 public void removeService(String clazz) { 091 services.remove(clazz); 092 } 093 094 protected void initialize(Properties properties) { 095 this.properties = properties; 096 registry = new BundleRegistry(); 097 frameworkListeners = new ListenerList(); 098 bundleListeners = new ListenerList(); 099 serviceListeners = new ListenerList(); 100 bundleIds = new BundleIdGenerator(); 101 idTableFile = new File(dataDir, "bundles.ids"); 102 bundleIds.load(idTableFile); 103 // setting up default properties 104 properties.put(Constants.FRAMEWORK_VENDOR, "Nuxeo"); 105 properties.put(Constants.FRAMEWORK_VERSION, "1.0.0"); 106 } 107 108 public void setSystemBundle(SystemBundle systemBundle) throws BundleException { 109 if (this.systemBundle != null) { 110 throw new IllegalStateException("Cannot set system bundle"); 111 } 112 install(systemBundle); 113 registry.addBundleAlias("system.bundle", systemBundle.getSymbolicName()); 114 this.systemBundle = systemBundle; 115 116 systemBundle.getBundleContext().registerService(PackageAdmin.class.getName(), new PackageAdminImpl(this), null); 117 } 118 119 public BundleRegistry getRegistry() { 120 return registry; 121 } 122 123 public String getProperty(String key) { 124 String value = properties.getProperty(key); 125 if (value == null) { 126 value = System.getProperty(key); 127 } 128 return value; 129 } 130 131 public String getProperty(String key, String defvalue) { 132 String val = getProperty(key); 133 if (val == null) { 134 val = defvalue; 135 } 136 return val; 137 } 138 139 /** 140 * @param name the property name. 141 * @param value the property value. 142 */ 143 public void setProperty(String name, String value) { 144 properties.put(name, value); 145 } 146 147 public void shutdown() throws IOException { 148 bundleIds.store(idTableFile); 149 registry.shutdown(); 150 properties.clear(); 151 registry = null; 152 frameworkListeners = null; 153 bundleListeners = null; 154 serviceListeners = null; 155 properties = null; 156 } 157 158 public long getBundleId(String symbolicName) { 159 return bundleIds.getBundleId(symbolicName); 160 } 161 162 public File getWorkingDir() { 163 return workingDir; 164 } 165 166 public File getDataDir() { 167 return dataDir; 168 } 169 170 public BundleImpl getBundle(String symbolicName) { 171 return registry.getBundle(symbolicName); 172 } 173 174 public BundleImpl[] getInstalledBundles() { 175 return registry.getInstalledBundles(); 176 } 177 178 public void install(BundleImpl bundle) throws BundleException { 179 double s = System.currentTimeMillis(); 180 registry.install(bundle); 181 bundle.startupTime = System.currentTimeMillis() - s; 182 } 183 184 public void uninstall(BundleImpl bundle) throws BundleException { 185 registry.uninstall(bundle); 186 } 187 188 public void addFrameworkListener(FrameworkListener listener) { 189 frameworkListeners.add(listener); 190 } 191 192 public void removeFrameworkListener(FrameworkListener listener) { 193 frameworkListeners.remove(listener); 194 } 195 196 public void addServiceListener(ServiceListener listener) { 197 serviceListeners.add(listener); 198 } 199 200 public void addServiceListener(ServiceListener listener, String filter) { 201 // TODO? 202 throw new UnsupportedOperationException("This method is not implemented"); 203 } 204 205 public void removeServiceListener(ServiceListener listener) { 206 serviceListeners.remove(listener); 207 } 208 209 public void addBundleListener(BundleListener listener) { 210 bundleListeners.add(listener); 211 } 212 213 public void removeBundleListener(BundleListener listener) { 214 bundleListeners.remove(listener); 215 } 216 217 public void fireFrameworkEvent(FrameworkEvent event) { 218 log.debug("Firing FrameworkEvent on " + frameworkListeners.size() + " listeners"); 219 Object[] listeners = frameworkListeners.getListeners(); 220 for (Object listener : listeners) { 221 log.debug("Start execution of " + listener.getClass() + " listener"); 222 try { 223 ((FrameworkListener) listener).frameworkEvent(event); 224 log.debug("End execution of " + listener.getClass() + " listener"); 225 } catch (RuntimeException e) { 226 log.error("Error during Framework Listener execution : " + listener.getClass(), e); 227 if (Boolean.getBoolean("nuxeo.start.strict")) { 228 throw e; 229 } 230 } 231 } 232 } 233 234 public void fireServiceEvent(ServiceEvent event) { 235 Object[] listeners = serviceListeners.getListeners(); 236 for (Object listener : listeners) { 237 ((ServiceListener) listener).serviceChanged(event); 238 } 239 } 240 241 public void fireBundleEvent(BundleEvent event) { 242 Object[] listeners = bundleListeners.getListeners(); 243 for (Object listener : listeners) { 244 ((BundleListener) listener).bundleChanged(event); 245 } 246 } 247 248 public Bundle getSystemBundle() { 249 return systemBundle; 250 } 251 252}