diff --git a/core/pom.xml b/core/pom.xml index f5d23e5a01..2b90eebd06 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -22,6 +22,41 @@ + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + + + com.github.ben-manes.caffeine:caffeine + + + + + com.github.benmanes.caffeine + org.kohsuke.stapler.shaded.com.github.benmanes.caffeine + + + + + com.github.ben-manes.caffeine:caffeine + + META-INF/** + + + + false + + + + @@ -88,9 +123,9 @@ true - com.google.guava - guava - 11.0.1 + com.github.ben-manes.caffeine + caffeine + 2.9.0 org.kohsuke diff --git a/core/src/main/java/org/kohsuke/stapler/AbstractTearOff.java b/core/src/main/java/org/kohsuke/stapler/AbstractTearOff.java index 07907e6b26..8041aafd8a 100644 --- a/core/src/main/java/org/kohsuke/stapler/AbstractTearOff.java +++ b/core/src/main/java/org/kohsuke/stapler/AbstractTearOff.java @@ -23,8 +23,8 @@ package org.kohsuke.stapler; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.File; @@ -58,7 +58,7 @@ private static final class ExpirableCacheHit { this.script = script; } } - private final Cache> cachedScripts = CacheBuilder.newBuilder().softValues().build(); + private final Cache> cachedScripts = Caffeine.newBuilder().softValues().build(); protected AbstractTearOff(MetaClass owner, Class cltClass) { this.owner = owner; diff --git a/core/src/main/java/org/kohsuke/stapler/CachingScriptLoader.java b/core/src/main/java/org/kohsuke/stapler/CachingScriptLoader.java index 0bb83135c7..60e51df6e0 100644 --- a/core/src/main/java/org/kohsuke/stapler/CachingScriptLoader.java +++ b/core/src/main/java/org/kohsuke/stapler/CachingScriptLoader.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.LoadingCache; import java.net.URL; @@ -25,7 +25,7 @@ public abstract class CachingScriptLoader { * * {@link Optional} is used as Google Collection doesn't allow null values in a map. */ - private final LoadingCache> scripts = CacheBuilder.newBuilder().softValues().build(new CacheLoader>() { + private final LoadingCache> scripts = Caffeine.newBuilder().softValues().build(new CacheLoader>() { public Optional load(String from) { try { return Optional.create(loadScript(from)); @@ -59,7 +59,7 @@ public S findScript(String name) throws E { if (MetaClass.NO_CACHE) return loadScript(name); else - return scripts.getUnchecked(name).get(); + return scripts.get(name).get(); } /** diff --git a/core/src/main/java/org/kohsuke/stapler/Function.java b/core/src/main/java/org/kohsuke/stapler/Function.java index 63678f80bf..0808a6106a 100644 --- a/core/src/main/java/org/kohsuke/stapler/Function.java +++ b/core/src/main/java/org/kohsuke/stapler/Function.java @@ -23,9 +23,9 @@ package org.kohsuke.stapler; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.CacheLoader; +import com.github.benmanes.caffeine.cache.LoadingCache; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -195,7 +195,7 @@ Object bindAndInvoke(Object o, StaplerRequest req, StaplerResponse rsp, Object.. } // if the databinding method is provided, call that - Function binder = PARSE_METHODS.getUnchecked(t); + Function binder = PARSE_METHODS.get(t); if (binder!=RETURN_NULL) { arguments[i] = binder.bindAndInvoke(null,req,rsp); continue; @@ -226,7 +226,7 @@ Object bindAndInvoke(Object o, StaplerRequest req, StaplerResponse rsp, Object.. throw new AssertionError(e); // impossible } - PARSE_METHODS = CacheBuilder.newBuilder().weakKeys().build(new CacheLoader() { + PARSE_METHODS = Caffeine.newBuilder().weakKeys().build(new CacheLoader() { public Function load(Class from) { // MethdFunction for invoking a static method as a static method FunctionList methods = new ClassDescriptor(from).methods.name("fromStapler"); diff --git a/core/src/main/java/org/kohsuke/stapler/export/Iterators.java b/core/src/main/java/org/kohsuke/stapler/export/Iterators.java new file mode 100644 index 0000000000..4022585833 --- /dev/null +++ b/core/src/main/java/org/kohsuke/stapler/export/Iterators.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007 The Guava Authors + * + * Licensed 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.kohsuke.stapler.export; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +/** + * This class contains static utility methods that operate on or return objects of type {@link + * Iterator}. + * + *

Performance notes: Unless otherwise noted, all of the iterators produced in this class + * are lazy, which means that they only advance the backing iteration when absolutely + * necessary. + * + *

See the Guava User Guide section on {@code + * Iterators}. + * + * @author Kevin Bourrillion + * @author Jared Levy + */ +final class Iterators { + private Iterators() {} + + /** + * Returns a view containing the first {@code limitSize} elements of {@code iterator}. If {@code + * iterator} contains fewer than {@code limitSize} elements, the returned view contains all of its + * elements. The returned iterator supports {@code remove()} if {@code iterator} does. + * + * @param iterator the iterator to limit + * @param limitSize the maximum number of elements in the returned iterator + * @throws IllegalArgumentException if {@code limitSize} is negative + */ + static Iterator limit(final Iterator iterator, final int limitSize) { + if (iterator == null) { + throw new NullPointerException(); + } + if (limitSize < 0) { + throw new IllegalArgumentException("limit is negative"); + } + return new Iterator() { + private int count; + + @Override + public boolean hasNext() { + return count < limitSize && iterator.hasNext(); + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + count++; + return iterator.next(); + } + + @Override + public void remove() { + iterator.remove(); + } + }; + } +} diff --git a/core/src/main/java/org/kohsuke/stapler/export/Range.java b/core/src/main/java/org/kohsuke/stapler/export/Range.java index 056a35a04a..463873fd60 100644 --- a/core/src/main/java/org/kohsuke/stapler/export/Range.java +++ b/core/src/main/java/org/kohsuke/stapler/export/Range.java @@ -1,7 +1,5 @@ package org.kohsuke.stapler.export; -import com.google.common.collect.Iterators; - import java.util.Arrays; import java.util.Collection; import java.util.Iterator; diff --git a/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyClassLoaderTearOff.java b/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyClassLoaderTearOff.java index dffd2d8847..c7fede8fe7 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyClassLoaderTearOff.java +++ b/jelly/src/main/java/org/kohsuke/stapler/jelly/JellyClassLoaderTearOff.java @@ -23,9 +23,6 @@ package org.kohsuke.stapler.jelly; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.TagLibrary; @@ -35,6 +32,8 @@ import java.lang.ref.WeakReference; import java.net.URL; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * {@link MetaClassLoader} tear-off for Jelly support. @@ -47,7 +46,7 @@ public class JellyClassLoaderTearOff { /** * See {@link JellyClassTearOff#scripts} for why we use {@link WeakReference} here. */ - private volatile WeakReference> taglibs; + private volatile WeakReference> taglibs; static ExpressionFactory EXPRESSION_FACTORY = new JexlExpressionFactory(); @@ -56,46 +55,43 @@ public JellyClassLoaderTearOff(MetaClassLoader owner) { } public TagLibrary getTagLibrary(String nsUri) { - LoadingCache m=null; + ConcurrentMap m=null; if(taglibs!=null) m = taglibs.get(); if(m==null) { - m = CacheBuilder.newBuilder().build(new CacheLoader() { - public TagLibrary load(String nsUri) { + m = new ConcurrentHashMap<>(); + taglibs = new WeakReference<>(m); + } + TagLibrary tl = m.computeIfAbsent(nsUri, key -> { if(owner.parent!=null) { // parent first - TagLibrary tl = owner.parent.loadTearOff(JellyClassLoaderTearOff.class).getTagLibrary(nsUri); - if(tl!=null) return tl; + TagLibrary taglib = owner.parent.loadTearOff(JellyClassLoaderTearOff.class).getTagLibrary(key); + if(taglib!=null) return taglib; } - String taglibBasePath = trimHeadSlash(nsUri); + String taglibBasePath = trimHeadSlash(key); try { URL res = owner.loader.getResource(taglibBasePath +"/taglib"); if(res!=null) - return new CustomTagLibrary(createContext(),owner.loader,nsUri,taglibBasePath); + return new CustomTagLibrary(createContext(),owner.loader,key,taglibBasePath); } catch (IllegalArgumentException e) { // if taglibBasePath doesn't even look like an URL, getResource throws IllegalArgumentException. // see http://old.nabble.com/bug-1.331-to26145963.html } // support URIs like "this:it" or "this:instance". Note that "this" URI itself is registered elsewhere - if (nsUri.startsWith("this:")) + if (key.startsWith("this:")) try { - return new ThisTagLibrary(EXPRESSION_FACTORY.createExpression(nsUri.substring(5))); + return new ThisTagLibrary(EXPRESSION_FACTORY.createExpression(key.substring(5))); } catch (JellyException e) { - throw new IllegalArgumentException("Illegal expression in the URI: "+nsUri,e); + throw new IllegalArgumentException("Illegal expression in the URI: "+key,e); } - if (nsUri.equals("jelly:stapler")) + if (key.equals("jelly:stapler")) return new StaplerTagLibrary(); return NO_SUCH_TAGLIBRARY; // "not found" is also cached. - } - }); - taglibs = new WeakReference>(m); - } - - TagLibrary tl = m.getUnchecked(nsUri); + }); if (tl==NO_SUCH_TAGLIBRARY) return null; return tl; }