private StackTraceDeobfuscator getDeobfuscator() throws IOException {
   if (deobfuscator == null) {
     String path = getRequestModuleBasePath() + "/" + JUnitSymbolMapsLinker.SYMBOL_MAP_DIR;
     deobfuscator = StackTraceDeobfuscator.fromUrl(getServletContext().getResource(path));
   }
   return deobfuscator;
 }
  @Override
  public LogRecord deobfuscateLogRecord(LogRecord value) {
    // don't deobfuscate DevMode, there's no symbol map
    if ("HostedMode".equals(getPermutationStrongName())) {
      return value;
    }

    StackTraceDeobfuscator deobf = StackTraceDeobfuscator.fromUrl(getSymbolMapUrl());

    HttpServletRequest threadLocalRequest = getThreadLocalRequest();
    String strongName = null;
    if (threadLocalRequest != null) {
      // can be null during tests
      strongName = threadLocalRequest.getHeader(RpcRequestBuilder.STRONG_NAME_HEADER);
    }
    LogRecord newRecord = RemoteLoggingServiceUtil.deobfuscateLogRecord(deobf, value, strongName);
    Logger.getLogger(value.getLoggerName()).log(newRecord);
    return newRecord;
  }
  public final String logOnServer(LogRecord lr) {

    String modulePath = getRequestModuleBasePath();
    String strongName = getPermutationStrongName();
    try {

      if (!deobfuscators.containsKey(modulePath)) {
        deobfuscators.put(
            modulePath,
            StackTraceDeobfuscator.fromUrl(
                getServletContext().getResource("/WEB-INF/deploy" + modulePath + "symbolMaps/")));
      }

      logOnServer(lr, strongName, deobfuscators.get(modulePath), null);
    } catch (RemoteLoggingServiceUtil.RemoteLoggingException e) {
      log.log(Level.SEVERE, "Remote logging failed", e);
      return "Remote logging failed, check stack trace for details.";
    } catch (MalformedURLException e) {
      log.log(Level.SEVERE, "Remote logging failed", e);
      return "Remote logging failed, check stack trace for details.";
    }
    return null;
  }