1. mst
  2. ooo340

Commits

Joachim Lingner  committed 9f0dfb3

jl155 #i111592# online update, updating user extension if it would override a required shared extension.

  • Participants
  • Parent commits 4ff985c
  • Branches default

Comments (0)

Files changed (5)

File desktop/source/deployment/gui/dp_gui.hrc

View file
 
 #define RID_STR_UPDATE_BROWSERBASED              (RID_DEPLOYMENT_GUI_START+150)
 #define RID_STR_UPDATE_VERSION                   (RID_DEPLOYMENT_GUI_START+151)
+#define RID_STR_UPDATE_SHARED                    (RID_DEPLOYMENT_GUI_START+152)
 #define RID_DLG_LICENSE							RID_DEPLOYMENT_LICENSE_START
 
 

File desktop/source/deployment/gui/dp_gui_extlistbox.cxx

View file
 }
 
 //------------------------------------------------------------------------------
+
+//Do not call anything on xPackage anymore. removeEntry is called as a result of
+//XExtensionManager::removeExtension which already calls XPackage::dispose.
 void ExtensionBox_Impl::removeEntry( const uno::Reference< deployment::XPackage > &xPackage )
 {
     if ( ! m_bInDelete )
                 // the entry will be moved into the m_vRemovedEntries list which will be
                 // cleared on the next paint event
                 m_vRemovedEntries.push_back( *iIndex );
+                //erase is safe here because we break always after calling
+                //erase. That is, the iterator will not be used again.
                 m_vEntries.erase( iIndex );
-                (*iIndex)->m_xPackage->removeEventListener(
-                    uno::Reference<lang::XEventListener>(m_xRemoveListener, uno::UNO_QUERY));
 
                 m_bNeedsRecalc = true;
                 Invalidate();

File desktop/source/deployment/gui/dp_gui_updatedata.cxx

View file
 namespace {
 
 ::rtl::OUString getDisplayString(::rtl::OUString const & name,
-                        ::rtl::OUString const & version,
-    bool bBrowserUpdate)
+                                 ::rtl::OUString const & version,
+                                 bool bBrowserUpdate, bool bShared)
 {
     rtl::OUStringBuffer b(name);
     //The extension dialog does not show a string "Version" in front of the version.
             vos::OGuard g( Application::GetSolarMutex() );
             b.append(String(DpGuiResId(RID_STR_UPDATE_BROWSERBASED)));
         }
-    }        
+    }
+    if (bShared)
+    {
+        b.append(static_cast< sal_Unicode >(' '));
+        b.append(String(DpGuiResId(RID_STR_UPDATE_SHARED)));
+    }
     return b.makeStringAndClear();
 }
 
         sWebsiteURL = *updateWebsiteURL;
     onlineVersion = updateVersion = infoset.getVersion();
 
-    sUpdateDisplayString = getDisplayString(name, onlineVersion, sWebsiteURL.getLength());
+    sUpdateDisplayString = getDisplayString(
+        name, onlineVersion, sWebsiteURL.getLength(), bShared);
 };
 
 UpdateData::UpdateData(
         sWebsiteURL = *updateWebsiteURL;
 
     onlineVersion = updateVersion = info.getVersion();
-    sUpdateDisplayString = getDisplayString(name, onlineVersion, sWebsiteURL.getLength());
+    sUpdateDisplayString = getDisplayString(
+        name, onlineVersion, sWebsiteURL.getLength(), bShared);
 
     requiredUpdates = getInterExtensionDependencies(info);
 

File desktop/source/deployment/gui/dp_gui_updatedialog.cxx

View file
 
 struct MatchDependingExtension
 {
-    rtl::OUString m_identifier;
-    rtl::OUString m_version;
+    const rtl::OUString m_identifier;
+    const rtl::OUString m_version;
 
     MatchDependingExtension(dp_gui::UpdateData const & data);
     bool operator () (uno::Reference<xml::dom::XElement> const & dep) const;
 };
 
 MatchDependingExtension::MatchDependingExtension(
-    dp_gui::UpdateData const & data)
+    dp_gui::UpdateData const & data):
+    m_identifier(data.identifier), m_version(data.updateVersion)
 {
-    m_identifier = data.identifier;
-    m_version = data.updateVersion;
 }
 
 bool MatchDependingExtension::operator ()( uno::Reference<xml::dom::XElement> const & dep ) const
 {
     rtl::OUString m_identifier;
     rtl::OUString m_version;
+    const bool m_bShared;
 
-    MatchRequiredExtension(uno::Reference<xml::dom::XElement> const & dep);
+    MatchRequiredExtension(uno::Reference<xml::dom::XElement> const & dep, bool bShared);
     bool operator () (dp_gui::UpdateData const & dep) const;
 };
 
 MatchRequiredExtension::MatchRequiredExtension(
-    uno::Reference<xml::dom::XElement> const & dep)
+    uno::Reference<xml::dom::XElement> const & dep, bool bShared):m_bShared(bShared)
 {   
     m_identifier = dep->getAttribute(OUSTR("identifier"));
     m_version = dep->getAttribute(OUSTR("minimum-version"));
 bool MatchRequiredExtension::operator ()( dp_gui::UpdateData const & data ) const
 {
     if (m_identifier.equals(data.identifier)
-        && dp_misc::compareVersions(data.updateVersion, m_version) != dp_misc::LESS)
+        && dp_misc::compareVersions(data.updateVersion, m_version) != dp_misc::LESS
+        && data.bIsShared == m_bShared)
         return true;
      return false;
 }
     const rtl::OUString m_identifier;
     const bool bShared;
     FindUpdateData(dp_gui::UpdateData const & data);
+    FindUpdateData( ::rtl::OUString const & identifier, bool bShared);
     bool operator () (dp_gui::UpdateData const & addedData);
 };
 
 {
 }
 
+FindUpdateData::FindUpdateData(::rtl::OUString const & identifier, bool bShared):
+    m_identifier(identifier), bShared(bShared)
+{
+}
+
 bool FindUpdateData::operator () (dp_gui::UpdateData const & addedData)
 {
     if (addedData.identifier.equals(m_identifier)
 
 
 
-struct MatchExtensionWithDependency
-{
-    rtl::OUString m_identifier;
-    rtl::OUString m_version;
+// struct MatchExtensionWithDependency
+// {
+//     rtl::OUString m_identifier;
+//     rtl::OUString m_version;
 
-    MatchExtensionWithDependency(uno::Reference<xml::dom::XNode> const & dep);
-    bool operator () (uno::Reference<deployment::XPackage> const & extension) const;
-};
+//     MatchExtensionWithDependency(uno::Reference<xml::dom::XNode> const & dep);
+//     bool operator () (uno::Reference<deployment::XPackage> const & extension) const;
+// };
 
-MatchExtensionWithDependency::MatchExtensionWithDependency(
-    uno::Reference<xml::dom::XNode> const & dep)
-{
-    const uno::Reference<xml::dom::XElement> elem(dep, uno::UNO_QUERY_THROW);
-    m_identifier = elem->getAttribute(OUSTR("identifier"));
-    m_version = elem->getAttribute(OUSTR("minimum-version"));
-}
+// MatchExtensionWithDependency::MatchExtensionWithDependency(
+//     uno::Reference<xml::dom::XNode> const & dep)
+// {
+//     const uno::Reference<xml::dom::XElement> elem(dep, uno::UNO_QUERY_THROW);
+//     m_identifier = elem->getAttribute(OUSTR("identifier"));
+//     m_version = elem->getAttribute(OUSTR("minimum-version"));
+// }
 
-bool MatchExtensionWithDependency::operator ()( uno::Reference<deployment::XPackage> const & extension) const
-{
-    if (m_identifier.equals(dp_misc::getIdentifier(extension))
-        && dp_misc::compareVersions(extension->getVersion(), m_version) != dp_misc::LESS)
-        return true;
-     return false;
-}
+// bool MatchExtensionWithDependency::operator ()( uno::Reference<deployment::XPackage> const & extension) const
+// {
+//     if (m_identifier.equals(dp_misc::getIdentifier(extension))
+//         && dp_misc::compareVersions(extension->getVersion(), m_version) != dp_misc::LESS)
+//         return true;
+//      return false;
+// }
 
 
 } //end namespace
     USHORT        m_nIndex;
     rtl::OUString m_aName;
     rtl::OUString m_identifier;
+    bool          m_bShared;
 
     Index( Kind theKind, USHORT nIndex, const rtl::OUString &rName,
-           const rtl::OUString & rIdentifier);
+           const rtl::OUString & rIdentifier, bool bShared);
 };
 
 //------------------------------------------------------------------------------
 UpdateDialog::Index::Index( Kind theKind, USHORT nIndex, const rtl::OUString &rName,
-                            rtl::OUString const & rIdentifier):
+                            rtl::OUString const & rIdentifier, bool bShared):
     m_eKind( theKind ),
     m_bIgnored( false ),
     m_nIndex( nIndex ),
     m_aName( rName ),
-    m_identifier(rIdentifier)
+    m_identifier(rIdentifier),
+    m_bShared(bShared)
 {}
 
 //------------------------------------------------------------------------------
     {
         dp_misc::DescriptionInfoset info(
             m_context, uno::Reference<xml::dom::XNode>(dependency, uno::UNO_QUERY_THROW));
-        const ::boost::optional< ::rtl::OUString> opt_id =  info.getIdentifier();
-        ::rtl::OUString id;
-        if (opt_id)
-            id = *opt_id;
-        OSL_ASSERT(id.getLength());
         RequiredUpdate mapValue(
-            id,
+            identifier,
             info.getLocalizedDisplayName(),
-            info.getVersion(),
+            dependency->getAttribute(OUSTR("minimum-version")),
             it_upd_info->second);
         
         inout_requiredUpdates[it_upd_info->first] = mapValue;
                             vecUnknown))
                     {
                         vecRequiredExtensions.push_back(cur_dep);
-                        //Determine if the required updates are already in the
-                        //m_vExtensionList. If not then we create an additional
-                        //UpdateData.
+                        //Create UpdateData for all required extensions, unless they already
+                        //exist
                         typedef RequiredUpdatesMap::const_iterator CIT_REQ;
                         for (CIT_REQ i_req = mapRequiredUpdates.begin();
                              i_req != mapRequiredUpdates.end(); i_req++)
                         {
-                            ::std::vector<uno::Reference<deployment::XPackage> >::const_iterator iext =
-                                ::std::find_if(m_vExtensionList.begin(), m_vExtensionList.end(),
-                                               MatchExtensionWithDependency(
-                                                   i_req->second.m_updateInformation));
-                            if (iext == m_vExtensionList.end())
+                            dp_misc::DescriptionInfoset infoReqExt(
+                                m_context, i_req->second.m_updateInformation);
+                            ::boost::optional< ::rtl::OUString> id = infoReqExt.getIdentifier();
+                            if (id)
                             {
-                                //Also look in vecUpData if it was already added
-                                //We only need to look for the identifier, because there is always
-                                //only one extension  with a particular identifier in the map
-                                //that we get with getOnlineUpdateInfos
-                                dp_misc::DescriptionInfoset infoReqExt(
-                                    m_context, i_req->second.m_updateInformation);
-                                ::boost::optional< ::rtl::OUString> id = infoReqExt.getIdentifier();
-                                if (id)
+                                ::std::vector<UpdateData>::const_iterator iupdata =
+                                    ::std::find_if(vecUpData.begin(), vecUpData.end(),
+                                                   FindUpdateData(*id, bShared ));
+                                if (iupdata == vecUpData.end())
                                 {
-                                    ::std::vector<UpdateData>::const_iterator iupdata =
-                                        ::std::find_if(vecUpData.begin(), vecUpData.end(),
-                                                       MatchUpdateData(*id));
-                                    if (iupdata == vecUpData.end())
+                                    UpdateData data(m_context, i_req->second.m_displayName,
+                                                    i_req->second.m_updateInformation, bShared, true);
+                                    vecUpData.push_back(data);
+
+                                    //We must prevent the case that a
+                                    //required shared extension is inactive
+                                    //and there is a user extension which
+                                    //does not satisfy the dependency
+                                    if (bShared && needsUserUpdate(i_req->second))
                                     {
-                                        UpdateData data(m_context, i_req->second.m_displayName,
-                                                        i_req->second.m_updateInformation, bShared, true);
-                                        vecUpData.push_back(data);
-
-                                        //We must prevent the case that a
-                                        //required shared extension is inactive
-                                        //and there is a user extension which
-                                        //does not satisfy the dependency
-                                        if (bShared && needsUserUpdate(i_req->second))
+                                        //Only create new UpdateData unless it already exists
+                                        ::std::vector<UpdateData>::const_iterator iupdataShared =
+                                            ::std::find_if(vecUpData.begin(), vecUpData.end(),
+                                                           FindUpdateData(*id, false));
+                                        if (iupdataShared == vecUpData.end())
                                         {
                                             UpdateData data(m_context, i_req->second.m_displayName,
-                                                        i_req->second.m_updateInformation, false, true);
-                                            vecUpData.push_back(data);   
-                                       }
+                                                            i_req->second.m_updateInformation, false, true);
+                                            vecUpData.push_back(data);
+                                        }
                                     }
                                 }
                             }
                             vecUnsolvedDeps.push_back(*iu);
                     }
                 }
-                //if all solved construct UpdateData
-                UpdateData data(m_context, *i, it_upInfo->second, vecUnsolvedDeps,
-                                vecRequiredExtensions, bShared, false);
-                vecUpData.push_back(data);
+                //Create UpdateData even if there are unsatisfied dependencies.
+                //This update will be displayed as "disabled" when one presses "Show all"
+                //Make sure to only show it once
+                ::std::vector<UpdateData>::const_iterator iupdata =
+                      ::std::find_if(vecUpData.begin(), vecUpData.end(),
+                                     FindUpdateData(dp_misc::getIdentifier(*i), bShared ));
+                if (iupdata == vecUpData.end())
+                {
+                    UpdateData data(m_context, *i, it_upInfo->second, vecUnsolvedDeps,
+                                    vecRequiredExtensions, bShared, false);
+                    vecUpData.push_back(data);
+                }
             }
         }
      }
     
 
 //Currently the user does not see shared extensions if there are user extensions
-//with the same identifier are installed. The update dialog does also NOT
-//display an update for user and shared (both with the same id). It just shows
-//one update. If it is installed for user and shared depends in most cases on
-//having an extension with that id installed in the respective repository.
-//That is, even if only one update is displayed it may be applied two times, for
-//user and shared extension.
+//with the same identifier are installed.
 //
 //For
 //example, there is a shared extension and no user extension. Then the update is
 //update for the same, then the required extension is NOT installed in the user
 //repository.
 
-//Tere can be the case that there is a local update AND a online update with a
+//There can be the case that there is a local update AND a online update with a
 //better version but unsatisfied dependencies. Then the local update would be
 //used and when checking the next time, the disabled online update would be
-//displayd
+//displayed
 
 //The information what extensions are to be updated is contained in
-//m_vExtensionList. It contains exactly one extension for one particular
-//identifier. That is, it does not reflect necessarily the extension which was
-//selected by the user. The extensions in m_vExtensionList are those which have
-//the highest versions among the group of extensions with the same identifiers
-//from the bundled, shared and user repositoriy. The idea is, that newer
-//extensions may contain more recent update information, provided that they
-//provide their own update information.
-
-//-----
-//If there is are two extensions with the same id (shared, user) then both extensions are
-//in m_vExtensionList. Onle when user chooses "Check updates" button.
+//m_vExtensionList. It contains the extension which was selected in the dialog
+//or all user and bundled extensions.
 void UpdateDialog::Thread::execute()
 {
     {
 {
     USHORT nIndex = sal::static_int_cast< USHORT >( m_enabledUpdates.size() );
     UpdateDialog::Index *pEntry = new UpdateDialog::Index(
-        ENABLED_UPDATE, nIndex, name, data.identifier);
+        ENABLED_UPDATE, nIndex, name, data.identifier, data.bIsShared);
     m_enabledUpdates.push_back( data );
     m_ListboxEntries.push_back( pEntry );
 
 {
     USHORT nIndex = sal::static_int_cast< USHORT >( m_disabledUpdates.size() );
     UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, nIndex, data.name,
-                                                           data.identifier);
+                                                           data.identifier, false);
 
     m_disabledUpdates.push_back( data );
     m_ListboxEntries.push_back( pEntry );
 {
     USHORT nIndex = sal::static_int_cast< USHORT >( m_specificErrors.size() );
     UpdateDialog::Index *pEntry = new UpdateDialog::Index( DISABLED_UPDATE, nIndex, data.name,
-        data.identifier);
+                                                           data.identifier, false);
 
     m_specificErrors.push_back( data );
     m_ListboxEntries.push_back( pEntry );
             //now we must also find the extensions which depend from this one too
             ::std::vector<dp_gui::UpdateData> vecDep = getAllDependingUpdates(*i);
             for (CITU ii = vecDep.begin(); ii != vecDep.end(); ii++)
-                vecReturn.push_back(*ii);
+            {
+                if (::std::find_if(vecReturn.begin(), vecReturn.end(), FindUpdateData(*ii))
+                    == vecReturn.end())
+                    vecReturn.push_back(*ii);
+            }
             //only the the selected updates are needed
             if (m_updates.IsChecked(getListBoxPosition(*i)))
+            {
+                if (::std::find_if(vecReturn.begin(), vecReturn.end(), FindUpdateData(*i))
+                    == vecReturn.end())
                 vecReturn.push_back(*i);
+            }
         }
     }
     return vecReturn;
         typedef ::std::vector< dp_gui::UpdateData >::const_iterator CIR;
         CIR iReq =
             ::std::find_if(m_enabledUpdates.begin(),
-                           m_enabledUpdates.end(), MatchRequiredExtension(*i));
+                           m_enabledUpdates.end(), MatchRequiredExtension(*i, upData.bIsShared));
         if (iReq != m_enabledUpdates.end())
         {
             ::std::vector<dp_gui::UpdateData> vecReq = getAllRequiredUpdates(*iReq);
             typedef ::std::vector<dp_gui::UpdateData>::const_iterator CIR;
             for (CIR ii = vecReq.begin(); ii != vecReq.end(); ii++)
-                vecReturn.push_back(*ii);
+            {
+                if (::std::find_if(vecReturn.begin(), vecReturn.end(), FindUpdateData(*ii))
+                    == vecReturn.end())
+                    vecReturn.push_back(*ii);
+            }
             //only the unselected updates are needed
             if (!m_updates.IsChecked(getListBoxPosition(*iReq)))
                 vecReturn.push_back(*iReq);
         }
         
+        if (upData.bIsShared && iReq != m_enabledUpdates.end())
+        {
+            iReq =
+                ::std::find_if(
+                    m_enabledUpdates.begin(), m_enabledUpdates.end(),
+                    MatchRequiredExtension(*i, false));
+            if (iReq != m_enabledUpdates.end())
+            {
+                ::std::vector<dp_gui::UpdateData> vecReq = getAllRequiredUpdates(*iReq);
+                typedef ::std::vector<dp_gui::UpdateData>::const_iterator CIR;
+                for (CIR ii = vecReq.begin(); ii != vecReq.end(); ii++)
+                {
+                    if (::std::find_if(vecReturn.begin(), vecReturn.end(), FindUpdateData(*ii))
+                        == vecReturn.end())
+                        vecReturn.push_back(*ii);
+                }
+                //only the unselected updates are needed
+                if (!m_updates.IsChecked(getListBoxPosition(*iReq)))
+                    vecReturn.push_back(*iReq);
+            }
+        }
     }
+
+    
     return vecReturn;
 }
 
             //not in vecUnorderedUpdates then it is already installed.
             ::std::vector<dp_gui::UpdateData>::const_iterator iUpData =
                 ::std::find_if(vecUnorderedUpdates.begin(), vecUnorderedUpdates.end(),
-                               MatchUpdateData((*i)->getAttribute(OUSTR("identifier"))));
+                               FindUpdateData((*i)->getAttribute(OUSTR("identifier")), curData.bIsShared));
             if (iUpData != vecUnorderedUpdates.end())
                 addUpdateSorted(*iUpData, vecUnorderedUpdates);
         }
         //OSL_ASSERT(must nut be added yet, otherwise ring dependency
         OSL_ASSERT(0);
 #endif
+        //When installing a required shared extension we must make sure that
+        //first a user extension is installed. There may be a user extension
+        //which a version less thant the required one. The shared required
+        //extension would not be active. The update dialog ensures that the user
+        //extension is also updated. The user update must then be installed first.
+        if (curData.bIsShared && curData.bIsRequired)
+        {
+            ::std::vector< dp_gui::UpdateData >::const_iterator iDataUnordered =
+                ::std::find_if(vecUnorderedUpdates.begin(), vecUnorderedUpdates.end(),
+                               FindUpdateData(curData.identifier, false));
+            if (iDataUnordered != vecUnorderedUpdates.end())
+            {
+                //There is a user update available in vecUnorderedUpdates
+                addUpdateSorted(*iDataUnordered, vecUnorderedUpdates);
+            }   
+        }
         m_updateData.push_back(curData);
     }
-
 }
 
 void UpdateDialog::addUpdatesSorted(
         pEntry = static_cast< UpdateDialog::Index const * >(
             m_updates.GetEntryData(i++));
         if (pEntry != NULL
-            && pEntry->m_identifier.equals(data.identifier))
+            && pEntry->m_identifier.equals(data.identifier)
+            && pEntry->m_bShared == data.bIsShared)
             break;
     }
     while (pEntry != NULL);
             else
             {
                 //The update was checked. Make sure all required updates are also
-                //checked. Because all updates are checked per default, we do not inform
-                //the user
+                //checked. 
                 const ::std::vector<UpdateData> allReq =
                     getAllRequiredUpdates(m_enabledUpdates[pos]);
                 if (allReq.size())

File desktop/source/deployment/gui/dp_gui_updatedialog.src

View file
     Text[en-US] = "Version";
 };
 
+String RID_STR_UPDATE_SHARED
+{
+    Text[en-US] = "(shared)";
+};
 
+