| /* |
| * 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.clerezza.platform.scripting; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import javax.script.ScriptEngineFactory; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleEvent; |
| import org.osgi.framework.BundleListener; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.component.ComponentContext; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * @scr.component |
| * |
| * @author hasan |
| */ |
| public class ScriptEngineFactoryManager implements BundleListener { |
| |
| final Logger logger = LoggerFactory.getLogger(getClass()); |
| |
| private ComponentContext componentContext = null; |
| |
| private Map<Long, List<ServiceRegistration>> registeredFactories = |
| new HashMap<Long, List<ServiceRegistration>>(); |
| |
| private final String SERVICE_DEF_PATH = "/META-INF/services/"; |
| private final String SERVICE_DEF_FILE = "javax.script.ScriptEngineFactory"; |
| |
| protected void activate(final ComponentContext componentContext) { |
| this.componentContext = componentContext; |
| registerExistingEngineFactories(); |
| componentContext.getBundleContext().addBundleListener(this); |
| } |
| |
| private void registerExistingEngineFactories() { |
| if (componentContext == null) { |
| logger.warn("componentContext is null while trying to register" + |
| "script engine factories in started bundles"); |
| return; |
| } |
| Bundle[] bundles = componentContext.getBundleContext().getBundles(); |
| for (Bundle bundle : bundles) { |
| if (bundle.getState() == Bundle.ACTIVE) { |
| List<String> engineFactoryNames = getEngineFactoryNames(bundle); |
| registerEngineFactories(bundle, engineFactoryNames); |
| } |
| } |
| } |
| |
| private List<String> getEngineFactoryNames(Bundle bundle) { |
| List<String> engineFactoryNames = new ArrayList<String>(); |
| BufferedReader in = null; |
| try { |
| URL entry = bundle.getEntry(SERVICE_DEF_PATH+SERVICE_DEF_FILE); |
| if (entry == null) { |
| return null; |
| } |
| in = new BufferedReader(new InputStreamReader(entry.openStream())); |
| String engineFactoryName; |
| while ((engineFactoryName = in.readLine()) != null) { |
| engineFactoryName = engineFactoryName.trim(); |
| if (!engineFactoryName.isEmpty()) { |
| engineFactoryNames.add(engineFactoryName); |
| } |
| } |
| in.close(); |
| } catch (IOException ex) { |
| // ignored, since this bundle seems to not contain a script engine |
| logger.info("Cannot read {} in bundle {}", |
| SERVICE_DEF_PATH + SERVICE_DEF_FILE, bundle.getSymbolicName()); |
| } finally { |
| if (in != null) { |
| try { |
| in.close(); |
| } catch (IOException ex) { |
| // ignored |
| } |
| } |
| } |
| return engineFactoryNames; |
| } |
| |
| private void registerEngineFactories(Bundle bundle, List<String> engineFactoryNames) { |
| if (engineFactoryNames == null || engineFactoryNames.isEmpty()) { |
| return; |
| } |
| List<ServiceRegistration> serviceRegList = new ArrayList<ServiceRegistration>(); |
| for (String engineFactoryName : engineFactoryNames) { |
| try { |
| Class factoryClass = Class.forName(engineFactoryName); |
| ScriptEngineFactory factory = (ScriptEngineFactory) factoryClass.newInstance(); |
| String[] clazzes = {engineFactoryName, SERVICE_DEF_FILE}; |
| ServiceRegistration serviceReg = componentContext.getBundleContext().registerService(clazzes, factory, null); |
| serviceRegList.add(serviceReg); |
| |
| if (engineFactoryName.equals("com.sun.script.jruby.JRubyScriptEngineFactory")) { |
| factory = new JRubyScriptEngineFactoryWrapper( |
| (ScriptEngineFactory) factoryClass.newInstance()); |
| String[] wrappedClazzes = { |
| "org.apache.clerezza.platform.scripting.JRubyScriptEngineFactoryWrapper", |
| SERVICE_DEF_FILE |
| }; |
| serviceRegList.add(componentContext.getBundleContext().registerService(wrappedClazzes, factory, null)); |
| } |
| |
| } catch (InstantiationException ex) { |
| logger.warn("Cannot instantiate {}", engineFactoryName); |
| throw new RuntimeException(ex); |
| } catch (IllegalAccessException ex) { |
| throw new RuntimeException(ex); |
| } catch (ClassNotFoundException ex) { |
| logger.warn("Cannot find class {}", engineFactoryName); |
| throw new RuntimeException(ex); |
| } |
| } |
| long bundleId = bundle.getBundleId(); |
| registeredFactories.put(bundleId, serviceRegList); |
| } |
| |
| protected void deactivate(final ComponentContext componentContext) { |
| deregisterEngineFactories(); |
| componentContext.getBundleContext().removeBundleListener(this); |
| this.componentContext = null; |
| } |
| |
| private void deregisterEngineFactories() { |
| Iterator<List<ServiceRegistration>> serviceRegLists = |
| registeredFactories.values().iterator(); |
| while (serviceRegLists.hasNext()) { |
| for (ServiceRegistration serviceReg : serviceRegLists.next()) { |
| serviceReg.unregister(); |
| } |
| } |
| registeredFactories.clear(); |
| } |
| |
| @Override |
| public void bundleChanged(BundleEvent event) { |
| Bundle bundle = event.getBundle(); |
| switch (event.getType()) { |
| case BundleEvent.STARTED: |
| registerEngineFactories(bundle, getEngineFactoryNames(bundle)); |
| break; |
| case BundleEvent.STOPPED: |
| long bundleId = bundle.getBundleId(); |
| List<ServiceRegistration> serviceRegList = registeredFactories.get(bundleId); |
| if (serviceRegList != null && !serviceRegList.isEmpty()) { |
| for (ServiceRegistration serviceReg : serviceRegList) { |
| serviceReg.unregister(); |
| } |
| registeredFactories.remove(bundleId); |
| } |
| break; |
| } |
| } |
| } |