| /*=============================================================================# |
| # Copyright (c) 2010, 2020 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.rhelp.core; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import static org.eclipse.statet.internal.rhelp.core.RHelpCoreInternals.DEBUG; |
| |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| import org.eclipse.statet.jcommons.status.InfoStatus; |
| |
| import org.eclipse.statet.internal.rhelp.core.index.REnvIndexWriter; |
| import org.eclipse.statet.rhelp.core.REnvHelp; |
| import org.eclipse.statet.rhelp.core.REnvHelpConfiguration; |
| import org.eclipse.statet.rhelp.core.RHelpCore; |
| import org.eclipse.statet.rhelp.core.RHelpManager; |
| import org.eclipse.statet.rhelp.core.RPkgHelp; |
| import org.eclipse.statet.rj.renv.core.RPkgBuilt; |
| |
| |
| @NonNullByDefault |
| public class REnvHelpIndexChecker { |
| |
| |
| private static boolean equalVersion(final RPkgBuilt pkg1, final @Nullable RPkgBuilt pkg2) { |
| return (pkg2 != null |
| && pkg1.getVersion().equals(pkg2.getVersion()) |
| && pkg1.getBuilt().equals(pkg2.getBuilt()) ); |
| } |
| |
| |
| private final RHelpManager rHelpManager; |
| |
| private final REnvHelpConfiguration rEnvConfig; |
| |
| private int newPkg; |
| private int changedPkg; |
| private int newChange= -1; |
| |
| private Map<String, RPkgBuilt> needUpdate= new HashMap<>(); |
| private Map<String, RPkgBuilt> needUpdatePrevious= new HashMap<>(); |
| |
| private @Nullable Object indexLock; |
| |
| private @Nullable REnvHelp rEnvHelp; |
| private boolean rEnvHelpLock; |
| |
| private boolean inPackageCheck; |
| |
| |
| public REnvHelpIndexChecker(final RHelpManager rHelpManager, |
| final REnvHelpConfiguration rEnvConfig) { |
| this.rHelpManager= nonNullAssert(rHelpManager); |
| this.rEnvConfig= nonNullAssert(rEnvConfig); |
| |
| try { |
| final Path directory= SerUtil.getIndexDirectoryPath(this.rEnvConfig); |
| if (directory != null) { |
| try { |
| // directory writable? |
| if (!isWritable(directory)) { |
| if (DEBUG) { |
| RHelpCoreInternals.log(new InfoStatus(RHelpCore.BUNDLE_ID, |
| String.format("The index directory '%1$s' is not writable.", //$NON-NLS-1$ |
| directory.toString() ), |
| null)); |
| } |
| return; |
| } |
| } |
| catch (final IOException e) { |
| RHelpCoreInternals.log(new InfoStatus(RHelpCore.BUNDLE_ID, |
| String.format("The index directory '%1$s' is not accessible.", //$NON-NLS-1$ |
| directory.toString() ), |
| e)); |
| } |
| } |
| } |
| catch (final Exception e) {} |
| } |
| |
| |
| private boolean isWritable(final Path directory) throws IOException { |
| final Path testFile= directory.resolve("test" + System.nanoTime()); //$NON-NLS-1$ |
| try { |
| if (!Files.isDirectory(directory)) { |
| Files.createDirectories(directory); |
| } |
| Files.createFile(testFile); |
| Files.delete(testFile); |
| } |
| catch (final IOException e) { |
| return false; |
| } |
| return true; |
| } |
| |
| |
| public boolean beginCheck() { |
| this.newChange= (this.newChange < 0) ? 1 : 0; |
| |
| if (this.rEnvConfig == null) { |
| return false; |
| } |
| |
| final REnvHelp envHelp= this.rHelpManager.getHelp(this.rEnvConfig.getREnv()); |
| if ((envHelp != null) ? (this.rEnvHelp == null) : this.rEnvHelp != null) { |
| this.newChange= 1; |
| } |
| this.rEnvHelp= envHelp; |
| this.rEnvHelpLock= (this.rEnvHelp != null); |
| |
| if (!this.rEnvConfig.equals(this.rEnvConfig.getREnv().get(REnvHelpConfiguration.class))) { |
| return false; |
| } |
| |
| this.indexLock= this.rHelpManager.beginIndexCheck(this.rEnvConfig.getREnv()); |
| return (this.indexLock != null); |
| } |
| |
| public void beginPackageCheck() { |
| this.inPackageCheck= true; |
| |
| final Map<String, RPkgBuilt> tmp= this.needUpdate; |
| this.needUpdate= this.needUpdatePrevious; |
| this.needUpdatePrevious= tmp; |
| |
| this.newPkg= 0; |
| this.changedPkg= 0; |
| this.newChange= 0; |
| } |
| |
| public void checkPackage(final RPkgBuilt pkgInfo) { |
| if (!REnvIndexWriter.IGNORE_PKG_NAMES.contains(pkgInfo.getName())) { |
| final RPkgHelp pkgHelp= this.rEnvHelp.getPkgHelp(pkgInfo.getName()); |
| if (pkgHelp == null) { |
| this.newPkg++; |
| this.needUpdate.put(pkgInfo.getName(), pkgInfo); |
| if (this.newChange == 0 && !equalVersion(pkgInfo, this.needUpdatePrevious.get(pkgInfo.getName()))) { |
| this.newChange= 1; |
| } |
| } |
| else if (!RPkgBuilt.equalsBuilt(pkgInfo, pkgHelp.getPkgDescription())) { |
| this.changedPkg++; |
| this.needUpdate.put(pkgInfo.getName(), pkgInfo); |
| if (this.newChange == 0 && !equalVersion(pkgInfo, this.needUpdatePrevious.get(pkgInfo.getName()))) { |
| this.newChange= 1; |
| } |
| } |
| } |
| } |
| |
| public void endPackageCheck() { |
| this.inPackageCheck= false; |
| |
| this.needUpdatePrevious.clear(); |
| } |
| |
| public void cancelCheck() { |
| if (this.inPackageCheck) { |
| final Map<String, RPkgBuilt> tmp= this.needUpdate; |
| this.needUpdate= this.needUpdatePrevious; |
| this.needUpdatePrevious= tmp; |
| } |
| |
| this.needUpdatePrevious.clear(); |
| unlock(); |
| } |
| |
| public void finalCheck() { |
| unlock(); |
| } |
| |
| private void unlock() { |
| if (this.rEnvHelpLock) { |
| this.rEnvHelpLock= false; |
| this.rEnvHelp.unlock(); |
| } |
| } |
| |
| public void release() { |
| if (this.indexLock != null) { |
| this.rHelpManager.endIndexCheck(this.indexLock); |
| this.indexLock= null; |
| } |
| } |
| |
| |
| public boolean hasNewChanges() { |
| return (this.newChange > 0); |
| } |
| |
| public boolean needsComplete() { |
| return (this.rEnvHelp == null); |
| } |
| |
| public boolean hasPackageChanges() { |
| return (this.newPkg > 0 || this.changedPkg > 0); |
| } |
| |
| public int getNewPackageCount() { |
| return this.newPkg; |
| } |
| |
| public int getChangedPackageCount() { |
| return this.changedPkg; |
| } |
| |
| } |