Merge branch '1.4.5-SNAPSHOT' into 1.5.1-SNAPSHOT
Conflicts:
src/start/src/main/java/org/apache/accumulo/start/classloader/AccumuloClassLoader.java
Project: http://git-wip-us.apache.org/repos/asf/accumulo/repo
Commit: http://git-wip-us.apache.org/repos/asf/accumulo/commit/99062d85
Tree: http://git-wip-us.apache.org/repos/asf/accumulo/tree/99062d85
Diff: http://git-wip-us.apache.org/repos/asf/accumulo/diff/99062d85
Branch: refs/heads/1.6.0-SNAPSHOT
Commit: 99062d85a84b06f54f33222d79b0832d8ec59330
Parents: 09ce814 6537d7a
Author: Josh Elser <[email protected]>
Authored: Mon Feb 3 16:24:46 2014 -0500
Committer: Josh Elser <[email protected]>
Committed: Mon Feb 3 16:24:46 2014 -0500
----------------------------------------------------------------------
.../accumulo/start/classloader/AccumuloClassLoader.java | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/accumulo/blob/99062d85/start/src/main/java/org/apache/accumulo/start/classloader/AccumuloClassLoader.java
----------------------------------------------------------------------
diff --cc
start/src/main/java/org/apache/accumulo/start/classloader/AccumuloClassLoader.java
index 478f4bc,0000000..8cfbdcc
mode 100644,000000..100644
---
a/start/src/main/java/org/apache/accumulo/start/classloader/AccumuloClassLoader.java
+++
b/start/src/main/java/org/apache/accumulo/start/classloader/AccumuloClassLoader.java
@@@ -1,252 -1,0 +1,257 @@@
+/*
+ * 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.apache.accumulo.start.classloader;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ *
+ */
+public class AccumuloClassLoader {
+
+ public static final String CLASSPATH_PROPERTY_NAME = "general.classpaths";
+
+ public static final String ACCUMULO_CLASSPATH_VALUE =
+ "$ACCUMULO_CONF_DIR,\n" +
+ "$ACCUMULO_HOME/lib/[^.].*.jar,\n" +
+ "$ZOOKEEPER_HOME/zookeeper[^.].*.jar,\n" +
+ "$HADOOP_CONF_DIR,\n" +
+ "$HADOOP_PREFIX/[^.].*.jar,\n" +
+ "$HADOOP_PREFIX/lib/[^.].*.jar,\n" +
+ "$HADOOP_PREFIX/share/hadoop/common/.*.jar,\n" +
+ "$HADOOP_PREFIX/share/hadoop/common/lib/.*.jar,\n" +
+ "$HADOOP_PREFIX/share/hadoop/hdfs/.*.jar,\n" +
- "$HADOOP_PREFIX/share/hadoop/mapreduce/.*.jar,\n"
++ "$HADOOP_PREFIX/share/hadoop/mapreduce/.*.jar,\n" +
++ "/usr/lib/hadoop/[^.].*.jar,\n" +
++ "/usr/lib/hadoop/lib/[^.].*.jar,\n" +
++ "/usr/lib/hadoop-hdfs/[^.].*.jar,\n" +
++ "/usr/lib/hadoop-mapreduce/[^.].*.jar,\n" +
++ "/usr/lib/hadoop-yarn/[^.].*.jar,\n"
+ ;
+
+ private static String SITE_CONF;
+
+ private static URLClassLoader classloader;
+
+ private static Logger log = Logger.getLogger(AccumuloClassLoader.class);
+
+ static {
+ String configFile = System.getProperty("org.apache.accumulo.config.file",
"accumulo-site.xml");
+ if (System.getenv("ACCUMULO_CONF_DIR") != null) {
+ // accumulo conf dir should be set
+ SITE_CONF = System.getenv("ACCUMULO_CONF_DIR") + "/" + configFile;
+ } else if (System.getenv("ACCUMULO_HOME") != null) {
+ // if no accumulo conf dir, try accumulo home default
+ SITE_CONF = System.getenv("ACCUMULO_HOME") + "/conf/" + configFile;
+ } else {
+ SITE_CONF = null;
+ }
+ }
+
+ /**
+ * Parses and XML Document for a property node for a <name> with the value
propertyName if it finds one the function return that property's value for its
+ * <value> node. If not found the function will return null
+ *
+ * @param d
+ * XMLDocument to search through
+ * @param propertyName
+ */
+ private static String getAccumuloClassPathStrings(Document d, String
propertyName) {
+ NodeList pnodes = d.getElementsByTagName("property");
+ for (int i = pnodes.getLength() - 1; i >= 0; i--) {
+ Element current_property = (Element) pnodes.item(i);
+ Node cname = current_property.getElementsByTagName("name").item(0);
+ if (cname != null && cname.getTextContent().compareTo(propertyName) ==
0) {
+ Node cvalue = current_property.getElementsByTagName("value").item(0);
+ if (cvalue != null) {
+ return cvalue.getTextContent();
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Looks for the site configuration file for Accumulo and if it has a
property for propertyName return it otherwise returns defaultValue Should throw
an
+ * exception if the default configuration can not be read;
+ *
+ * @param propertyName
+ * Name of the property to pull
+ * @param defaultValue
+ * Value to default to if not found.
+ * @return site or default class path String
+ */
+
+ public static String getAccumuloString(String propertyName, String
defaultValue) {
+
+ try {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ String site_classpath_string = null;
+ try {
+ Document site_conf = db.parse(SITE_CONF);
+ site_classpath_string = getAccumuloClassPathStrings(site_conf,
propertyName);
+ } catch (Exception e) {
+ /* we don't care because this is optional and we can use defaults */
+ }
+ if (site_classpath_string != null)
+ return site_classpath_string;
+ return defaultValue;
+ } catch (Exception e) {
+ throw new IllegalStateException("ClassPath Strings Lookup failed", e);
+ }
+ }
+
+ /**
+ * Replace environment variables in the classpath string with their actual
value
+ *
+ * @param classpath
+ * @param env
+ */
+ public static String replaceEnvVars(String classpath, Map<String,String>
env) {
+ Pattern envPat = Pattern.compile("\\$[A-Za-z][a-zA-Z0-9_]*");
+ Matcher envMatcher = envPat.matcher(classpath);
+ while (envMatcher.find(0)) {
+ // name comes after the '$'
+ String varName = envMatcher.group().substring(1);
+ String varValue = env.get(varName);
+ if (varValue == null) {
+ varValue = "";
+ }
+ classpath = (classpath.substring(0, envMatcher.start()) + varValue +
classpath.substring(envMatcher.end()));
+ envMatcher.reset(classpath);
+ }
+ return classpath;
+ }
+
+ /**
+ * Populate the list of URLs with the items in the classpath string
+ *
+ * @param classpath
+ * @param urls
+ * @throws MalformedURLException
+ */
+ private static void addUrl(String classpath, ArrayList<URL> urls) throws
MalformedURLException {
+ classpath = classpath.trim();
+ if (classpath.length() == 0)
+ return;
+
+ classpath = replaceEnvVars(classpath, System.getenv());
+
+ // Try to make a URI out of the classpath
+ URI uri = null;
+ try {
+ uri = new URI(classpath);
+ } catch (URISyntaxException e) {
+ // Not a valid URI
+ }
+
+ if (null == uri || !uri.isAbsolute() || (null != uri.getScheme() &&
uri.getScheme().equals("file://"))) {
+ // Then treat this URI as a File.
+ // This checks to see if the url string is a dir if it expand and get
all jars in that directory
+ final File extDir = new File(classpath);
+ if (extDir.isDirectory())
+ urls.add(extDir.toURI().toURL());
+ else {
+ if (extDir.getParentFile() != null) {
+ File[] extJars = extDir.getParentFile().listFiles(new
FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.matches("^" + extDir.getName());
+ }
+ });
+ if (extJars != null && extJars.length > 0) {
+ for (File jar : extJars)
+ urls.add(jar.toURI().toURL());
+ } else {
+ log.debug("ignoring classpath entry " + classpath);
+ }
+ } else {
+ log.debug("ignoring classpath entry " + classpath);
+ }
+ }
+ } else {
+ urls.add(uri.toURL());
+ }
+
+ }
+
+ private static ArrayList<URL> findAccumuloURLs() throws IOException {
+ String cp =
getAccumuloString(AccumuloClassLoader.CLASSPATH_PROPERTY_NAME,
AccumuloClassLoader.ACCUMULO_CLASSPATH_VALUE);
+ if (cp == null)
+ return new ArrayList<URL>();
+ String[] cps = replaceEnvVars(cp, System.getenv()).split(",");
+ ArrayList<URL> urls = new ArrayList<URL>();
+ for (String classpath : cps) {
+ if (!classpath.startsWith("#")) {
+ addUrl(classpath, urls);
+ }
+ }
+ return urls;
+ }
+
+ public static synchronized ClassLoader getClassLoader() throws IOException {
+ if (classloader == null) {
+ ArrayList<URL> urls = findAccumuloURLs();
+
+ ClassLoader parentClassLoader =
AccumuloClassLoader.class.getClassLoader();
+
+ log.debug("Create 2nd tier ClassLoader using URLs: " + urls.toString());
+ URLClassLoader aClassLoader = new URLClassLoader(urls.toArray(new
URL[urls.size()]), parentClassLoader) {
+ @Override
+ protected synchronized Class<?> loadClass(String name, boolean
resolve) throws ClassNotFoundException {
+
+ if (name.startsWith("org.apache.accumulo.start.classloader.vfs")) {
+ Class<?> c = findLoadedClass(name);
+ if (c == null) {
+ try {
+ // try finding this class here instead of parent
+ c = findClass(name);
+ } catch (ClassNotFoundException e) {
+
+ }
+ }
+ }
+ return super.loadClass(name, resolve);
+ }
+ };
+ classloader = aClassLoader;
+ }
+
+ return classloader;
+ }
+}