diff --git a/gerrit-common/BUCK b/gerrit-common/BUCK index 2841a40c04..e2dcb27b63 100644 --- a/gerrit-common/BUCK +++ b/gerrit-common/BUCK @@ -7,6 +7,7 @@ ANNOTATIONS = [ ] EXCLUDES = [ + SRC + 'common/PluginData.java', SRC + 'common/FileUtil.java', ] @@ -45,6 +46,7 @@ java_library( '//gerrit-reviewdb:server', '//lib:gwtjsonrpc', '//lib:gwtorm', + '//lib:guava', '//lib/jgit:jgit', ], visibility = ['PUBLIC'], diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java new file mode 100644 index 0000000000..fc5bb56b7b --- /dev/null +++ b/gerrit-common/src/main/java/com/google/gerrit/common/PluginData.java @@ -0,0 +1,46 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// 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 com.google.gerrit.common; + +package com.google.gerrit.common; + +import com.google.common.base.Objects; + +import java.io.File; + +public class PluginData { + public final String name; + public final String version; + public final File pluginFile; + + public PluginData(String name, String version, File pluginFile) { + this.name = name; + this.version = version; + this.pluginFile = pluginFile; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PluginData) { + PluginData o = (PluginData) obj; + return Objects.equal(name, o.name) && Objects.equal(version, o.version) + && Objects.equal(pluginFile, o.pluginFile); + } + return super.equals(obj); + } + + @Override + public int hashCode() { + return Objects.hashCode(name, version, pluginFile); + } +} \ No newline at end of file diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java index 2f25ed0901..7e2a2b5e19 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/JarScanner.java @@ -38,10 +38,12 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.util.Collection; +import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.Map; @@ -92,6 +94,15 @@ public class JarScanner { } } + public static Iterable scan(File file, String pluginName, + Class annotation) throws InvalidPluginException, + IOException { + Map, Iterable> result = + scan(new JarFile(file), pluginName, + Arrays.> asList(annotation)); + return result.get(annotation); + } + public static Map, Iterable> scan( JarFile jarFile, String pluginName, Iterable> annotations) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java index 9a1ca5e308..b4d8df1a25 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/PluginLoader.java @@ -77,6 +77,10 @@ public class PluginLoader implements LifecycleListener { static final String PLUGIN_TMP_PREFIX = "plugin_"; static final Logger log = LoggerFactory.getLogger(PluginLoader.class); + public static String getPluginName(File srcFile) throws IOException { + return Objects.firstNonNull(getGerritPluginName(srcFile), nameOf(srcFile)).toLowerCase(); + } + private final File pluginsDir; private final File dataDir; private final File tmpDir; @@ -661,7 +665,7 @@ public class PluginLoader implements LifecycleListener { // If multiple plugin files provide the same plugin name, then only // the first plugin remains active and all other plugins with the same // name are disabled. - private static Multimap prunePlugins(File pluginsDir) { + public static Multimap prunePlugins(File pluginsDir) { List jars = scanJarsInPluginsDirectory(pluginsDir); Multimap map; try { @@ -757,8 +761,7 @@ public class PluginLoader implements LifecycleListener { throws IOException { Multimap map = LinkedHashMultimap.create(); for (File srcFile : plugins) { - map.put(Objects.firstNonNull(getGerritPluginName(srcFile), - nameOf(srcFile)), srcFile); + map.put(getPluginName(srcFile), srcFile); } return map; } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStore.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStore.java new file mode 100644 index 0000000000..3fe00f4b55 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStore.java @@ -0,0 +1,27 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// 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 com.google.gerrit.server.securestore; + +import com.google.gerrit.extensions.annotations.ExtensionPoint; + +@ExtensionPoint +public interface SecureStore { + + String get(String section, String subsection, String name); + + void set(String section, String subsection, String name, String value); + + void unset(String section, String subsection, String name); +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreData.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreData.java new file mode 100644 index 0000000000..b92510547f --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreData.java @@ -0,0 +1,77 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// 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 com.google.gerrit.server.securestore; + +import com.google.common.base.Objects; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +public class SecureStoreData { + public final File pluginFile; + public final String storeName; + public final String className; + + public SecureStoreData(String pluginName, String className, File jarFile, + String storeName) { + this.className = className; + this.pluginFile = jarFile; + this.storeName = String.format("%s/%s", pluginName, storeName); + } + + public String getStoreName() { + return storeName; + } + + public Class load() { + return load(pluginFile); + } + + @SuppressWarnings("unchecked") + public Class load(File pluginFile) { + try { + URL[] pluginJarUrls = new URL[] {pluginFile.toURI().toURL()}; + ClassLoader currentCL = Thread.currentThread().getContextClassLoader(); + final URLClassLoader newClassLoader = + new URLClassLoader(pluginJarUrls, currentCL); + Thread.currentThread().setContextClassLoader(newClassLoader); + return (Class) newClassLoader.loadClass(className); + } catch (Exception e) { + throw new SecureStoreException(String.format( + "Cannot load secure store implementation for %s", storeName), e); + } + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("storeName", storeName) + .add("className", className).add("file", pluginFile).toString(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SecureStoreData) { + SecureStoreData o = (SecureStoreData) obj; + return storeName.equals(o.storeName); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(storeName); + } +} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreException.java b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreException.java new file mode 100644 index 0000000000..01450f8809 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/securestore/SecureStoreException.java @@ -0,0 +1,27 @@ +// Copyright (C) 2013 The Android Open Source Project +// +// 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 com.google.gerrit.server.securestore; + +public class SecureStoreException extends RuntimeException { + private static final long serialVersionUID = 5581700510568485065L; + + SecureStoreException(String msg) { + super(msg); + } + + SecureStoreException(String msg, Exception e) { + super(msg, e); + } +}