| /* |
| * 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.netbeans.modules.autoupdate.services; |
| |
| import java.util.Collections; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| import org.netbeans.api.autoupdate.UpdateElement; |
| import org.netbeans.api.autoupdate.UpdateManager; |
| import org.netbeans.api.autoupdate.UpdateManager.TYPE; |
| import org.netbeans.api.autoupdate.UpdateUnit; |
| import org.netbeans.modules.autoupdate.updateprovider.ArtificialFeaturesProvider; |
| import org.netbeans.modules.autoupdate.updateprovider.FeatureItem; |
| import org.openide.util.NbBundle; |
| |
| |
| public class FeatureUpdateUnitImpl extends UpdateUnitImpl { |
| private static final Logger LOG = Logger.getLogger (FeatureUpdateUnitImpl.class.getName()); |
| private UpdateElement installedElement = null; |
| private UpdateElement updateElement = null; |
| private boolean initialized = false; |
| private UpdateManager.TYPE type; |
| |
| public FeatureUpdateUnitImpl (String codename, UpdateManager.TYPE type) { |
| super (codename); |
| this.type = type; |
| } |
| |
| @Override |
| public UpdateElement getInstalled () { |
| synchronized(this) { |
| initializeFeature (); |
| } |
| return installedElement; |
| } |
| |
| @Override |
| public List<UpdateElement> getAvailableUpdates () { |
| synchronized(this) { |
| initializeFeature (); |
| } |
| |
| if (updateElement == null) { |
| return Collections.emptyList (); |
| } |
| |
| String id = updateElement.getCodeName (); |
| LOG.log (Level.FINE, "UpdateElement " + id + "[" + |
| (installedElement == null ? "<not installed>" : installedElement.getSpecificationVersion ()) + "] has update " + |
| id + "[" + updateElement.getSpecificationVersion () + "]"); |
| |
| return Collections.singletonList (updateElement); |
| } |
| |
| @Override |
| public TYPE getType () { |
| return type; |
| } |
| |
| private void initializeFeature () { |
| if(initialized) { |
| return; |
| } |
| List<UpdateElement> featureElements = getUpdates (); |
| |
| installedElement = null; |
| updateElement = null; |
| |
| UpdateElement installedFeatureElement = null; |
| FeatureUpdateElementImpl featureImpl = null; |
| |
| Set<ModuleUpdateElementImpl> installedModules = new HashSet<ModuleUpdateElementImpl> (); |
| Set<FeatureUpdateElementImpl> installedFeatures = new HashSet<FeatureUpdateElementImpl> (); |
| |
| Set<ModuleUpdateElementImpl> availableModules = new HashSet<ModuleUpdateElementImpl> (); |
| Set<FeatureUpdateElementImpl> availableFeatures = new HashSet<FeatureUpdateElementImpl> (); |
| |
| Set<ModuleUpdateElementImpl> missingModules = new HashSet<ModuleUpdateElementImpl> (); |
| Set<FeatureUpdateElementImpl> missingFeatures = new HashSet<FeatureUpdateElementImpl> (); |
| |
| assert featureElements != null : "FeatureUpdateUnitImpl " + getCodeName () + " contains some available elements."; |
| for (UpdateElement el : featureElements) { |
| |
| featureImpl = (FeatureUpdateElementImpl) Trampoline.API.impl (el); |
| boolean installed = false; |
| |
| for (ModuleUpdateElementImpl moduleImpl : featureImpl.getContainedModuleElements ()) { |
| installed |= moduleImpl.getUpdateUnit ().getInstalled () != null; |
| UpdateElement iue = moduleImpl.getUpdateUnit ().getInstalled (); |
| UpdateElementImpl iuei = iue == null ? null : Trampoline.API.impl (iue); |
| assert iuei == null || iuei instanceof ModuleUpdateElementImpl : "Impl of " + iue + " is instanceof ModuleUpdateElementImpl"; |
| if (iue != null) { |
| installedModules.add ((ModuleUpdateElementImpl) iuei); |
| } else { |
| LOG.log (Level.FINER, this.getCodeName () + " misses required module " + moduleImpl.getUpdateElement ()); |
| missingModules.add (moduleImpl); |
| } |
| if (! moduleImpl.getUpdateUnit ().getAvailableUpdates ().isEmpty ()) { |
| UpdateElement aue = moduleImpl.getUpdateUnit ().getAvailableUpdates ().get (0); |
| UpdateElementImpl auei = Trampoline.API.impl (aue); |
| assert auei instanceof ModuleUpdateElementImpl : "Impl of " + aue + " is instanceof ModuleUpdateElementImpl"; |
| availableModules.add ((ModuleUpdateElementImpl) auei); |
| LOG.log (Level.FINER, this + " has a update of module " + moduleImpl.getUpdateElement () + " to " + auei.getUpdateElement ()); |
| } |
| } |
| |
| for (FeatureUpdateElementImpl dependingFeatureImpl : featureImpl.getDependingFeatures()) { |
| installed |= dependingFeatureImpl.getUpdateUnit().getInstalled() != null; |
| UpdateElement iue = dependingFeatureImpl.getUpdateUnit().getInstalled(); |
| UpdateElementImpl iuei = iue == null ? null : Trampoline.API.impl(iue); |
| assert iuei == null || iuei instanceof FeatureUpdateElementImpl : "Impl of " + iue + " is instanceof FeatureUpdateElementImpl"; |
| if (iuei != null) { |
| installedFeatures.add((FeatureUpdateElementImpl) iuei); |
| } else { |
| LOG.log(Level.FINER, this.getCodeName() + " misses required module " + featureImpl.getUpdateElement()); |
| missingFeatures.add(featureImpl); |
| } |
| if (! dependingFeatureImpl.getUpdateUnit().getAvailableUpdates().isEmpty()) { |
| UpdateElement aue = dependingFeatureImpl.getUpdateUnit().getAvailableUpdates().get(0); |
| UpdateElementImpl auei = Trampoline.API.impl(aue); |
| assert auei instanceof FeatureUpdateElementImpl : "Impl of " + aue + " is instanceof FeatureUpdateElementImpl"; |
| availableFeatures.add((FeatureUpdateElementImpl) auei); |
| LOG.log(Level.FINER, this + " has a update of feature " + dependingFeatureImpl.getUpdateElement() + " to " + auei.getUpdateElement()); |
| } |
| } |
| |
| if (installed) { |
| installedFeatureElement = el; |
| } |
| } |
| |
| boolean isStandalone = UpdateManager.TYPE.STANDALONE_MODULE == getType (); |
| |
| // if some element is whole installed |
| if (installedFeatureElement != null) { |
| // create new one element contains all installed modules |
| FeatureItem item = ArtificialFeaturesProvider.createFeatureItem ( |
| getCodeName (), |
| installedModules, |
| installedFeatures, |
| featureImpl, |
| isStandalone ? null : presentAddionallyDescription (installedModules, presentMissingModules (missingModules))); |
| FeatureUpdateElementImpl featureElementImpl = new FeatureUpdateElementImpl ( |
| item, |
| installedFeatureElement.getSource (), |
| installedModules, |
| installedFeatures, |
| featureImpl.getType ()); |
| installedElement = Trampoline.API.createUpdateElement (featureElementImpl); |
| featureElementImpl.setUpdateUnit (installedFeatureElement.getUpdateUnit ()); |
| } |
| |
| // add also new update element |
| if (! featureElements.isEmpty ()) { |
| if (! availableModules.isEmpty () || ! availableFeatures.isEmpty()) { |
| // add available modules or features to missing |
| missingModules.addAll (availableModules); |
| FeatureItem item = ArtificialFeaturesProvider.createFeatureItem ( |
| getCodeName (), |
| availableModules, |
| availableFeatures, |
| featureImpl, |
| isStandalone ? null : presentAddionallyDescription (presentUpdatableModules (/* XXX */missingModules), installedModules)); |
| FeatureUpdateElementImpl featureElementImpl = new FeatureUpdateElementImpl ( |
| item, |
| featureElements.get (0).getSource (), |
| availableModules, |
| availableFeatures, |
| featureImpl.getType ()); |
| updateElement = Trampoline.API.createUpdateElement (featureElementImpl); |
| featureElementImpl.setUpdateUnit (featureElements.get (0).getUpdateUnit ()); |
| addUpdate (updateElement); |
| } |
| } |
| |
| initialized = true; |
| } |
| |
| @Override |
| public void setInstalled (UpdateElement installed) { |
| assert false : "Invalid calling setInstalled (" + installed + ") on FeatureUpdateUnitImpl."; |
| } |
| |
| @Override |
| public void setAsUninstalled () { |
| synchronized (this) { |
| initialized = false; |
| } |
| } |
| |
| @Override |
| public void updateInstalled (UpdateElement installed) { |
| synchronized (this) { |
| initialized = false; |
| } |
| } |
| |
| private static String getDisplayNames (Set<ModuleUpdateElementImpl> moduleImpls) { |
| assert moduleImpls != null && ! moduleImpls.isEmpty () : "Some ModuleUpdateElementImpl must found to take its display names."; |
| String res = ""; |
| for (ModuleUpdateElementImpl moduleImpl : moduleImpls) { |
| res += (res.length () == 0 ? "" : ", ") + moduleImpl.getDisplayName (); |
| } |
| return res; |
| } |
| |
| private static String presentMissingModules (Set<ModuleUpdateElementImpl> missingModuleImpls) { |
| if (missingModuleImpls.isEmpty ()) { |
| return ""; |
| } |
| |
| boolean once = missingModuleImpls.size () == 1; |
| String res; |
| if (once) { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_MissingModule", getDisplayNames (missingModuleImpls)); |
| } else { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_MissingModules", getDisplayNames (missingModuleImpls)); |
| } |
| |
| return res; |
| } |
| |
| private static String presentUpdatableModules (Set<ModuleUpdateElementImpl> updatebleModuleImpls) { |
| if (updatebleModuleImpls.isEmpty ()) { |
| return ""; |
| } |
| |
| boolean once = updatebleModuleImpls.size () == 1; |
| String res; |
| if (once) { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_UpdatableModule", getDisplayNames (updatebleModuleImpls)); |
| } else { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_UpdatableModules", getDisplayNames (updatebleModuleImpls)); |
| } |
| |
| return res; |
| } |
| |
| private static String presentIncludedModules (Set<ModuleUpdateElementImpl> includedModuleImpls) { |
| if (includedModuleImpls.isEmpty ()) { |
| return ""; |
| } |
| |
| boolean once = includedModuleImpls.size () == 1; |
| String res; |
| if (once) { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_ContainedModule", getDisplayNames (includedModuleImpls)); |
| } else { |
| res = NbBundle.getMessage (FeatureUpdateUnitImpl.class, "FeatureUpdateUnitImpl_ContainedModules", getDisplayNames (includedModuleImpls)); |
| } |
| |
| return res; |
| } |
| |
| private static String presentAddionallyDescription (Set<ModuleUpdateElementImpl> included, String more) { |
| String add = presentIncludedModules (included) + more; |
| return add.length () > 0 ? add : null; |
| } |
| |
| private static String presentAddionallyDescription (String more, Set<ModuleUpdateElementImpl> included) { |
| String add = more + presentIncludedModules (included); |
| return add.length () > 0 ? add : null; |
| } |
| |
| @Override |
| public boolean isPending () { |
| return UpdateUnitFactory.getDefault().isScheduledForRestart (getUpdateUnit ()); |
| } |
| |
| @Override |
| public UpdateUnit getVisibleAncestor() { |
| return this.getUpdateUnit(); |
| } |
| } |