001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.deploy.auto;
016    
017    import aQute.libg.header.OSGiHeader;
018    
019    import com.liferay.portal.kernel.deploy.auto.AutoDeployException;
020    import com.liferay.portal.kernel.deploy.auto.AutoDeployListener;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.kernel.zip.ZipReader;
025    import com.liferay.portal.kernel.zip.ZipReaderFactoryUtil;
026    import com.liferay.portal.osgi.service.OSGiServiceUtil;
027    
028    import java.io.File;
029    import java.io.FileInputStream;
030    import java.io.InputStream;
031    
032    import java.net.URI;
033    
034    import java.util.Dictionary;
035    import java.util.Iterator;
036    import java.util.Map;
037    import java.util.Set;
038    import java.util.jar.Attributes;
039    import java.util.jar.Manifest;
040    
041    import org.osgi.framework.Bundle;
042    import org.osgi.framework.BundleContext;
043    import org.osgi.framework.Constants;
044    import org.osgi.framework.Version;
045    import org.osgi.framework.launch.Framework;
046    
047    /**
048     * @author Raymond Augé
049     */
050    public class OSGiAutoDeployListener implements AutoDeployListener {
051    
052            public void deploy(File file, String context) throws AutoDeployException {
053                    try {
054                            doDeploy(file, context);
055                    }
056                    catch (Exception e) {
057                            throw new AutoDeployException(e);
058                    }
059            }
060    
061            protected void cleanUp(ZipReader zipReader, InputStream inputStream) {
062                    if (inputStream != null) {
063                            try {
064                                    inputStream.close();
065                            }
066                            catch (Exception e) {
067                                    _log.error(e, e);
068                            }
069    
070                            inputStream = null;
071                    }
072    
073                    if (zipReader != null) {
074                            try {
075                                    zipReader.close();
076                            }
077                            catch (Exception e) {
078                                    _log.error(e, e);
079                            }
080                    }
081            }
082    
083            protected void doDeploy(File file, String context) throws Exception {
084                    Framework framework = OSGiServiceUtil.getFramework();
085    
086                    if (framework == null) {
087                            if (_log.isDebugEnabled()) {
088                                    _log.debug("OSGi framework is disabled or not installed");
089                            }
090    
091                            return;
092                    }
093    
094                    String fileName = file.getName();
095    
096                    fileName = fileName.toLowerCase();
097    
098                    if (file.isDirectory() ||
099                            (!fileName.endsWith(".jar") && !fileName.endsWith(".war"))) {
100    
101                            return;
102                    }
103    
104                    ZipReader zipReader = null;
105    
106                    InputStream inputStream = null;
107    
108                    try {
109                            zipReader = ZipReaderFactoryUtil.getZipReader(file);
110    
111                            inputStream = zipReader.getEntryAsInputStream(
112                                    "/META-INF/MANIFEST.MF");
113    
114                            if (inputStream == null) {
115                                    return;
116                            }
117    
118                            Manifest manifest = new Manifest(inputStream);
119    
120                            Attributes attributes = manifest.getMainAttributes();
121    
122                            String bundleSymbolicName = attributes.getValue(
123                                    Constants.BUNDLE_SYMBOLICNAME);
124    
125                            if (Validator.isNotNull(bundleSymbolicName)) {
126                                    installBundle(framework, file, manifest);
127                            }
128                    }
129                    finally {
130                            cleanUp(zipReader, inputStream);
131                    }
132            }
133    
134            protected Bundle getBundle(Framework framework, Manifest manifest) {
135                    BundleContext bundleContext = framework.getBundleContext();
136    
137                    Attributes attributes = manifest.getMainAttributes();
138    
139                    String bundleSymbolicNameAttribute = attributes.getValue(
140                            Constants.BUNDLE_SYMBOLICNAME);
141    
142                    Map<String, Map<String, String>> bundleSymbolicNamesMap =
143                            OSGiHeader.parseHeader(bundleSymbolicNameAttribute);
144    
145                    Set<String> bundleSymbolicNamesSet = bundleSymbolicNamesMap.keySet();
146    
147                    Iterator<String> bundleSymbolicNamesIterator =
148                            bundleSymbolicNamesSet.iterator();
149    
150                    String bundleSymbolicName = bundleSymbolicNamesIterator.next();
151    
152                    String bundleVersionAttribute = attributes.getValue(
153                            Constants.BUNDLE_VERSION);
154    
155                    Version bundleVersion = Version.parseVersion(bundleVersionAttribute);
156    
157                    for (Bundle bundle : bundleContext.getBundles()) {
158                            if (bundleSymbolicName.equals(bundle.getSymbolicName()) &&
159                                    bundleVersion.equals(bundle.getVersion())) {
160    
161                                    return bundle;
162                            }
163                    }
164    
165                    return null;
166            }
167    
168            protected void installBundle(
169                            Framework framework, File file, Manifest manifest)
170                    throws Exception {
171    
172                    Bundle bundle = getBundle(framework, manifest);
173    
174                    InputStream inputStream = new FileInputStream(file);
175    
176                    if (bundle != null) {
177                            bundle.update(inputStream);
178                    }
179                    else {
180                            try {
181                                    BundleContext bundleContext = framework.getBundleContext();
182    
183                                    URI uri = file.toURI();
184    
185                                    bundle = bundleContext.installBundle(
186                                            uri.toString(), inputStream);
187                            }
188                            catch (Exception e) {
189                                    _log.error(e, e);
190                            }
191                    }
192    
193                    if (bundle == null) {
194                            return;
195                    }
196    
197                    Dictionary<String, String> headers = bundle.getHeaders();
198    
199                    if (headers.get(Constants.FRAGMENT_HOST) != null) {
200                            return;
201                    }
202    
203                    bundle.start();
204            }
205    
206            private static Log _log = LogFactoryUtil.getLog(
207                    OSGiAutoDeployListener.class);
208    
209    }