http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/Glog.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/Glog.java b/commons/src/main/java/com/twitter/common/logging/Glog.java deleted file mode 100644 index 904b263..0000000 --- a/commons/src/main/java/com/twitter/common/logging/Glog.java +++ /dev/null @@ -1,208 +0,0 @@ -/** - * 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.twitter.common.logging; - -import javax.annotation.Nullable; - -import com.google.common.base.Objects; -import com.google.common.base.Throwables; - -import org.joda.time.DateTimeZone; -import org.joda.time.format.DateTimeFormat; -import org.joda.time.format.DateTimeFormatter; - -/** - * A utility that can format log records to match the format generated by glog: - * <pre> - * I0218 17:36:47.461 (source) (message) - * </pre> - */ -public final class Glog { - - /** - * Classifies the importance of a log message. - */ - public enum Level { - - /** - * Indicates the message's classification is unknown. This most likely indicates a - * configuration or programming error that can be corrected by mapping the underlying log - * system's level appropriately. - */ - UNKNOWN('U'), - - /** - * Indicates the message is for debugging purposes only. - */ - DEBUG('D'), - - /** - * Indicates a message of general interest. - */ - INFO('I'), - - /** - * Indicates a warning message likely worth of attention. - */ - WARNING('W'), - - /** - * Indicates an unexpected error. - */ - ERROR('E'), - - /** - * Indicates a fatal exception generally paired with actions to shut down the errored process. - */ - FATAL('F'); - - final char label; - - private Level(char label) { - this.label = label; - } - } - - /** - * An object that can provide details of a log record. - * - * @param <T> The type of log record the formatter handles. - */ - public interface Formatter<T> { - - /** - * Gets the message contained in the log record. - * - * @param record The record to extract a message from. - * @return The formatted message. - */ - String getMessage(T record); - - /** - * Gets the class name of the class that sent the log record for logging. - * - * @param record The record to extract a producing class name from. - * @return The producing class if known; otherwise {@code null}. - */ - @Nullable - String getClassName(T record); - - /** - * Gets the name of the method of within the class that sent the log record for logging. - * - * @param record The record to extract a producing method name from. - * @return The producing method name if known; otherwise {@code null}. - */ - @Nullable - String getMethodName(T record); - - /** - * Gets the level of the log record. - * - * @param record The record to extract a log level from. - * @return The record's log level. Can be {@code null} or {@link Level#UNKNOWN} if unknown. - */ - @Nullable - Level getLevel(T record); - - /** - * Gets the timestamp in milliseconds since the epoch when the log record was generated. - * - * @param record The record to extract a time stamp from. - * @return The log record's birth date. - */ - long getTimeStamp(T record); - - /** - * Gets the id of the thread that generated the log record. - * - * @param record The record to extract a thread id from. - * @return The id of the thread that generated the log record. - */ - long getThreadId(T record); - - /** - * Gets the exception associated with the log record if any. - * - * @param record The record to extract an exception from. - * @return The exception associated with the log record; may be {@code null}. - */ - @Nullable - Throwable getThrowable(T record); - } - - private static final DateTimeFormatter DATE_TIME_FORMATTER = - DateTimeFormat.forPattern("MMdd HH:mm:ss.SSS").withZone(DateTimeZone.UTC); - - private static final int BASE_MESSAGE_LENGTH = - 1 // Level char. - + 4 // Month + day - + 1 // space - + 12 // Timestamp - + 1 // space - + 6 // THREAD - + 4 // Room for thread ID. - + 1; // space - - /** - * Converts the given log record into a glog format log line using the given formatter. - * - * @param formatter A formatter that understands how to unpack the given log record. - * @param record A structure containing log data. - * @param <T> The type of log record. - * @return A glog formatted log line. - */ - public static <T> String formatRecord(Formatter<T> formatter, T record) { - String message = formatter.getMessage(record); - int messageLength = BASE_MESSAGE_LENGTH - + 2 // Colon and space - + message.length(); - - String className = formatter.getClassName(record); - String methodName = null; - if (className != null) { - messageLength += className.length(); - methodName = formatter.getMethodName(record); - if (methodName != null) { - messageLength += 1; // Period between class and method. - messageLength += methodName.length(); - } - } - - StringBuilder sb = new StringBuilder(messageLength) - .append(Objects.firstNonNull(formatter.getLevel(record), Level.UNKNOWN).label) - .append(DATE_TIME_FORMATTER.print(formatter.getTimeStamp(record))) - .append(" THREAD") - .append(formatter.getThreadId(record)); - - if (className != null) { - sb.append(' ').append(className); - if (methodName != null) { - sb.append('.').append(methodName); - } - } - - sb.append(": ").append(message); - Throwable throwable = formatter.getThrowable(record); - if (throwable != null) { - sb.append('\n').append(Throwables.getStackTraceAsString(throwable)); - } - - return sb.append('\n').toString(); - } - - private Glog() { - // utility - } -}
http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/Log.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/Log.java b/commons/src/main/java/com/twitter/common/logging/Log.java deleted file mode 100644 index 3c7b63a..0000000 --- a/commons/src/main/java/com/twitter/common/logging/Log.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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.twitter.common.logging; - -import java.util.List; - -/** - * Logs messages to scribe. - * - * @author William Farner - */ -public interface Log<T, R> { - - /** - * Submits a log message. - * - * @param entry Entry to log. - * @return The result of the log request. - */ - public R log(T entry); - - /** - * Batch version of log. - * - * @param entries Entries to log. - * @return The result of the log request. - */ - public R log(List<T> entries); - - /** - * Flushes the log, attempting to purge any state that is only stored locally. - */ - public void flush(); -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/LogFormatter.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/LogFormatter.java b/commons/src/main/java/com/twitter/common/logging/LogFormatter.java deleted file mode 100644 index b5cd4d9..0000000 --- a/commons/src/main/java/com/twitter/common/logging/LogFormatter.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * 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.twitter.common.logging; - -import java.util.logging.Formatter; -import java.util.logging.Level; -import java.util.logging.LogRecord; - -import com.google.common.collect.ImmutableMap; - -/** - * Log formatter to match the format generated by glog. - * - * @see Glog - */ -public class LogFormatter extends Formatter implements Glog.Formatter<LogRecord> { - - private static final ImmutableMap<Level, Glog.Level> LEVEL_LABELS = - ImmutableMap.<Level, Glog.Level>builder() - .put(Level.FINEST, Glog.Level.DEBUG) - .put(Level.FINER, Glog.Level.DEBUG) - .put(Level.FINE, Glog.Level.DEBUG) - .put(Level.CONFIG, Glog.Level.INFO) - .put(Level.INFO, Glog.Level.INFO) - .put(Level.WARNING, Glog.Level.WARNING) - .put(Level.SEVERE, Glog.Level.ERROR) - .build(); - - - @Override - public String format(final LogRecord record) { - return Glog.formatRecord(this, record); - } - - @Override - public String getMessage(LogRecord record) { - return formatMessage(record); - } - - @Override - public String getClassName(LogRecord record) { - return record.getSourceClassName(); - } - - @Override - public String getMethodName(LogRecord record) { - return record.getSourceMethodName(); - } - - @Override - public Glog.Level getLevel(LogRecord record) { - return LEVEL_LABELS.get(record.getLevel()); - } - - @Override - public long getTimeStamp(LogRecord record) { - return record.getMillis(); - } - - @Override - public long getThreadId(LogRecord record) { - return record.getThreadID(); - } - - @Override - public Throwable getThrowable(LogRecord record) { - return record.getThrown(); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/LogUtil.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/LogUtil.java b/commons/src/main/java/com/twitter/common/logging/LogUtil.java deleted file mode 100644 index fe612fc..0000000 --- a/commons/src/main/java/com/twitter/common/logging/LogUtil.java +++ /dev/null @@ -1,90 +0,0 @@ -/** - * 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.twitter.common.logging; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.SystemUtils; - -import java.io.File; -import java.util.logging.LogManager; -import java.util.logging.Logger; - -/** - * Logging utility functions. - * - * @author William Farner - */ -public class LogUtil { - - private static final Logger LOG = Logger.getLogger(LogUtil.class.getName()); - - private static final String LOG_MANAGER_FILE_PROP = "java.util.logging.FileHandler.pattern"; - - @VisibleForTesting - static final File DEFAULT_LOG_DIR = new File("/var/log"); - - /** - * Gets the log directory as configured with the log manager. This will attempt to expand any - * directory wildcards that are included in log file property. - * - * @return The configured log directory. - */ - public static File getLogManagerLogDir() { - return getLogManagerLogDir(LogManager.getLogManager().getProperty(LOG_MANAGER_FILE_PROP)); - } - - /** - * Gets the log directory as specified in a log file pattern. This will attempt to expand any - * directory wildcards that are included in log file property. - * - * @param logFilePattern The pattern to extract the log directory from. - * @return The configured log directory. - */ - public static File getLogManagerLogDir(String logFilePattern) { - if (StringUtils.isEmpty(logFilePattern)) { - LOG.warning("Could not find log dir in logging property " + LOG_MANAGER_FILE_PROP - + ", reading from " + DEFAULT_LOG_DIR); - return DEFAULT_LOG_DIR; - } - - String logDir = expandWildcard(logFilePattern, "%t", SystemUtils.JAVA_IO_TMPDIR); - logDir = expandWildcard(logDir, "%h", SystemUtils.USER_HOME); - File parent = new File(logDir).getParentFile(); - return parent == null ? new File(".") : parent; - } - - /** - * Expands a directory path wildcard within a file pattern string. - * Correctly handles cases where the replacement string does and does not contain a trailing - * slash. - * - * @param pattern File pattern string, which may or may not contain a wildcard. - * @param dirWildcard Wildcard string to expand. - * @param replacement Path component to expand wildcard to. - * @return {@code pattern} with all instances of {@code dirWildcard} replaced with - * {@code replacement}. - */ - private static String expandWildcard(String pattern, String dirWildcard, String replacement) { - String replace = dirWildcard; - if (replacement.charAt(replacement.length() - 1) == '/') { - replace += '/'; - } - return pattern.replaceAll(replace, replacement); - } - - private LogUtil() { - // Utility class. - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/RootLogConfig.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/RootLogConfig.java b/commons/src/main/java/com/twitter/common/logging/RootLogConfig.java deleted file mode 100644 index 8e0648d..0000000 --- a/commons/src/main/java/com/twitter/common/logging/RootLogConfig.java +++ /dev/null @@ -1,339 +0,0 @@ -/** - * 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.twitter.common.logging; - -import java.util.HashMap; -import java.util.Map; -import java.util.logging.ConsoleHandler; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogManager; -import java.util.logging.Logger; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; - -import com.twitter.common.args.Arg; -import com.twitter.common.args.CmdLine; - -/** - * A configuration class for the root java.util.logging Logger. - * - * Defines flags to control the behavior behavior of the root logger similarly to Google's glog - * library (see http://code.google.com/p/google-glog ). - */ -public class RootLogConfig { - /** - * An enum reflecting log {@link Level} constants. - */ - public enum LogLevel { - FINEST(Level.FINEST), - FINER(Level.FINER), - FINE(Level.FINE), - CONFIG(Level.CONFIG), - INFO(Level.INFO), - WARNING(Level.WARNING), - SEVERE(Level.SEVERE); - - private final Level level; - - private LogLevel(Level level) { - this.level = level; - } - - private Level getLevel() { - return level; - } - } - - @CmdLine(name = "logtostderr", help = "Log messages to stderr instead of logfiles.") - private static Arg<Boolean> LOGTOSTDERR = Arg.create(false); - - @CmdLine(name = "alsologtostderr", - help = "Log messages to stderr, in addition to log files. Ignored when --logtostderr") - private static Arg<Boolean> ALSOLOGTOSTDERR = Arg.create(false); - - @CmdLine(name = "vlog", - help = "The value is one of the constants in java.util.logging.Level. " - + "Shows all messages with level equal or higher " - + "than the value of this flag.") - private static Arg<LogLevel> VLOG = Arg.create(LogLevel.INFO); - - @CmdLine(name = "vmodule", - help = "Per-class verbose level. The argument has to contain a comma-separated list " - + "of <class_name>=<log_level>. <class_name> is the full-qualified name of a " - + "class, <log_level> is one of the constants in java.util.logging.Level. " - + "<log_level> overrides any value given by --vlog.") - private static Arg<Map<Class<?>, LogLevel>> VMODULE = - Arg.<Map<Class<?>, LogLevel>>create(new HashMap<Class<?>, LogLevel>()); - - @CmdLine(name = "use_glog_formatter", help = "True to use the glog formatter exclusively.") - private static Arg<Boolean> USE_GLOG_FORMATTER = Arg.create(true); - - /** - * Represents a logging configuration for java.util.logging. - */ - public static final class Configuration { - boolean logToStderr = false; - boolean alsoLogToStderr = false; - boolean useGLogFormatter = true; - LogLevel vlog = LogLevel.INFO; - ImmutableMap<Class<?>, LogLevel> vmodule = ImmutableMap.of(); - String rootLoggerName = ""; - - Configuration() { - // Guard for internal use only. - } - - /** - * Returns {@code true} if configured to log just to stderr. - */ - public boolean isLogToStderr() { - return logToStderr; - } - - /** - * Returns {@code true} if configured to log to stderr in addition to log files.. - */ - public boolean isAlsoLogToStderr() { - return alsoLogToStderr; - } - - /** - * Returns {@code true} if configured to log in google-glog format. - */ - public boolean isUseGLogFormatter() { - return useGLogFormatter; - } - - /** - * Returns the default global log level. - */ - public LogLevel getVlog() { - return vlog; - } - - /** - * Returns the custom log levels configured for individual classes. - */ - public ImmutableMap<Class<?>, LogLevel> getVmodule() { - return vmodule; - } - - /** - * Applies this configuration to the root log. - */ - public void apply() { - RootLogConfig.configure(this); - } - } - - /** - * A builder-pattern class used to perform the configuration programmatically - * (i.e. not through flags). - * Example: - * <code> - * RootLogConfig.builder().logToStderr(true).build().apply(); - * </code> - */ - public static final class Builder { - private final Configuration configuration; - - private Builder() { - this.configuration = new Configuration(); - } - - /** - * Only log messages to stderr, instead of log files. Overrides alsologtostderr. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder logToStderr(boolean flag) { - configuration.logToStderr = flag; - return this; - } - - /** - * Also log messages to stderr, in addition to log files. - * Overridden by logtostderr. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder alsoLogToStderr(boolean flag) { - configuration.alsoLogToStderr = flag; - return this; - } - - /** - * Format log messages in one-line with a header, similar to google-glog. - * Default: false. - * - * @param flag True to enable, false to disable. - * @return this Configuration object. - */ - public Builder useGLogFormatter(boolean flag) { - configuration.useGLogFormatter = flag; - return this; - } - - /** - * Output log messages at least at the given verbosity level. - * Overridden by vmodule. - * Default: INFO - * - * @param level LogLevel enumerator for the minimum log message verbosity level that is output. - * @return this Configuration object. - */ - public Builder vlog(LogLevel level) { - Preconditions.checkNotNull(level); - configuration.vlog = level; - return this; - } - - /** - * Output log messages for a given set of classes at the associated verbosity levels. - * Overrides vlog. - * Default: no classes are treated specially. - * - * @param pairs Map of classes and correspoding log levels. - * @return this Configuration object. - */ - public Builder vmodule(Map<Class<?>, LogLevel> pairs) { - Preconditions.checkNotNull(pairs); - configuration.vmodule = ImmutableMap.copyOf(pairs); - return this; - } - - /** - * Returns the built up configuration. - */ - public Configuration build() { - return configuration; - } - - // Intercepts the root logger, for testing purposes only. - @VisibleForTesting - Builder rootLoggerName(String name) { - Preconditions.checkNotNull(name); - Preconditions.checkArgument(!name.isEmpty()); - configuration.rootLoggerName = name; - return this; - } - } - - /** - * Creates a new Configuration builder object. - * - * @return The builder. - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Creates a logging configuration using flags - * - * @return The logging configuration specified via command line flags. - */ - public static Configuration configurationFromFlags() { - return builder() - .logToStderr(LOGTOSTDERR.get()) - .alsoLogToStderr(ALSOLOGTOSTDERR.get()) - .useGLogFormatter(USE_GLOG_FORMATTER.get()) - .vlog(VLOG.get()) - .vmodule(VMODULE.get()) - .build(); - } - - private static void configure(Configuration configuration) { - // Edit the properties of the root logger. - Logger rootLogger = Logger.getLogger(configuration.rootLoggerName); - if (configuration.logToStderr) { - setLoggerToStderr(rootLogger); - } else if (configuration.alsoLogToStderr) { - setLoggerToAlsoStderr(rootLogger); - } - if (configuration.useGLogFormatter) { - setGLogFormatter(rootLogger); - } - if (configuration.vlog != null) { - setVlog(rootLogger, configuration.vlog); - } - if (configuration.vmodule != null) { - setVmodules(configuration.vmodule); - } - } - - private static void setLoggerToStderr(Logger logger) { - LogManager.getLogManager().reset(); - setConsoleHandler(logger, true); - } - - private static void setLoggerToAlsoStderr(Logger logger) { - setConsoleHandler(logger, false); - } - - private static void setConsoleHandler(Logger logger, boolean removeOtherHandlers) { - Handler consoleHandler = null; - for (Handler h : logger.getHandlers()) { - if (h instanceof ConsoleHandler) { - consoleHandler = h; - } else if (removeOtherHandlers) { - logger.removeHandler(h); - } - } - if (consoleHandler == null) { - consoleHandler = new ConsoleHandler(); - logger.addHandler(new ConsoleHandler()); - } - consoleHandler.setLevel(Level.ALL); - consoleHandler.setFilter(null); - } - - private static void setGLogFormatter(Logger logger) { - for (Handler h : logger.getHandlers()) { - h.setFormatter(new LogFormatter()); - } - } - - private static void setVmodules(Map<Class<?>, LogLevel> vmodules) { - for (Map.Entry<Class<?>, LogLevel> entry : vmodules.entrySet()) { - String className = entry.getKey().getName(); - Logger logger = Logger.getLogger(className); - setVlog(logger, entry.getValue()); - } - } - - private static void setVlog(Logger logger, LogLevel logLevel) { - final Level newLevel = logLevel.getLevel(); - logger.setLevel(newLevel); - do { - for (Handler handler : logger.getHandlers()) { - Level handlerLevel = handler.getLevel(); - if (newLevel.intValue() < handlerLevel.intValue()) { - handler.setLevel(newLevel); - } - } - } while (logger.getUseParentHandlers() && (logger = logger.getParent()) != null); - } - - // Utility class. - private RootLogConfig() { - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeHandler.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeHandler.java b/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeHandler.java deleted file mode 100644 index 894a9b1..0000000 --- a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeHandler.java +++ /dev/null @@ -1,196 +0,0 @@ -/** - * 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.twitter.common.logging.julbridge; - -import java.text.MessageFormat; -import java.util.MissingResourceException; -import java.util.logging.Formatter; -import java.util.logging.Handler; -import java.util.logging.LogRecord; - -import javax.annotation.Nullable; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.spi.LocationInfo; -import org.apache.log4j.spi.LoggerRepository; -import org.apache.log4j.spi.LoggingEvent; -import org.apache.log4j.spi.ThrowableInformation; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * JUL Handler to convert JUL {@link LogRecord} messages into Log4j's {@link LoggingEvent} messages, - * and route them to a Log4J logger with the same name as the JUL logger. - */ -public class JULBridgeHandler extends Handler { - private static final String UNKNOWN_LOGGERNAME = "unknown"; - - /** - * Converts a JUL log record into a Log4J logging event. - * - * @param record the JUL log record to convert - * @param logger the Log4J logger to use for the logging event - * @param level the Log4J level to use for the logging event - * @param useExtendedLocationInfo if false, do no try to get source file and line informations - * @return a Log4J logging event - */ - static LoggingEvent toLoggingEvent(LogRecord record, Logger logger, Level level, - boolean useExtendedLocationInfo) { - - LocationInfo locationInfo = useExtendedLocationInfo - ? new LocationInfo(new Throwable(), record.getSourceClassName()) - : new LocationInfo("?", record.getSourceClassName(), record.getSourceMethodName(), "?"); - - // Getting thread name from thread id? complicated... - String threadName = String.valueOf(record.getThreadID()); - ThrowableInformation throwableInformation = record.getThrown() == null - ? null - : new ThrowableInformation(record.getThrown()); - - return new LoggingEvent( - record.getSourceClassName(), - logger, - record.getMillis(), - level, - formatMessage(record), - threadName, - throwableInformation, - null /* ndc */, - locationInfo, - null /* properties */); - } - - /** - * Formats a log record message in a way similar to {@link Formatter#formatMessage(LogRecord)}. - * - * If the record contains a resource bundle, a lookup is done to find a localized version. - * - * If the record contains parameters, the message is formatted using - * {@link MessageFormat#format(String, Object...)} - * - * @param record the log record used to format the message - * @return a formatted string - */ - static String formatMessage(LogRecord record) { - String message = record.getMessage(); - - // Look for a resource bundle - java.util.ResourceBundle catalog = record.getResourceBundle(); - if (catalog != null) { - try { - message = catalog.getString(record.getMessage()); - } catch (MissingResourceException e) { - // Not found? Fallback to original message string - message = record.getMessage(); - } - } - - Object parameters[] = record.getParameters(); - if (parameters == null || parameters.length == 0) { - // No parameters? just return the message string - return message; - } - - // Try formatting - try { - return MessageFormat.format(message, parameters); - } catch (IllegalArgumentException e) { - return message; - } - } - - private final LoggerRepository loggerRepository; - private final boolean useExtendedLocationInfo; - - /** - * Creates a new JUL handler. Equivalent to calling {@link #JULBridgeHandler(boolean)} passing - * <code>false</code> as argument. - */ - public JULBridgeHandler() { - this(LogManager.getLoggerRepository(), false); - } - - /** - * Creates a new JUL handler. - * Equivalent to calling {@link #JULBridgeHandler(LoggerRepository, boolean)} passing - * <code>LogManager.getLoggerRepository()</code> and <code>useExtendedLocationInfo</code> as - * arguments. - * - * @param useExtendedLocationInfo if true, try to add source filename and line info to log message - */ - public JULBridgeHandler(boolean useExtendedLocationInfo) { - this(LogManager.getLoggerRepository(), useExtendedLocationInfo); - } - - /** - * Creates a new JUL handler. - * - * @param loggerRepository Log4j logger repository where to get loggers from - * @param useExtendedLocationInfo if true, try to add source filename and line info to log message - * @throws NullPointerException if loggerRepository is null - */ - public JULBridgeHandler(LoggerRepository loggerRepository, boolean useExtendedLocationInfo) { - this.loggerRepository = checkNotNull(loggerRepository); - this.useExtendedLocationInfo = useExtendedLocationInfo; - } - - /** - * Gets a Log4J Logger with the same name as the logger name stored in the log record. - * - * @param record a JUL log record - * @return a Log4J logger with the same name, or name {@value #UNKNOWN_LOGGERNAME} if no name is - * present in the record. - */ - Logger getLogger(LogRecord record) { - String loggerName = record.getLoggerName(); - if (loggerName == null) { - loggerName = UNKNOWN_LOGGERNAME; - } - - return loggerRepository.getLogger(loggerName); - } - - /** - * Publishes the log record to a Log4J logger of the same name. - * - * Before formatting the message, level is converted and message is discarded if Log4j logger is - * not enabled for that level. - * - * @param record the record to publish - */ - @Override - public void publish(@Nullable LogRecord record) { - // Ignore silently null records - if (record == null) { - return; - } - - Logger log4jLogger = getLogger(record); - Level log4jLevel = JULBridgeLevelConverter.toLog4jLevel(record.getLevel()); - - if (log4jLogger.isEnabledFor(log4jLevel)) { - LoggingEvent event = toLoggingEvent(record, log4jLogger, log4jLevel, useExtendedLocationInfo); - - log4jLogger.callAppenders(event); - } - } - - @Override - public void flush() {} - - @Override - public void close() {} -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverter.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverter.java b/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverter.java deleted file mode 100644 index 50749d9..0000000 --- a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLevelConverter.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * 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.twitter.common.logging.julbridge; - -import java.util.logging.Level; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * An utility class to convert between JUL and Log4j Levels. Mapping is as follows: - * <ul> - * <li>FINEST <-> TRACE</li> - * <li>FINER -> DEBUG</li> - * <li>FINE <-> DEBUG</li> - * <li>INFO <-> INFO</li> - * <li>WARNING <-> WARN</li> - * <li>SEVERE <-> ERROR</li> - * <li>SEVERE <- FATAL</li> - * </ul> - * - * Unknowns levels are mapped to FINE/DEBUG - */ -public class JULBridgeLevelConverter { - - private JULBridgeLevelConverter() {} - - /** - * Converts a JUL level into a Log4j level. - * - * @param level the JUL level to convert - * @return a Log4j level - * @throws NullPointerException if level is null - */ - public static org.apache.log4j.Level toLog4jLevel(Level level) { - checkNotNull(level); - - if (level == Level.FINEST) { - return org.apache.log4j.Level.TRACE; - } else if (level == Level.FINER) { - return org.apache.log4j.Level.DEBUG; - } else if (level == Level.FINE) { - return org.apache.log4j.Level.DEBUG; - } else if (level == Level.INFO) { - return org.apache.log4j.Level.INFO; - } else if (level == Level.WARNING) { - return org.apache.log4j.Level.WARN; - } else if (level == Level.SEVERE) { - return org.apache.log4j.Level.ERROR; - } else if (level == Level.ALL) { - return org.apache.log4j.Level.ALL; - } else if (level == Level.OFF) { - return org.apache.log4j.Level.OFF; - } - - return org.apache.log4j.Level.DEBUG; - } - - /** - * Converts a Log4j level into a JUL level. - * - * @param level the Log4j level to convert - * @return a JUL level - * @throws NullPointerException if level is null - */ - public static Level fromLog4jLevel(org.apache.log4j.Level level) { - checkNotNull(level); - - if (level == org.apache.log4j.Level.TRACE) { - return Level.FINEST; - } else if (level == org.apache.log4j.Level.DEBUG) { - return Level.FINE; - } else if (level == org.apache.log4j.Level.INFO) { - return Level.INFO; - } else if (level == org.apache.log4j.Level.WARN) { - return Level.WARNING; - } else if (level == org.apache.log4j.Level.ERROR) { - return Level.SEVERE; - } else if (level == org.apache.log4j.Level.FATAL) { - return Level.SEVERE; - } else if (level == org.apache.log4j.Level.ALL) { - return Level.ALL; - } else if (level == org.apache.log4j.Level.OFF) { - return Level.OFF; - } - - return Level.FINE; - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLogManager.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLogManager.java b/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLogManager.java deleted file mode 100644 index a9f771f..0000000 --- a/commons/src/main/java/com/twitter/common/logging/julbridge/JULBridgeLogManager.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * 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.twitter.common.logging.julbridge; - -import java.util.logging.LogManager; -import java.util.logging.Logger; - -import org.apache.log4j.spi.LoggerRepository; - -/** - * A JUL LogManager which takes over the logging configuration and redirects all messages to Log4j. - * - * The approach is inspired by the apache-jul-log4j-bridge project from Paul Smith - * (<psm...@apache.org>) and available at <a - * href="http://people.apache.org/~psmith/logging.apache.org/sandbox/jul-log4j-bridge/" /> - * - * During initialization, it resets configuration and adds a default handler to the root logger to - * perform the redirection. It also sets the root logger level to the Log4j repository threshold. - * This implies that Log4j is properly configured before this manager is taking over. - * - * To install this log manager, simply add the following property to the java command line: - * <code>-Djava.util.logging.manager=com.twitter.common.logging.julbridge.JULBridgeLogManager</code> - * - * It is possible to configure using extended location information (source filename and line info) - * by adding the following property to the java command line: - * <code>-Dcom.twitter.common.logging.julbridge.use-extended-location-info=true</code> - * - */ -public final class JULBridgeLogManager extends LogManager { - /** - * System property name to control if log messages sent from JUL to log4j should contain - * extended location information. - * - * Set @value to true to add source filename and line number to each message. - */ - public static final String USE_EXTENDED_LOCATION_INFO_PROPERTYNAME = - "com.twitter.common.logging.julbridge.use-extended-location-info"; - - /* - * LogManager requires a public no-arg constructor to be present so a new instance can be created - * when configured using the system property. A private constructor will throw an exception. - */ - public JULBridgeLogManager() {} - - @Override - public void readConfiguration() { - assimilate(org.apache.log4j.LogManager.getLoggerRepository()); - } - - /** - * Assimilates an existing JUL log manager. Equivalent to calling - * {@link #assimilate(LoggerRepository)} with <code>LogManager.getLoggerRepository</code>. - */ - public static void assimilate() { - assimilate(org.apache.log4j.LogManager.getLoggerRepository()); - } - - /** - * Assimilates an existing JUL log manager. - * - * It resets the manager configuration, and adds a bridge handler to the root logger. Messages are - * redirected to the specified Log4j logger repository. - * - * @param loggerRepository the Log4j logger repository to use to redirect messages - */ - public static void assimilate(LoggerRepository loggerRepository) { - LogManager.getLogManager().reset(); - - boolean withExtendedLocationInfos = - Boolean.getBoolean(USE_EXTENDED_LOCATION_INFO_PROPERTYNAME); - - Logger rootLogger = Logger.getLogger(""); - rootLogger.setLevel(JULBridgeLevelConverter.fromLog4jLevel(loggerRepository.getThreshold())); - rootLogger.addHandler(new JULBridgeHandler(loggerRepository, withExtendedLocationInfos)); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/logging/log4j/GlogLayout.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/logging/log4j/GlogLayout.java b/commons/src/main/java/com/twitter/common/logging/log4j/GlogLayout.java deleted file mode 100644 index 6f0ffe5..0000000 --- a/commons/src/main/java/com/twitter/common/logging/log4j/GlogLayout.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * 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.twitter.common.logging.log4j; - -import com.google.common.collect.ImmutableMap; - -import org.apache.log4j.Layout; -import org.apache.log4j.Level; -import org.apache.log4j.spi.LocationInfo; -import org.apache.log4j.spi.LoggingEvent; -import org.apache.log4j.spi.ThrowableInformation; - -import com.twitter.common.logging.Glog; -import com.twitter.common.logging.Glog.Formatter; - -/** - * Log4j Layout to match the format generated by glog. - * - * @see Glog - */ -public class GlogLayout extends Layout implements Formatter<LoggingEvent> { - - private static final ImmutableMap<Level, Glog.Level> LEVEL_LABELS = - ImmutableMap.<Level, Glog.Level>builder() - .put(Level.TRACE, Glog.Level.DEBUG) - .put(Level.DEBUG, Glog.Level.DEBUG) - .put(Level.INFO, Glog.Level.INFO) - .put(Level.WARN, Glog.Level.WARNING) - .put(Level.ERROR, Glog.Level.ERROR) - .put(Level.FATAL, Glog.Level.FATAL) - .build(); - - @Override - public String format(LoggingEvent record) { - return Glog.formatRecord(this, record); - } - - @Override - public boolean ignoresThrowable() { - return false; // We handle stack trace formatting. - } - - @Override - public void activateOptions() { - // We use no options - } - - @Override - public String getMessage(LoggingEvent record) { - return record.getRenderedMessage(); - } - - @Override - public String getClassName(LoggingEvent record) { - LocationInfo locationInformation = record.getLocationInformation(); - return (locationInformation != null) - ? locationInformation.getClassName() - : null; - } - - @Override - public String getMethodName(LoggingEvent record) { - LocationInfo locationInformation = record.getLocationInformation(); - return (locationInformation != null) - ? record.getLocationInformation().getMethodName() - : null; - } - - @Override - public Glog.Level getLevel(LoggingEvent record) { - return LEVEL_LABELS.get(record.getLevel()); - } - - @Override - public long getTimeStamp(LoggingEvent record) { - return record.getTimeStamp(); - } - - @Override - public long getThreadId(LoggingEvent record) { - return Thread.currentThread().getId(); - } - - @Override - public Throwable getThrowable(LoggingEvent record) { - ThrowableInformation throwableInformation = record.getThrowableInformation(); - return throwableInformation != null ? throwableInformation.getThrowable() : null; - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/Environment.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/Environment.java b/commons/src/main/java/com/twitter/common/net/Environment.java deleted file mode 100644 index 1609283..0000000 --- a/commons/src/main/java/com/twitter/common/net/Environment.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * 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.twitter.common.net; - -/** - * Represents a network environment at the granularity of a datacenter. - * - * @author John Sirois - */ -public interface Environment { - - /** - * Returns the name of this network environment's datacenter. - * - * @return the name of this environment's datacenter - */ - String dcName(); - - /** - * Creates a fully qualified hostname for a given unqualified hostname in the network - * environment's datacenter. Does not confirm that the host exists. - * - * @param hostname The simple hostname to qualify. - * @return The fully qualified hostname. - */ - String fullyQualify(String hostname); - - /** - * Checks if a given {@code hostname} is a valid hostname for a host in this network environment; - * does not guarantee that the host exists in this network environment. - * - * @param hostname The simple hostname to check for membership in this network environment. - * @return {@code true} if the hostname is a valid hostname for this network environment. - */ - boolean contains(String hostname); -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/InetSocketAddressHelper.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/InetSocketAddressHelper.java b/commons/src/main/java/com/twitter/common/net/InetSocketAddressHelper.java deleted file mode 100644 index e7b01df..0000000 --- a/commons/src/main/java/com/twitter/common/net/InetSocketAddressHelper.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * 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.twitter.common.net; - -import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.common.base.Throwables; -import com.google.common.collect.Iterables; -import com.google.common.collect.Sets; -import org.apache.commons.lang.StringUtils; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.UnknownHostException; -import java.util.Set; - -/** - * A utility that can parse [host]:[port] pairs or :[port] designators into instances of - * {@link java.net.InetSocketAddress}. The literal '*' can be specified for port as an alternative - * to '0' to indicate any local port. - * - * @author John Sirois - */ -public final class InetSocketAddressHelper { - - /** - * A function that uses {@link #parse(String)} to map an endpoint spec to an - * {@link InetSocketAddress}. - */ - public static final Function<String, InetSocketAddress> STR_TO_INET = - new Function<String, InetSocketAddress>() { - @Override public InetSocketAddress apply(String value) { - return parse(value); - } - }; - - /** - * A function that uses {@link #getLocalAddress(int)} to map a local port number to an - * {@link InetSocketAddress}. - * If an {@link UnknownHostException} is thrown, it will be propagated as a - * {@link RuntimeException}. - */ - public static final Function<Integer, InetSocketAddress> INT_TO_INET = - new Function<Integer, InetSocketAddress>() { - @Override public InetSocketAddress apply(Integer port) { - try { - return getLocalAddress(port); - } catch (UnknownHostException e) { - throw Throwables.propagate(e); - } - } - }; - - public static final Function<InetSocketAddress, String> INET_TO_STR = - new Function<InetSocketAddress, String>() { - @Override public String apply(InetSocketAddress addr) { - return InetSocketAddressHelper.toString(addr); - } - }; - - /** - * Attempts to parse an endpoint spec into an InetSocketAddress. - * - * @param value the endpoint spec - * @return a parsed InetSocketAddress - * @throws NullPointerException if {@code value} is {@code null} - * @throws IllegalArgumentException if {@code value} cannot be parsed - */ - public static InetSocketAddress parse(String value) { - Preconditions.checkNotNull(value); - - String[] spec = value.split(":", 2); - if (spec.length != 2) { - throw new IllegalArgumentException("Invalid socket address spec: " + value); - } - - String host = spec[0]; - int port = asPort(spec[1]); - - return StringUtils.isEmpty(host) - ? new InetSocketAddress(port) - : InetSocketAddress.createUnresolved(host, port); - } - - /** - * Attempts to return a usable String given an InetSocketAddress. - * - * @param value the InetSocketAddress. - * @return the String representation of the InetSocketAddress. - */ - public static String toString(InetSocketAddress value) { - Preconditions.checkNotNull(value); - return value.getHostName() + ":" + value.getPort(); - } - - private static int asPort(String port) { - if ("*".equals(port)) { - return 0; - } - try { - return Integer.parseInt(port); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Invalid port: " + port, e); - } - } - - public static InetSocketAddress getLocalAddress(int port) throws UnknownHostException { - String ipAddress = InetAddress.getLocalHost().getHostAddress(); - return new InetSocketAddress(ipAddress, port); - } - - private InetSocketAddressHelper() { - // utility - } - - /** - * Converts backend definitions (in host:port form) a set of socket addresses. - * - * @param backends Backends to convert. - * @return Sockets representing the provided backends. - */ - public static Set<InetSocketAddress> convertToSockets(Iterable<String> backends) { - return Sets.newHashSet(Iterables.transform(backends, STR_TO_INET)); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/ProxyAuthorizer.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/ProxyAuthorizer.java b/commons/src/main/java/com/twitter/common/net/ProxyAuthorizer.java deleted file mode 100644 index 5dbe653..0000000 --- a/commons/src/main/java/com/twitter/common/net/ProxyAuthorizer.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * 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.twitter.common.net; - -import org.apache.commons.codec.binary.Base64; - -import java.net.HttpURLConnection; - -/** - * Authorizes http connection for use over the proxy it is built with - * - * @author William Farner - */ -public class ProxyAuthorizer { - private final ProxyConfig config; - - private ProxyAuthorizer(ProxyConfig config) { - this.config = config; - } - - public static ProxyAuthorizer adapt(ProxyConfig config) { - return new ProxyAuthorizer(config); - } - - public void authorize(HttpURLConnection httpCon) { - httpCon.setRequestProperty("Proxy-Authorization", "Basic " + - new String(Base64.encodeBase64(new String(config.getProxyUser() + ":" + - config.getProxyPassword()).getBytes())).trim()); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/ProxyConfig.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/ProxyConfig.java b/commons/src/main/java/com/twitter/common/net/ProxyConfig.java deleted file mode 100644 index 0765bad..0000000 --- a/commons/src/main/java/com/twitter/common/net/ProxyConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * 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.twitter.common.net; - -import java.net.InetSocketAddress; -import javax.annotation.Nullable; - -/** - * Proxy configuration parameters: proxy address, username, and password. - * - * @author John Corwin - */ -public interface ProxyConfig { - public InetSocketAddress getProxyAddress(); - - public @Nullable String getProxyUser(); - - public @Nullable String getProxyPassword(); -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/UrlHelper.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/UrlHelper.java b/commons/src/main/java/com/twitter/common/net/UrlHelper.java deleted file mode 100644 index 3375f19..0000000 --- a/commons/src/main/java/com/twitter/common/net/UrlHelper.java +++ /dev/null @@ -1,156 +0,0 @@ -/** - * 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.twitter.common.net; - -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.google.common.collect.Lists; - -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Arrays; -import java.util.List; -import java.util.logging.Logger; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * @author William Farner - */ -public class UrlHelper { - - private static final Logger LOG = Logger.getLogger(UrlHelper.class.getName()); - - /** - * Gets the domain from {@code url}. - * - * @param url A url. - * @return The domain portion of the URL, or {@code null} if the url is invalid. - */ - public static String getDomain(String url) { - try { - return getDomainChecked(url); - } catch (URISyntaxException e) { - LOG.finest("Malformed url: " + url); - return null; - } - } - - /** - * Gets the domain from {@code uri}, and throws an exception if it's not a valid uri. - * - * @param url A url. - * @throws URISyntaxException if url is not a valid {@code URI} - * @return The domain portion of the given url, or {@code null} if the host is undefined. - */ - public static String getDomainChecked(String url) throws URISyntaxException { - Preconditions.checkNotNull(url); - url = addProtocol(url); - return new URI(url).getHost(); - } - - /** - * Gets the path from {@code url}. - * - * @param url A url. - * @return The path portion of the URL, or {@code null} if the url is invalid. - */ - public static String getPath(String url) { - Preconditions.checkNotNull(url); - url = addProtocol(url); - try { - return new URI(url).getPath(); - } catch (URISyntaxException e) { - LOG.info("Malformed url: " + url); - return null; - } - } - - /** - * Strips URL parameters from a url. - * This will remove anything after and including a question mark in the URL. - * - * @param url The URL to strip parameters from. - * @return The original URL with parameters stripped, which will be the original URL if no - * parameters were found. - */ - public static String stripUrlParameters(String url) { - Preconditions.checkNotNull(url); - int paramStartIndex = url.indexOf("?"); - if (paramStartIndex == -1) { - return url; - } else { - return url.substring(0, paramStartIndex); - } - } - - /** - * Convenience method that calls #stripUrlParameters(String) for a URL. - * - * @param url The URL to strip parameters from. - * @return The original URL with parameters stripped, which will be the original URL if no - * parameters were found. - */ - public static String stripUrlParameters(URL url) { - return stripUrlParameters(url.toString()); - } - - private static final Pattern URL_PROTOCOL_REGEX = - Pattern.compile("^https?://", Pattern.CASE_INSENSITIVE); - - /** - * Checks whether a URL specifies its protocol, prepending http if it does not. - * - * @param url The URL to fix. - * @return The URL with the http protocol specified if no protocol was already specified. - */ - public static String addProtocol(String url) { - Preconditions.checkNotNull(url); - Matcher matcher = URL_PROTOCOL_REGEX.matcher(url); - if (!matcher.find()) { - url = "http://" + url; - } - return url; - } - - /** - * Gets the domain levels for a host. - * For example, sub1.sub2.domain.co.uk would return - * [sub1.sub2.domain.co.uk, sub2.domain.co.uk, domain.co.uk, co.uk, uk]. - * - * - * @param host The host to peel subdomains off from. - * @return The domain levels in this host. - */ - public static List<String> getDomainLevels(String host) { - Preconditions.checkNotNull(host); - - // Automatically include www prefix if not present. - if (!host.startsWith("www")) { - host = "www." + host; - } - - Joiner joiner = Joiner.on("."); - List<String> domainParts = Lists.newLinkedList(Arrays.asList(host.split("\\."))); - List<String> levels = Lists.newLinkedList(); - - while (!domainParts.isEmpty()) { - levels.add(joiner.join(domainParts)); - domainParts.remove(0); - } - - return levels; - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/UrlResolver.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/UrlResolver.java b/commons/src/main/java/com/twitter/common/net/UrlResolver.java deleted file mode 100644 index 1fd49b6..0000000 --- a/commons/src/main/java/com/twitter/common/net/UrlResolver.java +++ /dev/null @@ -1,446 +0,0 @@ -/** - * 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.twitter.common.net; - -import java.io.IOException; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.logging.Level; -import java.util.logging.Logger; - -import javax.annotation.Nullable; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Functions; -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ListenableFutureTask; -import com.google.common.util.concurrent.ThreadFactoryBuilder; - -import com.twitter.common.base.ExceptionalFunction; -import com.twitter.common.net.UrlResolver.ResolvedUrl.EndState; -import com.twitter.common.quantity.Amount; -import com.twitter.common.quantity.Time; -import com.twitter.common.stats.PrintableHistogram; -import com.twitter.common.util.BackoffStrategy; -import com.twitter.common.util.Clock; -import com.twitter.common.util.TruncatedBinaryBackoff; -import com.twitter.common.util.caching.Cache; -import com.twitter.common.util.caching.LRUCache; - -/** - * Class to aid in resolving URLs by following redirects, which can optionally be performed - * asynchronously using a thread pool. - * - * @author William Farner - */ -public class UrlResolver { - private static final Logger LOG = Logger.getLogger(UrlResolver.class.getName()); - - private static final String TWITTER_UA = "Twitterbot/0.1"; - private static final UrlResolverUtil URL_RESOLVER = - new UrlResolverUtil(Functions.constant(TWITTER_UA)); - - private static final ExceptionalFunction<String, String, IOException> RESOLVER = - new ExceptionalFunction<String, String, IOException>() { - @Override public String apply(String url) throws IOException { - return URL_RESOLVER.getEffectiveUrl(url, null); - } - }; - - private static ExceptionalFunction<String, String, IOException> - getUrlResolver(final @Nullable ProxyConfig proxyConfig) { - if (proxyConfig != null) { - return new ExceptionalFunction<String, String, IOException>() { - @Override public String apply(String url) throws IOException { - return URL_RESOLVER.getEffectiveUrl(url, proxyConfig); - } - }; - } else { - return RESOLVER; - } - } - - private final ExceptionalFunction<String, String, IOException> resolver; - private final int maxRedirects; - - // Tracks the number of active tasks (threads in use). - private final Semaphore poolEntrySemaphore; - private final Integer threadPoolSize; - - // Helps with signaling the handler. - private final Executor handlerExecutor; - - // Manages the thread pool and task execution. - private ExecutorService executor; - - // Cache to store resolved URLs. - private final Cache<String, String> urlCache = LRUCache.<String, String>builder() - .maxSize(10000) - .makeSynchronized(true) - .build(); - - // Variables to track connection/request stats. - private AtomicInteger requestCount = new AtomicInteger(0); - private AtomicInteger cacheHits = new AtomicInteger(0); - private AtomicInteger failureCount = new AtomicInteger(0); - // Tracks the time (in milliseconds) required to resolve URLs. - private final PrintableHistogram urlResolutionTimesMs = new PrintableHistogram( - 1, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 500, 750, 1000, 1500, 2000); - - private final Clock clock; - private final BackoffStrategy backoffStrategy; - - @VisibleForTesting - UrlResolver(Clock clock, BackoffStrategy backoffStrategy, - ExceptionalFunction<String, String, IOException> resolver, int maxRedirects) { - this(clock, backoffStrategy, resolver, maxRedirects, null); - } - - /** - * Creates a new asynchronous URL resolver. A thread pool will be used to resolve URLs, and - * resolved URLs will be announced via {@code handler}. - * - * @param maxRedirects The maximum number of HTTP redirects to follow. - * @param threadPoolSize The number of threads to use for resolving URLs. - * @param proxyConfig The proxy settings with which to make the HTTP request, or null for the - * default configured proxy. - */ - public UrlResolver(int maxRedirects, int threadPoolSize, @Nullable ProxyConfig proxyConfig) { - this(Clock.SYSTEM_CLOCK, - new TruncatedBinaryBackoff(Amount.of(100L, Time.MILLISECONDS), Amount.of(1L, Time.SECONDS)), - getUrlResolver(proxyConfig), maxRedirects, threadPoolSize); - } - - public UrlResolver(int maxRedirects, int threadPoolSize) { - this(maxRedirects, threadPoolSize, null); - } - - private UrlResolver(Clock clock, BackoffStrategy backoffStrategy, - ExceptionalFunction<String, String, IOException> resolver, int maxRedirects, - @Nullable Integer threadPoolSize) { - this.clock = clock; - this.backoffStrategy = backoffStrategy; - this.resolver = resolver; - this.maxRedirects = maxRedirects; - - if (threadPoolSize != null) { - this.threadPoolSize = threadPoolSize; - Preconditions.checkState(threadPoolSize > 0); - poolEntrySemaphore = new Semaphore(threadPoolSize); - - // Start up the thread pool. - reset(); - - // Executor to send notifications back to the handler. This also needs to be - // a daemon thread. - handlerExecutor = - Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setDaemon(true).build()); - } else { - this.threadPoolSize = null; - poolEntrySemaphore = null; - handlerExecutor = null; - } - } - - public Future<ResolvedUrl> resolveUrlAsync(final String url, final ResolvedUrlHandler handler) { - Preconditions.checkNotNull( - "Asynchronous URL resolution cannot be performed without a valid handler.", handler); - - try { - poolEntrySemaphore.acquire(); - } catch (InterruptedException e) { - LOG.log(Level.SEVERE, "Interrupted while waiting for thread to resolve URL: " + url, e); - return null; - } - final ListenableFutureTask<ResolvedUrl> future = - ListenableFutureTask.create( - new Callable<ResolvedUrl>() { - @Override public ResolvedUrl call() { - return resolveUrl(url); - } - }); - - future.addListener(new Runnable() { - @Override public void run() { - try { - handler.resolved(future); - } finally { - poolEntrySemaphore.release(); - } - } - }, handlerExecutor); - - executor.execute(future); - return future; - } - - private void logThreadpoolInfo() { - LOG.info("Shutting down thread pool, available permits: " - + poolEntrySemaphore.availablePermits()); - LOG.info("Queued threads? " + poolEntrySemaphore.hasQueuedThreads()); - LOG.info("Queue length: " + poolEntrySemaphore.getQueueLength()); - } - - public void reset() { - Preconditions.checkState(threadPoolSize != null); - if (executor != null) { - Preconditions.checkState(executor.isShutdown(), - "The thread pool must be shut down before resetting."); - Preconditions.checkState(executor.isTerminated(), "There may still be pending async tasks."); - } - - // Create a thread pool with daemon threads, so that they may be terminated when no - // application threads are running. - executor = Executors.newFixedThreadPool(threadPoolSize, - new ThreadFactoryBuilder().setDaemon(true).setNameFormat("UrlResolver[%d]").build()); - } - - /** - * Terminates the thread pool, waiting at most {@code waitSeconds} for active threads to complete. - * After this method is called, no more URLs may be submitted for resolution. - * - * @param waitSeconds The number of seconds to wait for active threads to complete. - */ - public void clearAsyncTasks(int waitSeconds) { - Preconditions.checkState(threadPoolSize != null, - "finish() should not be called on a synchronous URL resolver."); - - logThreadpoolInfo(); - executor.shutdown(); // Disable new tasks from being submitted. - try { - // Wait a while for existing tasks to terminate - if (!executor.awaitTermination(waitSeconds, TimeUnit.SECONDS)) { - LOG.info("Pool did not terminate, forcing shutdown."); - logThreadpoolInfo(); - List<Runnable> remaining = executor.shutdownNow(); - LOG.info("Tasks still running: " + remaining); - // Wait a while for tasks to respond to being cancelled - if (!executor.awaitTermination(waitSeconds, TimeUnit.SECONDS)) { - LOG.warning("Pool did not terminate."); - logThreadpoolInfo(); - } - } - } catch (InterruptedException e) { - LOG.log(Level.WARNING, "Interrupted while waiting for threadpool to finish.", e); - // (Re-)Cancel if current thread also interrupted - executor.shutdownNow(); - // Preserve interrupt status - Thread.currentThread().interrupt(); - } - } - - /** - * Resolves a URL synchronously. - * - * @param url The URL to resolve. - * @return The resolved URL. - */ - public ResolvedUrl resolveUrl(String url) { - ResolvedUrl resolvedUrl = new ResolvedUrl(); - resolvedUrl.setStartUrl(url); - - String cached = urlCache.get(url); - if (cached != null) { - cacheHits.incrementAndGet(); - resolvedUrl.setNextResolve(cached); - resolvedUrl.setEndState(EndState.CACHED); - return resolvedUrl; - } - - String currentUrl = url; - long backoffMs = 0L; - String next = null; - for (int i = 0; i < maxRedirects; i++) { - try { - next = resolveOnce(currentUrl); - - // If there was a 4xx or a 5xx, we''ll get a null back, so we pretend like we never advanced - // to allow for a retry within the redirect limit. - // TODO(John Sirois): we really need access to the return code here to do the right thing; ie: - // retry for internal server errors but probably not for unauthorized - if (next == null) { - if (i < maxRedirects - 1) { // don't wait if we're about to exit the loop - backoffMs = backoffStrategy.calculateBackoffMs(backoffMs); - try { - clock.waitFor(backoffMs); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException( - "Interrupted waiting to retry a failed resolution for: " + currentUrl, e); - } - } - continue; - } - - backoffMs = 0L; - if (next.equals(currentUrl)) { - // We've reached the end of the redirect chain. - resolvedUrl.setEndState(EndState.REACHED_LANDING); - urlCache.put(url, currentUrl); - for (String intermediateUrl : resolvedUrl.getIntermediateUrls()) { - urlCache.put(intermediateUrl, currentUrl); - } - return resolvedUrl; - } else if (!url.equals(next)) { - resolvedUrl.setNextResolve(next); - } - currentUrl = next; - } catch (IOException e) { - LOG.log(Level.INFO, "Failed to resolve url: " + url, e); - resolvedUrl.setEndState(EndState.ERROR); - return resolvedUrl; - } - } - - resolvedUrl.setEndState(next == null || url.equals(currentUrl) ? EndState.ERROR - : EndState.REDIRECT_LIMIT); - return resolvedUrl; - } - - /** - * Resolves a url, following at most one redirect. Thread-safe. - * - * @param url The URL to resolve. - * @return The result of following the URL through at most one redirect or null if the url could - * not be followed - * @throws IOException If an error occurs while resolving the URL. - */ - private String resolveOnce(String url) throws IOException { - requestCount.incrementAndGet(); - - String resolvedUrl = urlCache.get(url); - if (resolvedUrl != null) { - cacheHits.incrementAndGet(); - return resolvedUrl; - } - - try { - long startTimeMs = System.currentTimeMillis(); - resolvedUrl = resolver.apply(url); - if (resolvedUrl == null) { - return null; - } - - urlCache.put(url, resolvedUrl); - - synchronized (urlResolutionTimesMs) { - urlResolutionTimesMs.addValue(System.currentTimeMillis() - startTimeMs); - } - return resolvedUrl; - } catch (IOException e) { - failureCount.incrementAndGet(); - throw e; - } - } - - @Override - public String toString() { - return String.format("Cache: %s\nFailed requests: %d,\nResolution Times: %s", - urlCache, failureCount.get(), - urlResolutionTimesMs.toString()); - } - - /** - * Class to wrap the result of a URL resolution. - */ - public static class ResolvedUrl { - public enum EndState { - REACHED_LANDING, - ERROR, - CACHED, - REDIRECT_LIMIT - } - - private String startUrl; - private final List<String> resolveChain; - private EndState endState; - - public ResolvedUrl() { - resolveChain = Lists.newArrayList(); - } - - @VisibleForTesting - public ResolvedUrl(EndState endState, String startUrl, String... resolveChain) { - this.endState = endState; - this.startUrl = startUrl; - this.resolveChain = Lists.newArrayList(resolveChain); - } - - public String getStartUrl() { - return startUrl; - } - - void setStartUrl(String startUrl) { - this.startUrl = startUrl; - } - - /** - * Returns the last URL resolved following a redirect chain, or null if the startUrl is a - * landing URL. - */ - public String getEndUrl() { - return resolveChain.isEmpty() ? null : Iterables.getLast(resolveChain); - } - - void setNextResolve(String endUrl) { - this.resolveChain.add(endUrl); - } - - /** - * Returns any immediate URLs encountered on the resolution chain. If the startUrl redirects - * directly to the endUrl or they are the same the imtermediate URLs will be empty. - */ - public Iterable<String> getIntermediateUrls() { - return resolveChain.size() <= 1 ? ImmutableList.<String>of() - : resolveChain.subList(0, resolveChain.size() - 1); - } - - public EndState getEndState() { - return endState; - } - - void setEndState(EndState endState) { - this.endState = endState; - } - - public String toString() { - return String.format("%s -> %s [%s, %d redirects]", - startUrl, Joiner.on(" -> ").join(resolveChain), endState, resolveChain.size()); - } - } - - /** - * Interface to use for notifying the caller of resolved URLs. - */ - public interface ResolvedUrlHandler { - /** - * Signals that a URL has been resolved to its target. The implementation of this method must - * be thread safe. - * - * @param future The future that has finished resolving a URL. - */ - public void resolved(Future<ResolvedUrl> future); - } -} http://git-wip-us.apache.org/repos/asf/aurora/blob/06ddaadb/commons/src/main/java/com/twitter/common/net/UrlResolverUtil.java ---------------------------------------------------------------------- diff --git a/commons/src/main/java/com/twitter/common/net/UrlResolverUtil.java b/commons/src/main/java/com/twitter/common/net/UrlResolverUtil.java deleted file mode 100644 index c92fcb6..0000000 --- a/commons/src/main/java/com/twitter/common/net/UrlResolverUtil.java +++ /dev/null @@ -1,148 +0,0 @@ -/** - * 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.twitter.common.net; - -import com.google.common.base.Function; -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import com.twitter.common.base.MorePreconditions; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.Proxy; -import java.net.Proxy.Type; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Map; -import java.util.logging.Logger; -import javax.annotation.Nullable; - -/** - * A utility that can resolve HTTP urls. - * - * @author John Sirois - */ -class UrlResolverUtil { - - private static final Logger LOG = Logger.getLogger(UrlResolverUtil.class.getName()); - - // Default user-agent string to user for HTTP requests. - private static final String DEFAULT_USER_AGENT = "Lynxy/6.6.6dev.8 libwww-FM/3.14159FM"; - - private static Map<String, String> checkNotBlank(Map<String, String> hostToUserAgent) { - Preconditions.checkNotNull(hostToUserAgent); - MorePreconditions.checkNotBlank(hostToUserAgent.entrySet()); - return hostToUserAgent; - } - - private final Function<? super URL, String> urlToUserAgent; - - UrlResolverUtil(Map<String, String> hostToUserAgent) { - this(Functions.compose(Functions.forMap(checkNotBlank(hostToUserAgent), DEFAULT_USER_AGENT), - new Function<URL, String>() { - @Override public String apply(URL url) { - return url.getHost(); - } - })); - } - - UrlResolverUtil(Function<? super URL, String> urlToUserAgent) { - this.urlToUserAgent = Preconditions.checkNotNull(urlToUserAgent); - } - - /** - * Returns the URL that {@code url} lands on, which will be the result of a 3xx redirect, - * or {@code url} if the url does not redirect using an HTTP 3xx response code. If there is a - * non-2xx or 3xx HTTP response code null is returned. - * - * @param url The URL to follow. - * @return The redirected URL, or {@code url} if {@code url} returns a 2XX response, otherwise - * null - * @throws java.io.IOException If an error occurs while trying to follow the url. - */ - String getEffectiveUrl(String url, @Nullable ProxyConfig proxyConfig) throws IOException { - Preconditions.checkNotNull(url); - // Don't follow https. - if (url.startsWith("https://")) { - url = url.replace("https://", "http://"); - } else if (!url.startsWith("http://")) { - url = "http://" + url; - } - - URL urlObj = new URL(url); - - HttpURLConnection con; - if (proxyConfig != null) { - Proxy proxy = new Proxy(Type.HTTP, proxyConfig.getProxyAddress()); - con = (HttpURLConnection) urlObj.openConnection(proxy); - ProxyAuthorizer.adapt(proxyConfig).authorize(con); - } else { - con = (HttpURLConnection) urlObj.openConnection(); - } - try { - - // TODO(John Sirois): several commonly tweeted hosts 406 or 400 on HEADs and only work with GETs - // fix the call chain to be able to specify retry-with-GET - con.setRequestMethod("HEAD"); - - con.setUseCaches(true); - con.setConnectTimeout(5000); - con.setReadTimeout(5000); - con.setInstanceFollowRedirects(false); - - // I hate to have to do this, but some URL shorteners don't respond otherwise. - con.setRequestProperty("User-Agent", urlToUserAgent.apply(urlObj)); - try { - con.connect(); - } catch (StringIndexOutOfBoundsException e) { - LOG.info("Got StringIndexOutOfBoundsException when fetching headers for " + url); - return null; - } - - int responseCode = con.getResponseCode(); - switch (responseCode / 100) { - case 2: - return url; - case 3: - String location = con.getHeaderField("Location"); - if (location == null) { - if (responseCode != 304 /* not modified */) { - LOG.info( - String.format("[%d] Location header was null for URL: %s", responseCode, url)); - } - return url; - } - - // HTTP 1.1 spec says this should be an absolute URI, but i see lots of instances where it - // is relative, so we need to check. - try { - String domain = UrlHelper.getDomainChecked(location); - if (domain == null || domain.isEmpty()) { - // This is a relative URI. - location = "http://" + UrlHelper.getDomain(url) + location; - } - } catch (URISyntaxException e) { - LOG.info("location contained an invalid URI: " + location); - } - - return location; - default: - LOG.info("Failed to resolve url: " + url + " with: " - + responseCode + " -> " + con.getResponseMessage()); - return null; - } - } finally { - con.disconnect(); - } - } -}