| /* |
| * 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.ace.deployment.service.impl; |
| |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.net.MalformedURLException; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| import java.net.URLConnection; |
| import java.util.ArrayList; |
| import java.util.Dictionary; |
| import java.util.Hashtable; |
| import java.util.List; |
| import java.util.SortedSet; |
| import java.util.TreeSet; |
| |
| import org.apache.ace.connectionfactory.ConnectionFactory; |
| import org.apache.ace.deployment.Deployment; |
| import org.apache.ace.deployment.service.DeploymentService; |
| import org.apache.ace.discovery.Discovery; |
| import org.apache.ace.identification.Identification; |
| import org.osgi.framework.Version; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventAdmin; |
| import org.osgi.service.log.LogService; |
| |
| /** |
| * Provides an implementation for {@link DeploymentService}. |
| */ |
| public class DeploymentServiceImpl implements DeploymentService { |
| |
| private final String TOPIC_DEPLOYMENTPACKAGE_INSTALL = "org/apache/ace/deployment/INSTALL"; |
| |
| // injected by dependencymanager |
| protected volatile Deployment m_deployer; |
| protected volatile Identification m_identification; |
| protected volatile Discovery m_discovery; |
| protected volatile LogService m_log; |
| protected volatile EventAdmin m_eventAdmin; |
| protected volatile ConnectionFactory m_connectionFactory; |
| |
| /** |
| * @see org.apache.ace.deployment.service.DeploymentService#getHighestLocalVersion() |
| */ |
| public Version getHighestLocalVersion() { |
| Object[] installedPackages = m_deployer.list(); |
| List<Version> versions = new ArrayList<>(); |
| for (int i = 0; i < installedPackages.length; i++) { |
| if (m_deployer.getName(installedPackages[i]).equals(m_identification.getID())) { |
| versions.add(m_deployer.getVersion(installedPackages[i])); |
| } |
| } |
| return getHighestVersion(versions); |
| } |
| |
| /** |
| * @see org.apache.ace.deployment.service.DeploymentService#getHighestRemoteVersion() |
| */ |
| public Version getHighestRemoteVersion() throws IOException { |
| SortedSet<Version> versions = getRemoteVersions(getURL()); |
| return ((versions == null) || versions.isEmpty()) ? null : versions.last(); |
| } |
| |
| /** |
| * @see org.apache.ace.deployment.service.DeploymentService#getRemoteVersions() |
| */ |
| public SortedSet<Version> getRemoteVersions() throws IOException { |
| return getRemoteVersions(getURL()); |
| } |
| |
| /** |
| * @see org.apache.ace.deployment.service.DeploymentService#installVersion(org.osgi.framework.Version, org.osgi.framework.Version) |
| */ |
| public void installVersion(Version highestRemoteVersion, Version highestLocalVersion) throws IOException, Exception { |
| InputStream inputStream = null; |
| |
| m_log.log(LogService.LOG_INFO, "Installing version: " + highestRemoteVersion); |
| |
| try { |
| String version = highestRemoteVersion.toString(); |
| URL baseURL = getURL(); |
| boolean isFileBasedProtocol = "file".equals(baseURL.getProtocol()); |
| if (highestLocalVersion != null && !isFileBasedProtocol) { |
| version += "?current=" + highestLocalVersion.toString(); |
| } |
| URL dataURL = new URL(baseURL, version); |
| if (isFileBasedProtocol) { |
| File file = urlToFile(dataURL); |
| inputStream = new FileInputStream(file); |
| } |
| else { |
| inputStream = getContents(dataURL); |
| } |
| |
| // Post event for auditlog |
| m_eventAdmin.postEvent(createEvent(version, dataURL)); |
| |
| m_deployer.install(inputStream); |
| } |
| finally { |
| if (inputStream != null) { |
| try { |
| inputStream.close(); |
| } |
| catch (Exception ex) { |
| // Not much we can do. |
| } |
| } |
| } |
| } |
| |
| /** |
| * @see org.apache.ace.deployment.service.DeploymentService#update(org.osgi.framework.Version) |
| */ |
| public void update(Version toVersion) throws Exception { |
| installVersion(toVersion, getHighestLocalVersion()); |
| } |
| |
| /** |
| * @param url |
| * @return |
| * @throws IOException |
| */ |
| final SortedSet<Version> getRemoteVersions(URL url) throws IOException { |
| if (url == null) { |
| return null; |
| } |
| |
| if ("file".equals(url.getProtocol())) { |
| return getVersionsFromDirectory(url); |
| } |
| else { |
| return getVersionsFromServer(url); |
| } |
| } |
| |
| /** |
| * @param version |
| * @param dataURL |
| * @return |
| */ |
| private Event createEvent(String version, URL dataURL) { |
| Dictionary<String, Object> properties = new Hashtable<>(); |
| properties.put("deploymentpackage.url", dataURL.toString()); |
| properties.put("deploymentpackage.version", version); |
| Event event = new Event(TOPIC_DEPLOYMENTPACKAGE_INSTALL, properties); |
| return event; |
| } |
| |
| /** |
| * @param versions |
| * @return |
| */ |
| private Version getHighestVersion(List<Version> versions) { |
| Version highestVersion = null; |
| for (Version version : versions) { |
| if (highestVersion == null) { |
| highestVersion = version; |
| } |
| else if (version.compareTo(highestVersion) > 0) { |
| highestVersion = version; |
| } |
| } |
| return highestVersion; |
| } |
| |
| /** |
| * @return |
| */ |
| private URL getURL() { |
| URL host = m_discovery.discover(); |
| if (host == null) { |
| return null; |
| } |
| try { |
| return new URL(host, "deployment/" + m_identification.getID() + "/versions/"); |
| } |
| catch (MalformedURLException e) { |
| m_log.log(LogService.LOG_WARNING, "Malformed URL", e); |
| return null; |
| } |
| } |
| |
| /** |
| * @param url |
| * @return |
| */ |
| private SortedSet<Version> getVersionsFromDirectory(URL url) { |
| File file = urlToFile(url); |
| if (!file.isDirectory()) { |
| return null; |
| } |
| |
| final File[] files = file.listFiles(); |
| SortedSet<Version> versions = new TreeSet<>(); |
| for (File f : files) { |
| try { |
| Version version = Version.parseVersion(f.getName()); |
| if (version != Version.emptyVersion) { |
| versions.add(version); |
| } |
| } |
| catch (IllegalArgumentException e) { |
| // if the file is not a valid version, we skip it |
| } |
| } |
| return versions; |
| } |
| |
| /** |
| * @param url |
| * @return |
| */ |
| private SortedSet<Version> getVersionsFromServer(URL url) { |
| BufferedReader bufReader = null; |
| try { |
| bufReader = new BufferedReader(new InputStreamReader(getContents(url))); |
| SortedSet<Version> versions = new TreeSet<>(); |
| |
| String versionString; |
| while ((versionString = bufReader.readLine()) != null) { |
| try { |
| Version version = Version.parseVersion(versionString); |
| if (version != Version.emptyVersion) { |
| versions.add(version); |
| } |
| } |
| catch (IllegalArgumentException iae) { |
| m_log.log(LogService.LOG_WARNING, "Received malformed version, ignoring: " + versionString); |
| } |
| } |
| |
| return versions; |
| } |
| catch (IOException ioe) { |
| m_log.log(LogService.LOG_DEBUG, "I/O error accessing server!", ioe); |
| return null; |
| } |
| finally { |
| if (bufReader != null) { |
| try { |
| bufReader.close(); |
| } |
| catch (Exception ex) { |
| // not much we can do |
| } |
| } |
| } |
| } |
| |
| /** |
| * @param url |
| * @return |
| */ |
| private File urlToFile(URL url) { |
| File file; |
| // See: http://weblogs.java.net/blog/kohsuke/archive/2007/04/how_to_convert.html |
| // makes a best effort to convert a file URL to a File |
| try { |
| file = new File(url.toURI()); |
| } |
| catch (URISyntaxException e) { |
| file = new File(url.getPath()); |
| } |
| return file; |
| } |
| |
| /** |
| * @param url the remote URL to connect to, cannot be <code>null</code>. |
| * @return an {@link InputStream} to the remote URL, never <code>null</code>. |
| * @throws IOException in case of I/O problems opening the remote connection. |
| */ |
| private InputStream getContents(URL url) throws IOException { |
| URLConnection conn = m_connectionFactory.createConnection(url); |
| return conn.getInputStream(); |
| } |
| } |