001/* 002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * bstefanescu 016 */ 017package org.nuxeo.ecm.webengine.app; 018 019import java.io.File; 020import java.io.IOException; 021import java.util.Map; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.nuxeo.common.utils.FileUtils; 026import org.nuxeo.common.utils.Path; 027import org.nuxeo.common.utils.PathFilter; 028import org.nuxeo.common.utils.ZipUtils; 029import org.nuxeo.ecm.webengine.WebEngine; 030import org.nuxeo.osgi.BundleManifestReader; 031import org.nuxeo.runtime.api.Framework; 032import org.osgi.framework.Bundle; 033import org.osgi.framework.BundleContext; 034import org.osgi.framework.ServiceReference; 035import org.osgi.service.packageadmin.PackageAdmin; 036 037/** 038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 039 */ 040public class WebEngineModuleFactory { 041 042 public static Log log = LogFactory.getLog(WebEngineModuleFactory.class); 043 044 public static Bundle[] getFragments(Bundle bundle) { 045 BundleContext context = bundle.getBundleContext(); 046 ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName()); 047 PackageAdmin admin = (PackageAdmin) context.getService(ref); 048 return admin.getFragments(bundle); 049 } 050 051 public static WebEngineModule getApplication(WebEngineModule app, Bundle bundle, Map<String, String> attrs) 052 throws ReflectiveOperationException, IOException { 053 WebEngine engine = Framework.getLocalService(WebEngine.class); 054 055 boolean explode = true; 056 if (attrs != null) { 057 if ("false".equals(attrs.get("explode"))) { 058 explode = false; 059 } 060 } 061 // register the web engine 062 063 File moduleDir = locateModuleDir(bundle, engine, explode); 064 065 app.init(engine, bundle, new File(moduleDir, "module.xml"), attrs); 066 067 app.cfg.directory = moduleDir; 068 069 Bundle[] fragments = getFragments(bundle); 070 for (Bundle fragment : fragments) { 071 File fragmentDir = locateModuleDir(fragment, engine, explode); 072 app.cfg.fragmentDirectories.add(fragmentDir); 073 } 074 app.cfg.allowHostOverride = Boolean.parseBoolean((String) bundle.getHeaders().get( 075 BundleManifestReader.ALLOW_HOST_OVERRIDE)); 076 engine.addApplication(app); 077 078 log.info("Deployed web module found in bundle: " + bundle.getSymbolicName()); 079 080 return app; 081 } 082 083 private static File locateModuleDir(Bundle bundle, WebEngine engine, boolean explode) throws IOException { 084 File moduleDir = null; 085 File bundleFile = Framework.getRuntime().getBundleFile(bundle); 086 if (explode) { 087 // this will also add the exploded directory to WebEngine class 088 // loader 089 moduleDir = explodeBundle(engine, bundle, bundleFile); 090 } else if (bundleFile.isDirectory()) { 091 moduleDir = bundleFile; 092 } 093 return moduleDir; 094 } 095 096 private static File explodeBundle(WebEngine engine, Bundle bundle, File bundleFile) throws IOException { 097 if (bundleFile.isDirectory()) { // exploded jar - deploy it as is. 098 return bundleFile; 099 } else { // should be a JAR - we copy the bundle module content 100 File moduleRoot = new File(engine.getRootDirectory(), "modules/" + bundle.getSymbolicName()); 101 if (moduleRoot.exists()) { 102 if (bundleFile.lastModified() < moduleRoot.lastModified()) { 103 // already deployed and JAR was not modified since. 104 return moduleRoot; 105 } 106 // remove existing files 107 FileUtils.deleteTree(moduleRoot); 108 } 109 // create the module root 110 moduleRoot.mkdirs(); 111 // avoid unziping classes 112 ZipUtils.unzip(bundleFile, moduleRoot, new PathFilter() { 113 @Override 114 public boolean isExclusive() { 115 return false; 116 } 117 118 @Override 119 public boolean accept(Path arg0) { 120 return !arg0.lastSegment().endsWith(".class"); 121 } 122 }); 123 return moduleRoot; 124 } 125 } 126 127}