Example #1
0
  /**
   * Takes a packed-stream InputStream, and writes to a JarOutputStream. Internally the entire
   * buffer must be read, it may be more efficient to read the packed-stream to a file and pass the
   * File object, in the alternate method described below.
   *
   * <p>Closes its input but not its output. (The output can accumulate more elements.)
   *
   * @param in an InputStream.
   * @param out a JarOutputStream.
   * @exception IOException if an error is encountered.
   */
  public void unpack(InputStream in0, JarOutputStream out) throws IOException {
    assert (Utils.currentInstance.get() == null);
    TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null : TimeZone.getDefault();

    try {
      Utils.currentInstance.set(this);
      if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
      final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
      BufferedInputStream in = new BufferedInputStream(in0);
      if (Utils.isJarMagic(Utils.readMagic(in))) {
        if (verbose > 0) Utils.log.info("Copying unpacked JAR file...");
        Utils.copyJarFile(new JarInputStream(in), out);
      } else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
        (new DoUnpack()).run(in, out);
        in.close();
        Utils.markJarFile(out);
      } else {
        (new NativeUnpack(this)).run(in, out);
        in.close();
        Utils.markJarFile(out);
      }
    } finally {
      _nunp = null;
      Utils.currentInstance.set(null);
      if (tz != null) TimeZone.setDefault(tz);
    }
  }
 private void setTimeZone(String line) throws JBookTraderException {
   String timeZone = line.substring(line.indexOf('=') + 1);
   TimeZone tz = TimeZone.getTimeZone(timeZone);
   if (!tz.getID().equals(timeZone)) {
     String msg =
         "The specified time zone " + "\"" + timeZone + "\"" + " does not exist." + LINE_SEP;
     msg += "Examples of valid time zones: " + " America/New_York, Europe/London, Asia/Singapore.";
     throw new JBookTraderException(msg);
   }
   sdf = new SimpleDateFormat("MMddyyHHmmss");
   // Enforce strict interpretation of date and time formats
   sdf.setLenient(false);
   sdf.setTimeZone(tz);
 }
Example #3
0
 /** This code borrowed from Piesquared on irc.nexuswar.com */
 private TimeZone tZF(String search) {
   if (search.equals("")) return TimeZone.getTimeZone("GMT");
   search = search.toLowerCase();
   search = search.replace("+", "\\+");
   search = search.replace("*", "\\*");
   search = search.replace("?", "\\?");
   String[] zones = TimeZone.getAvailableIDs();
   for (int i = 0; i < zones.length; i++)
     if (zones[i].toLowerCase().equals(search)) return TimeZone.getTimeZone(zones[i]);
   for (int i = 0; i < zones.length; i++)
     if (zones[i].toLowerCase().matches(".*" + search + ".*"))
       return TimeZone.getTimeZone(zones[i]);
   return TimeZone.getTimeZone("GMT");
 }
Example #4
0
  /**
   * Converts this <code>Date</code> object to a <code>String</code>. The output format is as
   * follows:
   *
   * <blockquote>
   *
   * <pre>yyyy MM dd hh mm ss +zzzz</pre>
   *
   * </blockquote>
   *
   * where:
   *
   * <ul>
   *   <li>
   *   <dd>yyyy is the year, as four decimal digits. Year values larger than
   *   <dd>9999 will be truncated to
   *   <dd>9999.
   *   <li>
   *   <dd>MM is the month (
   *   <dd>01 through
   *   <dd>12), as two decimal digits.
   *   <li>
   *   <dd>dd is the day of the month (
   *   <dd>01 through
   *   <dd>31), as two decimal digits.
   *   <li>
   *   <dd>hh is the hour of the day (
   *   <dd>00 through
   *   <dd>23), as two decimal digits.
   *   <li>
   *   <dd>mm is the minute within the hour (
   *   <dd>00 through
   *   <dd>59), as two decimal digits.
   *   <li>
   *   <dd>ss is the second within the minute (
   *   <dd>00 through
   *   <dd>59), as two decimal digits.
   *   <li>
   *   <dd>zzzz is the time zone offset in hours and minutes (four decimal digits
   *   <dd>"hhmm") relative to GMT, preceded by a "+" or "-" character (
   *   <dd>-1200 through
   *   <dd>+1200). For instance, Pacific Standard Time zone is printed as
   *   <dd>-0800. GMT is printed as
   *   <dd>+0000.
   * </ul>
   *
   * @return a string representation of this date.
   */
  public static String toISO8601String(Calendar calendar) {
    // Printing in the absence of a Calendar
    // implementation class is not supported
    if (calendar == null) {
      return "0000 00 00 00 00 00 +0000";
    }

    int year = calendar.get(Calendar.YEAR);
    int month = calendar.get(Calendar.MONTH) + 1;
    int day = calendar.get(Calendar.DAY_OF_MONTH);
    int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY);
    int hour = calendar.get(Calendar.HOUR);
    int minute = calendar.get(Calendar.MINUTE);
    int seconds = calendar.get(Calendar.SECOND);

    String yr = Integer.toString(year);

    // The total size of the string buffer
    // yr.length+1+2+1+2+1+2+1+2+1+2+1+5 = 25 + yr.length
    StringBuffer sb = new StringBuffer(25 + yr.length());

    appendFourDigits(sb, year).append(' ');
    appendTwoDigits(sb, month).append(' ');
    appendTwoDigits(sb, day).append(' ');
    appendTwoDigits(sb, hour_of_day).append(' ');
    appendTwoDigits(sb, minute).append(' ');
    appendTwoDigits(sb, seconds).append(' ');

    // TimeZone offset is represented in milliseconds.
    // Convert the offset to minutes:
    TimeZone t = calendar.getTimeZone();
    int zoneOffsetInMinutes = t.getRawOffset() / 1000 / 60;

    if (zoneOffsetInMinutes < 0) {
      zoneOffsetInMinutes = Math.abs(zoneOffsetInMinutes);
      sb.append('-');
    } else {
      sb.append('+');
    }

    int zoneHours = zoneOffsetInMinutes / 60;
    int zoneMinutes = zoneOffsetInMinutes % 60;

    appendTwoDigits(sb, zoneHours);
    appendTwoDigits(sb, zoneMinutes);

    return sb.toString();
  }
 protected Comment getGeneratedBy(boolean timestamp) {
   String text = "Generated by javadoc"; // marker string, deliberately not localized
   if (timestamp) {
     Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
     Date today = calendar.getTime();
     text += " (" + configuration.getDocletSpecificBuildDate() + ") on " + today;
   }
   return new Comment(text);
 }
  private XMLGregorianCalendar getTimeToXmlTime(long lastModified)
      throws DatatypeConfigurationException {

    GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC"));

    gc.setTime(new Date(lastModified));

    XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
    return xmlTime;
  }
Example #7
0
  static Date parseDate(String s) {
    Calendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));

    int year = Integer.parseInt(s.substring(0, 4));
    int month = Integer.parseInt(s.substring(4, 6)) - 1;
    int date = Integer.parseInt(s.substring(6, 8));
    int hour = Integer.parseInt(s.substring(8, 10));
    int minute = Integer.parseInt(s.substring(10, 12));
    int second = Integer.parseInt(s.substring(12, 14));
    c.set(year, month, date, hour, minute, second);

    return c.getTime();
  }
Example #8
0
File: Macro.java Project: bramk/bnd
  public String _tstamp(String args[]) {
    String format = "yyyyMMddHHmm";
    long now = System.currentTimeMillis();
    TimeZone tz = TimeZone.getTimeZone("UTC");

    if (args.length > 1) {
      format = args[1];
    }
    if (args.length > 2) {
      tz = TimeZone.getTimeZone(args[2]);
    }
    if (args.length > 3) {
      now = Long.parseLong(args[3]);
    }
    if (args.length > 4) {
      domain.warning("Too many arguments for tstamp: " + Arrays.toString(args));
    }

    SimpleDateFormat sdf = new SimpleDateFormat(format);
    sdf.setTimeZone(tz);

    return sdf.format(new Date(now));
  }
Example #9
0
  /**
   * Converts this <code>Date</code> object to a <code>String</code> of the form:
   *
   * <blockquote>
   *
   * <pre>
   * dow mon dd hh:mm:ss zzz yyyy</pre>
   *
   * </blockquote>
   *
   * where:
   *
   * <ul>
   *   <li><tt>dow</tt> is the day of the week (<tt>Sun, Mon, Tue, Wed, Thu, Fri, Sat</tt>).
   *   <li><tt>mon</tt> is the month (<tt>Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov,
   *       Dec</tt>).
   *   <li><tt>dd</tt> is the day of the month (<tt>01</tt> through <tt>31</tt>), as two decimal
   *       digits.
   *   <li><tt>hh</tt> is the hour of the day (<tt>00</tt> through <tt>23</tt>), as two decimal
   *       digits.
   *   <li><tt>mm</tt> is the minute within the hour (<tt>00</tt> through <tt>59</tt>), as two
   *       decimal digits.
   *   <li><tt>ss</tt> is the second within the minute (<tt>00</tt> through <tt>61</tt>, as two
   *       decimal digits.
   *   <li><tt>zzz</tt> is the time zone (and may reflect daylight savings time). If time zone
   *       information is not available, then <tt>zzz</tt> is empty - that is, it consists of no
   *       characters at all.
   *   <li><tt>yyyy</tt> is the year, as four decimal digits.
   * </ul>
   *
   * @return a string representation of this date.
   */
  public static String toString(Calendar calendar) {
    // Printing in the absence of a Calendar
    // implementation class is not supported
    if (calendar == null) {
      return "Thu Jan 01 00:00:00 UTC 1970";
    }

    int dow = calendar.get(Calendar.DAY_OF_WEEK);
    int month = calendar.get(Calendar.MONTH);
    int day = calendar.get(Calendar.DAY_OF_MONTH);
    int hour_of_day = calendar.get(Calendar.HOUR_OF_DAY);
    int minute = calendar.get(Calendar.MINUTE);
    int seconds = calendar.get(Calendar.SECOND);
    int year = calendar.get(Calendar.YEAR);

    String yr = Integer.toString(year);

    TimeZone zone = calendar.getTimeZone();
    String zoneID = zone.getID();
    if (zoneID == null) zoneID = "";

    // The total size of the string buffer
    // 3+1+3+1+2+1+2+1+2+1+2+1+zoneID.length+1+yr.length
    //  = 21 + zoneID.length + yr.length
    StringBuffer sb = new StringBuffer(25 + zoneID.length() + yr.length());

    sb.append(days[dow - 1]).append(' ');
    sb.append(months[month]).append(' ');
    appendTwoDigits(sb, day).append(' ');
    appendTwoDigits(sb, hour_of_day).append(':');
    appendTwoDigits(sb, minute).append(':');
    appendTwoDigits(sb, seconds).append(' ');
    if (zoneID.length() > 0) sb.append(zoneID).append(' ');
    appendFourDigits(sb, year);

    return sb.toString();
  }
  /** Creates a new instance of Config */
  private Config() {
    getPhoneManufacturer();

    int gmtloc = TimeZone.getDefault().getRawOffset() / 3600000;
    locOffset = 0;
    gmtOffset = gmtloc;

    short greenKeyCode = -1000;

    if (phoneManufacturer == SONYE) {
      // prefetch images
      RosterIcons.getInstance();
      SmilesIcons.getInstance();

      allowMinimize = true;
      greenKeyCode = VirtualList.SE_GREEN;
      if (phoneManufacturer == SONYE_M600) {
        KEY_BACK = -11;
      }
    } else if (phoneManufacturer == NOKIA) {
      // blFlash=false;
      greenKeyCode = VirtualList.NOKIA_GREEN;
    } else if (phoneManufacturer == MOTOEZX) {
      // VirtualList.keyClear=0x1000;
      VirtualList.keyVolDown = VirtualList.MOTOE680_VOL_DOWN;
      KEY_BACK = VirtualList.MOTOE680_REALPLAYER;
    } else if (phoneManufacturer == MOTO) {
      ghostMotor = true;
      // blFlash=false;
      istreamWaiting = true;
      greenKeyCode = VirtualList.MOTOROLA_GREEN;
      // VirtualList.keyClear=0x1000;
    } else if (phoneManufacturer == SIEMENS || phoneManufacturer == SIEMENS2) {
      keyLock = '#';
      keyVibra = '*';
      allowLightControl = true;
      // blFlash=true;
      KEY_BACK = -4; // keyCode==702
      greenKeyCode = VirtualList.SIEMENS_GREEN;
    } else if (phoneManufacturer == WTK) {
      greenKeyCode = VirtualList.NOKIA_GREEN;
    }

    VirtualList.greenKeyCode = greenKeyCode;
  }
Example #11
0
  static String formatDate(Date d) {
    Calendar c = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
    StringBuffer sb = new StringBuffer();
    NumberFormat w4 = new DecimalFormat();
    w4.setMinimumIntegerDigits(4);
    w4.setGroupingUsed(false);
    NumberFormat w2 = new DecimalFormat();
    w2.setMinimumIntegerDigits(2);

    c.setTime(d);
    sb.append(w4.format(c.get(c.YEAR)));
    sb.append(w2.format(c.get(c.MONTH) + 1));
    sb.append(w2.format(c.get(c.DAY_OF_MONTH)));
    sb.append(w2.format(c.get(c.HOUR_OF_DAY)));
    sb.append(w2.format(c.get(c.MINUTE)));
    sb.append(w2.format(c.get(c.SECOND)));
    return sb.toString();
  }
Example #12
0
  @Test
  public void testRead1() throws Exception {

    DataSet dataSet = from(this.getClass().getResourceAsStream("test1.json"));
    assertNotNull(dataSet);

    final DataSetMetadata metadata = dataSet.getMetadata();
    assertEquals("410d2196-8f90-478f-a817-7e8b6694ac91", metadata.getId());
    assertEquals("test", metadata.getName());
    assertEquals("anonymousUser", metadata.getAuthor());
    assertEquals(2, metadata.getContent().getNbRecords());
    assertEquals(1, metadata.getContent().getNbLinesInHeader());
    assertEquals(0, metadata.getContent().getNbLinesInFooter());

    final SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy HH:mm");
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

    Date expectedDate = dateFormat.parse("02-17-2015 09:02");
    assertEquals(expectedDate, new Date(metadata.getCreationDate()));

    List<ColumnMetadata> columns = dataSet.getMetadata().getRowMetadata().getColumns();
    assertEquals(6, columns.size());

    ColumnMetadata firstColumn = columns.get(0);
    assertEquals("0001", firstColumn.getId());
    assertEquals("id", firstColumn.getName());
    assertEquals("integer", firstColumn.getType());
    assertEquals(20, firstColumn.getQuality().getEmpty());
    assertEquals(26, firstColumn.getQuality().getInvalid());
    assertEquals(54, firstColumn.getQuality().getValid());

    ColumnMetadata lastColumn = columns.get(5);
    assertEquals("0007", lastColumn.getId());
    assertEquals("string", lastColumn.getType());
    assertEquals(8, lastColumn.getQuality().getEmpty());
    assertEquals(25, lastColumn.getQuality().getInvalid());
    assertEquals(67, lastColumn.getQuality().getValid());
  }
Example #13
0
 static {
   String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
   tz = TimeZone.getTimeZone("GMT");
   df = new SimpleDateFormat(pattern, Locale.US);
   df.setTimeZone(tz);
 }
 String timestamp() {
   Date date = currentTime != null ? currentTime : Calendar.getInstance().getTime();
   DateFormat dateFormat = new SimpleDateFormat(ISO_8601_TIME_FORMAT);
   dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
   return dateFormat.format(date);
 }
Example #15
0
 /**
  * Gets the value of this datetime as a milliseconds value for {@link java.sql.Time}.
  *
  * @param zone time zone in which to generate a time value for
  */
 public long getJdbcTime(TimeZone zone) {
   long timeValue = getTimeValue();
   return timeValue - zone.getOffset(timeValue);
 }
Example #16
0
 // implement BasicDatetime
 public void setZonedTime(long value, TimeZone zone) {
   this.internalTime = value + zone.getOffset(value);
 }
Example #17
0
 protected String createDateHeader(int expires) {
   final Calendar utc = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
   utc.add(Calendar.SECOND, expires);
   return toHttpDate(utc.getTime());
 }
Example #18
0
/**
 * This is the container for an instance of a site on a single server. This can be access via
 * __instance__
 *
 * @anonymous name : {local}, isField : {true}, desc : {Refers to the site being run.}, type:
 *     {library}
 * @anonymous name : {core}, isField : {true}, desc : {Refers to corejs.} example :
 *     {core.core.mail() calls corejs/core/mail.js}, type : {library}
 * @anonymous name : {external} isField : {true}, desc : {Refers to the external libraries.}, type :
 *     {library}
 * @anonymous name : {db}, isField : {true}, desc : {Refers to the database.}, type : {database}
 * @anonymous name : {setDB} desc : {changes <tt>db</tt> to refer to a different database.} param :
 *     {type : (string) name : (dbname) desc : (name of the database to which to connect)}
 * @anonymous name : {SYSOUT} desc : {Prints a string.} param : {type : (string) name : (str) desc :
 *     (the string to print)}
 * @anonymous name : {log} desc : {Global logger.} param : {type : (string) name : (str) desc : (the
 *     string to log)}
 * @expose
 * @docmodule system.system.__instance__
 */
public class AppContext extends ServletContextBase implements JSObject, Sizable {

  /** @unexpose */
  static final boolean DEBUG = AppServer.D;
  /**
   * If these files exist in the directory or parent directories of a file being run, run these
   * files first. Includes _init.js and /~~/core/init.js.
   */
  static final String INIT_FILES[] = new String[] {"/~~/core/init.js", "PREFIX_init"};

  /**
   * Initializes a new context for a given site directory.
   *
   * @param f the file to run
   */
  public AppContext(File f) {
    this(f.toString());
  }

  /**
   * Initializes a new context for a given site's path.
   *
   * @param root the path to the site from where ed is being run
   */
  public AppContext(String root) {
    this(root, guessNameAndEnv(root).name, guessNameAndEnv(root).env);
  }

  /**
   * Initializes a new context.
   *
   * @param root the path to the site
   * @param name the name of the site
   * @param environment the version of the site
   */
  public AppContext(String root, String name, String environment) {
    this(root, new File(root), name, environment);
  }

  /**
   * Initializes a new context.
   *
   * @param root the path to the site
   * @param rootFile the directory in which the site resides
   * @param name the name of the site
   * @param environment the version of the site
   */
  public AppContext(String root, File rootFile, String name, String environment) {
    this(root, rootFile, name, environment, null);
  }

  private AppContext(
      String root, File rootFile, String name, String environment, AppContext nonAdminParent) {
    super(name + ":" + environment);
    if (root == null) throw new NullPointerException("AppContext root can't be null");

    if (rootFile == null) throw new NullPointerException("AppContext rootFile can't be null");

    if (name == null) name = guessNameAndEnv(root).name;

    if (name == null) throw new NullPointerException("how could name be null");

    _root = root;
    _rootFile = rootFile;
    _git = new GitDir(_rootFile);
    _name = name;

    _environment = environment;
    _nonAdminParent = nonAdminParent;
    _admin = _nonAdminParent != null;
    _codePrefix = _admin ? "/~~/modules/admin/" : "";
    _moduleRegistry = ModuleRegistry.getNewGlobalChild();

    if (_git.isValid()) {
      _gitBranch = _git.getBranchOrTagName();
      _gitHash = _git.getCurrentHash();
    }

    _isGrid = name.equals("grid");

    _scope =
        new Scope(
            "AppContext:" + root + (_admin ? ":admin" : ""),
            _isGrid ? ed.cloud.Cloud.getInstance().getScope() : Scope.newGlobal(),
            null,
            Language.JS(),
            _rootFile);
    _scope.setGlobal(true);
    _initScope = _scope.child("_init");

    _usage = new UsageTracker(this);

    _baseScopeInit();

    _adminContext = _admin ? null : new AppContext(root, rootFile, name, environment, this);

    _rootContextReachable = new SeenPath();

    if (!_admin)
      _logger.info(
          "Started Context.  root:"
              + _root
              + " environment:"
              + environment
              + " git branch: "
              + _gitBranch);
  }

  /**
   * Returns the adapter type for the given file. Will first use the adapter selector function if it
   * was specified in init.js, otherwise will use the static type (either set in _init file, as a
   * server-wide override in 10gen.properties, or default of DIRECT_10GEN)
   *
   * @param file to produce type for
   * @return adapter type for the specified file
   */
  public AdapterType getAdapterType(File file) {

    // Q : I think this is the right thing to do
    if (inScopeSetup()) {
      return AdapterType.DIRECT_10GEN;
    }

    /*
     * cheap hack - prevent any _init.* file from getting run as anythign but DIRECT_10GEN
     */

    if (file != null && file.getName().indexOf("_init.") != -1) {
      return AdapterType.DIRECT_10GEN;
    }

    if (_adapterSelector == null) {
      return _staticAdapterType;
    }

    /*
     *  only let the app select type if file is part of application (i.e.
     *  don't do it for corejs, core modules, etc...
     */

    String fp = file.getAbsolutePath();
    String fullRoot = _rootFile.getAbsolutePath(); // there must be a nicer way to do this?

    if (!fp.startsWith(fullRoot)) {
      return AdapterType.DIRECT_10GEN;
    }

    Object o = _adapterSelector.call(_initScope, new JSString(fp.substring(fullRoot.length())));

    if (o == null) {
      return _staticAdapterType;
    }

    if (!(o instanceof JSString)) {
      log("Error : adapter selector not returning string.  Ignoring and using static adapter type");
      return _staticAdapterType;
    }

    AdapterType t = getAdapterTypeFromString(o.toString());

    return (t == null ? _staticAdapterType : t);
  }

  /**
   * Creates a copy of this context.
   *
   * @return an identical context
   */
  AppContext newCopy() {
    return new AppContext(_root, _rootFile, _name, _environment, _nonAdminParent);
  }

  /** Initializes the base scope for the application */
  private void _baseScopeInit() {
    // --- libraries

    if (_admin) _scope.put("local", new JSObjectBase(), true);
    else _setLocalObject(new JSFileLibrary(_rootFile, "local", this));

    _loadConfig();

    _core = CoreJS.get().getLibrary(getCoreJSVersion(), this, null, true);
    _logger.info("corejs : " + _core.getRoot());
    _scope.put("core", _core, true);

    _external =
        Module.getModule("external").getLibrary(getVersionForLibrary("external"), this, null, true);
    _scope.put("external", _external, true);

    _scope.put("__instance__", this, true);
    _scope.lock("__instance__");

    // --- db

    if (!_isGrid) {
      _scope.put("db", DBProvider.get(this), true);
      _scope.put(
          "setDB",
          new JSFunctionCalls1() {

            public Object call(Scope s, Object name, Object extra[]) {
              if (name.equals(_lastSetTo)) return true;

              DBBase db = (DBBase) AppContext.this._scope.get("db");
              if (!db.allowedToAccess(name.toString()))
                throw new JSException("you are not allowed to access db [" + name + "]");

              if (name.equals(db.getName())) return true;

              AppContext.this._scope.put(
                  "db", DBProvider.get(AppContext.this, name.toString()), false);
              _lastSetTo = name.toString();

              if (_adminContext != null) {
                // yes, i do want a new copy so Constructors don't get copied for both
                _adminContext._scope.put(
                    "db", DBProvider.get(AppContext.this, name.toString()), false);
              }

              return true;
            }

            String _lastSetTo = null;
          },
          true);
    }

    // --- output

    _scope.put(
        "SYSOUT",
        new JSFunctionCalls1() {
          public Object call(Scope s, Object str, Object foo[]) {
            System.out.println(AppContext.this._name + " \t " + str);
            return true;
          }
        },
        true);

    _scope.put("log", _logger, true);

    // --- random?

    _scope.put(
        "openFile",
        new JSFunctionCalls1() {
          public Object call(Scope s, Object name, Object extra[]) {
            return new JSLocalFile(_rootFile, name.toString());
          }
        },
        true);

    _scope.put("globalHead", _globalHead, true);

    Map<String, JSFileLibrary> rootFileMap = new HashMap<String, JSFileLibrary>();
    for (String rootKey : new String[] {"local", "core", "external"}) {
      Object temp = _scope.get(rootKey);
      if (temp instanceof JSFileLibrary) rootFileMap.put(rootKey, (JSFileLibrary) temp);
    }

    _scope.put(
        "fork",
        new JSFunctionCalls1() {
          public Object call(final Scope scope, final Object funcJS, final Object extra[]) {

            if (!(funcJS instanceof JSFunction))
              throw new JSException("fork has to take a function");

            return queueWork("forked", (JSFunction) funcJS, extra);
          }
        });
    _scope.lock("fork");

    ed.appserver.templates.djang10.JSHelper.install(_scope, rootFileMap, _logger);

    _scope.lock("user"); // protection against global user object
  }

  private void _loadConfig() {
    try {

      _configScope.set("__instance__", this);

      _loadConfigFromCloudObject(getSiteObject());
      _loadConfigFromCloudObject(getEnvironmentObject());

      File f;
      if (!_admin) {
        f = getFileSafe("_config.js");
        if (f == null || !f.exists()) f = getFileSafe("_config");
      } else
        f =
            new File(
                Module.getModule("core-modules/admin").getRootFile(getVersionForLibrary("admin")),
                "_config.js");

      _libraryLogger.info("config file [" + f + "] exists:" + f.exists());

      if (f == null || !f.exists()) return;

      Convert c = new Convert(f);
      JSFunction func = c.get();
      func.setUsePassedInScope(true);
      func.call(_configScope);

      _logger.debug("config things " + _configScope.keySet());
    } catch (Exception e) {
      throw new RuntimeException("couldn't load config", e);
    }
  }

  private void _loadConfigFromCloudObject(JSObject o) {
    if (o == null) return;

    _configScope.putAll((JSObject) o.get("config"));
  }

  /**
   * Get the version of corejs to run for this AppContext.
   *
   * @return the version of corejs as a string. null if should use default
   */
  public String getCoreJSVersion() {
    Object o = _scope.get("corejsversion");
    if (o != null) {
      _logger.error("you are using corejsversion which is deprecated.  please use version.corejs");
      return JS.toString(o);
    }

    return getVersionForLibrary("corejs");
  }

  /**
   * Get the version of a library to run.
   *
   * @param name the name of the library to look up
   * @return the version of the library to run as a string. null if should use default
   */
  public String getVersionForLibrary(String name) {
    String version = getVersionForLibrary(_configScope, name, this);
    _libraryVersions.set(name, version);
    return version;
  }

  public JSObject getLibraryVersionsLoaded() {
    return _libraryVersions;
  }

  /** @unexpose */
  public static String getVersionForLibrary(Scope s, String name) {
    AppRequest ar = AppRequest.getThreadLocal();
    return getVersionForLibrary(s, name, ar == null ? null : ar.getContext());
  }

  /** @unexpose */
  private static String getVersionForLibrary(Scope s, String name, AppContext ctxt) {
    final String version = _getVersionForLibrary(s, name, ctxt);
    _libraryLogger.log(
        ctxt != null && !ctxt._admin ? Level.DEBUG : Level.INFO,
        ctxt + "\t" + name + "\t" + version);
    return version;
  }

  private static String _getVersionForLibrary(Scope s, String name, AppContext ctxt) {
    final JSObject o1 =
        ctxt == null ? null : (JSObject) (s.get("version_" + ctxt.getEnvironmentName()));
    final JSObject o2 = (JSObject) s.get("version");

    _libraryLogger.debug(ctxt + "\t versionConfig:" + (o1 != null) + " config:" + (o2 != null));

    String version = _getString(name, o1, o2);
    if (version != null) return version;

    if (ctxt == null || ctxt._nonAdminParent == null) return null;

    return ctxt._nonAdminParent.getVersionForLibrary(name);
  }

  private static String _getString(String name, JSObject... places) {
    for (JSObject o : places) {
      if (o == null) continue;
      Object temp = o.get(name);
      if (temp == null) continue;
      return temp.toString();
    }
    return null;
  }

  /** @return [ <name> , <env> ] */
  static NameAndEnv guessNameAndEnv(String root) {
    root = ed.io.FileUtil.clean(root);
    root = root.replaceAll("\\.+/", "");
    String pcs[] = root.split("/+");

    if (pcs.length == 0) throw new RuntimeException("no root for : " + root);

    // handle anything with sites/foo
    for (int i = 0; i < pcs.length - 1; i++)
      if (pcs[i].equals("sites")) {
        return new NameAndEnv(pcs[i + 1], i + 2 < pcs.length ? pcs[i + 2] : null);
      }

    final int start = pcs.length - 1;
    for (int i = start; i > 0; i--) {
      String s = pcs[i];

      if (i == start
          && (s.equals("master")
              || s.equals("test")
              || s.equals("www")
              || s.equals("staging")
              ||
              // s.equals("stage") ||
              s.equals("dev"))) continue;

      return new NameAndEnv(s, i + 1 < pcs.length ? pcs[i + 1] : null);
    }

    return new NameAndEnv(pcs[0], pcs.length > 1 ? pcs[1] : null);
  }

  static class NameAndEnv {
    NameAndEnv(String name, String env) {
      this.name = name;
      this.env = env;
    }

    final String name;
    final String env;
  }

  /**
   * Returns the name of the site being run.
   *
   * @return the name of the site
   */
  public String getName() {
    return _name;
  }

  /**
   * Get the database being used.
   *
   * @return The database being used
   */
  public DBBase getDB() {
    return (DBBase) _scope.get("db");
  }

  /**
   * Given the _id of a JSFile, return the file.
   *
   * @param id _id of the file to find
   * @return The file, if found, otherwise null
   */
  JSFile getJSFile(String id) {

    if (id == null) return null;

    DBCollection f = getDB().getCollection("_files");
    return (JSFile) (f.find(new ObjectId(id)));
  }

  /**
   * Returns (and if necessary, reinitializes) the scope this context is using.
   *
   * @return the scope
   */
  public Scope getScope() {
    return _scope();
  }

  public Scope getInitScope() {
    return _initScope;
  }

  public Object getInitObject(String what) {
    return getFromInitScope(what);
  }

  public Object getFromInitScope(String what) {
    if (!_knownInitScopeThings.contains(what))
      System.err.println("*** Unknown thing requested from initScope [" + what + "]");
    return _initScope.get(what);
  }

  public void setInitObject(String name, Object value) {
    _initScope.set(name, value);
  }

  void setTLPreferredScope(AppRequest req, Scope s) {
    _scope.setTLPreferred(s);
  }

  private synchronized Scope _scope() {

    if (_inScopeSetup) return _scope;

    if (_getScopeTime() > _lastScopeInitTime) _scopeInited = false;

    if (_scopeInited) return _scope;

    _scopeInited = true;
    _lastScopeInitTime = System.currentTimeMillis();

    _setupScope();

    _setStaticAdapterType();

    _setAdapterSelectorFunction();

    return _scope;
  }

  protected void _setAdapterSelectorFunction() {

    Object o = this.getFromInitScope(INIT_ADAPTER_SELECTOR);

    if (o == null) {
      log("Adapter selector function not specified in _init file");
      return;
    }

    if (!(o instanceof JSFunction)) {
      log(
          "Adapter selector function specified in _init file  not a function.  Ignoring. ["
              + o.getClass()
              + "]");
      return;
    }

    _adapterSelector = (JSFunction) o;
    log("Adapter selector function specified in _init file");
  }

  public void setStaticAdapterTypeValue(AdapterType type) {
    log("Static adapter type directly set : " + type);
    _staticAdapterType = type;
  }

  public AdapterType getStaticAdapterTypeValue() {
    return _staticAdapterType;
  }

  /**
   * Figure out what kind of static adapter type was specified. By default it's a 10genDEFAULT app
   */
  protected void _setStaticAdapterType() {

    /*
     *  app configuration steps could have set this already.  If so, don't bother doing anything
     */
    if (_staticAdapterType != AdapterType.UNSET) {
      log("Static adapter type has already been directly set to " + _staticAdapterType);
      return;
    }

    /*
     * check to see if overridden in 10gen.properties
     */
    String override = Config.get().getProperty(INIT_ADAPTER_TYPE);

    if (override != null) {
      AdapterType t = getAdapterTypeFromString(override);

      if (t == null) {
        log(
            "Static adapter type specified as override ["
                + override
                + "] unknown - will use _init file specified or default");
      } else {
        log("Static adapter type overridden by 10gen.properties or env. Value : " + override);
        _staticAdapterType = t;
        return;
      }
    }

    /*
     *  if not, use the one from _init file if specified
     */

    _staticAdapterType = AdapterType.DIRECT_10GEN;
    Object o = getFromInitScope(INIT_ADAPTER_TYPE);

    if (o == null) {
      log("Static adapter type not specified in _init file - using default value of DIRECT_10GEN");
      return;
    }

    if (!(o instanceof JSString)) {
      log("Static adapter type from _init file not a string - using default value of DIRECT_10GEN");
      return;
    }

    _staticAdapterType = getAdapterTypeFromString(o.toString());

    if (_staticAdapterType == null) {
      log(
          "Static adapter type from _init file ["
              + o.toString()
              + "] unknown - using default value of DIRECT_10GEN");
      _staticAdapterType = AdapterType.DIRECT_10GEN;
      return;
    }

    log("Static adapter type specified in _init file = " + _staticAdapterType);

    return;
  }

  public AdapterType getAdapterTypeFromString(String s) {

    if (AdapterType.DIRECT_10GEN.toString().equals(s.toUpperCase())) {
      return AdapterType.DIRECT_10GEN;
    }

    if (AdapterType.CGI.toString().equals(s.toUpperCase())) {
      return AdapterType.CGI;
    }

    if (AdapterType.WSGI.toString().equals(s.toUpperCase())) {
      return AdapterType.WSGI;
    }

    return null;
  }

  /** @unexpose */
  public File getFileSafe(final String uri) {
    try {
      return getFile(uri);
    } catch (FileNotFoundException fnf) {
      return null;
    }
  }

  /** @unexpose */
  public File getFile(final String uri) throws FileNotFoundException {
    File f = _files.get(uri);

    if (f != null) return f;

    if (uri.startsWith("/~~/") || uri.startsWith("~~/"))
      f = _core.getFileFromPath(uri.substring(3));
    else if (uri.startsWith("/admin/")) f = _core.getFileFromPath("/modules" + uri);
    else if (uri.startsWith("/@@/") || uri.startsWith("@@/"))
      f = _external.getFileFromPath(uri.substring(3));
    else if (_localObject != null && uri.startsWith("/modules/"))
      f = _localObject.getFileFromPath(uri);
    else f = new File(_rootFile, uri);

    if (f == null) throw new FileNotFoundException(uri);

    _files.put(uri, f);
    return f;
  }

  public String getRealPath(String path) {
    try {
      return getFile(path).getAbsolutePath();
    } catch (FileNotFoundException fnf) {
      throw new RuntimeException("file not found [" + path + "]");
    }
  }

  public URL getResource(String path) {
    try {
      File f = getFile(path);
      if (!f.exists()) return null;
      return f.toURL();
    } catch (FileNotFoundException fnf) {
      // the spec says to return null if we can't find it
      // even though this is weird...
      return null;
    } catch (IOException ioe) {
      throw new RuntimeException("error opening [" + path + "]", ioe);
    }
  }

  public InputStream getResourceAsStream(String path) {
    URL url = getResource(path);
    if (url == null) return null;
    try {
      return url.openStream();
    } catch (IOException ioe) {
      throw new RuntimeException("can't getResourceAsStream [" + path + "]", ioe);
    }
  }

  /**
   * This causes the AppContext to be started over. All context level variable will be lost. If code
   * is being managed, will cause it to check that its up to date.
   */
  public void reset() {
    _reset = true;
  }

  /** Checks if this context has been reset. */
  public boolean isReset() {
    return _reset;
  }

  /**
   * Returns the path to the directory the appserver is running. (For example, site/version.)
   *
   * @return the path
   */
  public String getRoot() {
    return _root;
  }

  public File getRootFile() {
    return _rootFile;
  }

  /**
   * Creates an new request for the app server from an HTTP request.
   *
   * @param request HTTP request to create
   * @return the request
   */
  public AppRequest createRequest(HttpRequest request) {
    return createRequest(request, request.getHost(), request.getURI());
  }

  /**
   * Creates an new request for the app server from an HTTP request.
   *
   * @param request HTTP request to create
   * @param uri the URI requested
   * @return the request
   */
  public AppRequest createRequest(HttpRequest request, String host, String uri) {
    _numRequests++;

    if (AppRequest.isAdmin(request)) return new AppRequest(_adminContext, request, host, uri);

    return new AppRequest(this, request, host, uri);
  }

  /**
   * Tries to find the given file, assuming that it's missing the ".jxp" extension
   *
   * @param f File to check
   * @return same file if not found to be missing the .jxp, or a new File w/ the .jxp appended
   */
  File tryNoJXP(File f) {
    if (f.exists()) return f;

    if (f.getName().indexOf(".") >= 0) return f;

    File temp = new File(f.toString() + ".jxp");
    return temp.exists() ? temp : f;
  }

  File tryOtherExtensions(File f) {
    if (f.exists()) return f;

    if (f.getName().indexOf(".") >= 0) return f;

    for (int i = 0; i < JSFileLibrary._srcExtensions.length; i++) {
      File temp = new File(f.toString() + JSFileLibrary._srcExtensions[i]);
      if (temp.exists()) return temp;
    }

    return f;
  }

  /**
   * Maps a servlet-like URI to a jxp file.
   *
   * @param f File to check
   * @return new File with <root>.jxp if exists, orig file if not
   * @example /wiki/geir -> maps to wiki.jxp if exists
   */
  File tryServlet(File f) {
    if (f.exists()) return f;

    String uri = f.toString();

    if (uri.startsWith(_rootFile.toString())) uri = uri.substring(_rootFile.toString().length());

    if (_core != null && uri.startsWith(_core._base.toString()))
      uri = "/~~" + uri.substring(_core._base.toString().length());

    while (uri.startsWith("/")) uri = uri.substring(1);

    int start = 0;
    while (true) {

      int idx = uri.indexOf("/", start);
      if (idx < 0) break;
      String foo = uri.substring(0, idx);

      File temp = getFileSafe(foo + ".jxp");

      if (temp != null && temp.exists()) f = temp;

      start = idx + 1;
    }

    return f;
  }

  /**
   * Returns the index.jxp for the File argument if it's an existing directory, and the index.jxp
   * file exists
   *
   * @param f directory to check
   * @return new File for index.jxp in that directory, or same file object if not
   */
  File tryIndex(File f) {

    if (!(f.isDirectory() && f.exists())) return f;

    for (int i = 0; i < JSFileLibrary._srcExtensions.length; i++) {
      File temp = new File(f, "index" + JSFileLibrary._srcExtensions[i]);
      if (temp.exists()) return temp;
    }

    return f;
  }

  JxpSource getSource(File f) throws IOException {

    if (DEBUG) System.err.println("getSource\n\t " + f);

    File temp = _findFile(f);

    if (DEBUG) System.err.println("\t " + temp);

    if (!temp.exists()) return handleFileNotFound(f);

    //  if it's a directory (and we know we can't find the index file)
    //  TODO : at some point, do something where we return an index for the dir?
    if (temp.isDirectory()) return null;

    // if we are at init time, save it as an initializaiton file
    loadedFile(temp);

    // Ensure that this is w/in the right tree for the context
    if (_localObject != null && _localObject.isIn(temp)) return _localObject.getSource(temp);

    // if not, is it core?
    if (_core.isIn(temp)) return _core.getSource(temp);

    throw new RuntimeException("what?  can't find:" + f);
  }

  /**
   * Finds the appropriate file for the given path.
   *
   * <p>We have a hierarchy of attempts as we try to find a file :
   *
   * <p>1) first, see if it exists as is, or if it's really a .jxp w/o the extension 2) next, see if
   * it can be deconstructed as a servlet such that /foo/bar maps to /foo.jxp 3) See if we can find
   * the index file for it if a directory
   */
  File _findFile(File f) {

    File temp;

    if ((temp = tryNoJXP(f)) != f) {
      return temp;
    }

    if ((temp = tryOtherExtensions(f)) != f) {
      return temp;
    }

    if ((temp = tryServlet(f)) != f) {
      return temp;
    }

    if ((temp = tryIndex(f)) != f) {
      return temp;
    }

    return f;
  }

  public void loadedFile(File f) {
    if (_inScopeSetup) _initFlies.add(f);
  }

  public void addInitDependency(File f) {
    _initFlies.add(f);
  }

  JxpServlet getServlet(File f) throws IOException {
    // if this site doesn't exist, don't return anything
    if (!_rootFile.exists()) return null;

    JxpSource source = getSource(f);
    if (source == null) return null;
    return source.getServlet(this);
  }

  private void _setupScope() {
    if (_inScopeSetup) return;

    final Scope saveTLPref = _scope.getTLPreferred();
    _scope.setTLPreferred(null);

    final Scope saveTL = Scope.getThreadLocal();
    _scope.makeThreadLocal();

    _inScopeSetup = true;

    try {
      Object fo = getConfigObject("framework");

      if (fo != null) {

        Framework f = null;

        if (fo instanceof JSString) {
          f = Framework.byName(fo.toString(), null); // we allow people to just specify name
          _logger.info("Setting framework by name [" + fo.toString() + "]");
        } else if (fo instanceof JSObjectBase) {

          JSObjectBase obj = (JSObjectBase) fo;

          if (obj.containsKey("name")) {

            String s = obj.getAsString("version");

            f = Framework.byName(obj.getAsString("name"), s);
            _logger.info("Setting framework by name [" + obj.getAsString("name") + "]");
          } else if (obj.containsKey("custom")) {

            Object o = obj.get("custom");

            if (o instanceof JSObjectBase) {
              f = Framework.byCustom((JSObjectBase) o);
              _logger.info("Setting framework by custom [" + o + "]");
            } else {
              throw new RuntimeException("Error - custom framework wasn't an object [" + o + "]");
            }
          } else if (obj.containsKey("classname")) {
            f = Framework.byClass(obj.getAsString("classname"));
            _logger.info("Setting framework by class [" + obj.getAsString("classname") + "]");
          }
        }

        if (f == null) {
          throw new RuntimeException("Error : can't find framework [" + fo + "]");
        }

        f.install(this);
      }

      _runInitFiles(INIT_FILES);

      if (_adminContext != null) {
        _adminContext._scope.set("siteScope", _scope);
        _adminContext._setLocalObject(_localObject);
      }

      _lastScopeInitTime = _getScopeTime();
    } catch (RuntimeException re) {
      _scopeInited = false;
      throw re;
    } catch (Exception e) {
      _scopeInited = false;
      throw new RuntimeException(e);
    } finally {
      _inScopeSetup = false;
      _scope.setTLPreferred(saveTLPref);

      if (saveTL != null) saveTL.makeThreadLocal();

      this.approxSize(_rootContextReachable);
    }
  }

  public boolean inScopeSetup() {
    return _inScopeSetup;
  }

  private void _runInitFiles(String[] files) throws IOException {

    if (files == null) return;

    for (JSFunction func : _initRefreshHooks) {
      func.call(_initScope, null);
    }

    for (int i = 0; i < files.length; i++) runInitFile(files[i].replaceAll("PREFIX", _codePrefix));
  }

  public void addInitRefreshHook(JSFunction func) {
    _initRefreshHooks.add(func);
  }

  /** @param path (ex: /~~/foo.js ) */
  public void runInitFile(String path) throws IOException {
    _runInitFile(tryOtherExtensions(getFile(path)));
  }

  private void _runInitFile(File f) throws IOException {
    if (f == null) return;

    if (!f.exists()) return;

    _initFlies.add(f);
    JxpSource s = getSource(f);
    JSFunction func = s.getFunction();
    func.setUsePassedInScope(true);
    func.call(_initScope);
  }

  long _getScopeTime() {
    long last = 0;
    for (File f : _initFlies) if (f.exists()) last = Math.max(last, f.lastModified());
    return last;
  }

  /**
   * Convert this AppContext to a string by returning the name of the directory it's running in.
   *
   * @return the filename of its root directory
   */
  public String toString() {
    return _rootFile.toString();
  }

  public String debugInfo() {
    return _rootFile + " admin:" + _admin;
  }

  public void fix(Throwable t) {
    StackTraceHolder.getInstance().fix(t);
  }

  /**
   * Get a "global" head array. This array contains HTML that will be inserted into the head of
   * every request served by this app context. It's analagous to the <tt>head</tt> array, but
   * persistent.
   *
   * @return a mutable array
   */
  public JSArray getGlobalHead() {
    return _globalHead;
  }

  /**
   * Gets the date of creation for this app context.
   *
   * @return the creation date as a JS Date.
   */
  public JSDate getWhenCreated() {
    return _created;
  }

  /**
   * Gets the number of requests served by this app context.
   *
   * @return the number of requests served
   */
  public int getNumRequests() {
    return _numRequests;
  }

  /**
   * Get the name of the git branch we think we're running.
   *
   * @return the name of the git branch, as a string
   */
  public String getGitBranch() {
    return _gitBranch;
  }

  public String getGitHash() {
    return _gitHash;
  }

  /**
   * Update the git branch that we're running and return it.
   *
   * @return the name of the git branch, or null if there isn't any
   */
  public String getCurrentGitBranch() {
    return getCurrentGitBranch(false);
  }

  public String getCurrentGitBranch(boolean forceUpdate) {
    if (_gitBranch == null) return null;

    if (_gitFile == null) _gitFile = new File(_rootFile, ".git/HEAD");

    if (!_gitFile.exists()) throw new RuntimeException("this should be impossible");

    if (forceUpdate || _lastScopeInitTime < _gitFile.lastModified()) {
      _gitBranch = _git.getBranchOrTagName();
      _gitHash = _git.getCurrentHash();
    }

    return _gitBranch;
  }

  /**
   * Get the environment in which this site is running
   *
   * @return the environment name as a string
   */
  public String getEnvironmentName() {
    return _environment;
  }

  /**
   * updates the context to the correct branch based on environment and to the latest version of the
   * code if name or environemnt is missing, does nothing
   */
  public String updateCode() {

    if (!_git.isValid()) throw new RuntimeException(_rootFile + " is not a git repository");

    _logger.info("going to update code");
    _git.fullUpdate();

    if (_name == null || _environment == null) return getCurrentGitBranch();

    JSObject env = getEnvironmentObject();
    if (env == null) return null;

    String branch = env.get("branch").toString();
    _logger.info("updating to [" + branch + "]");

    _git.checkout(branch);
    Python.deleteCachedJythonFiles(_rootFile);

    return getCurrentGitBranch(true);
  }

  private JSObject getSiteObject() {
    return AppContextHolder.getSiteFromCloud(_name);
  }

  private JSObject getEnvironmentObject() {
    return AppContextHolder.getEnvironmentFromCloud(_name, _environment);
  }

  private void _setLocalObject(JSFileLibrary local) {
    _localObject = local;
    _scope.put("local", _localObject, true);
    _scope.put("jxp", _localObject, true);
    _scope.warn("jxp");
  }

  JxpSource handleFileNotFound(File f) {
    String name = f.getName();
    if (name.endsWith(".class")) {
      name = name.substring(0, name.length() - 6);
      return getJxpServlet(name);
    }

    return null;
  }

  public JxpSource getJxpServlet(String name) {
    JxpSource source = _httpServlets.get(name);
    if (source != null) return source;

    try {
      Class c = Class.forName(name);
      Object n = c.newInstance();
      if (!(n instanceof HttpServlet))
        throw new RuntimeException("class [" + name + "] is not a HttpServlet");

      HttpServlet servlet = (HttpServlet) n;
      servlet.init(createServletConfig(name));
      source = new ServletSource(servlet);
      _httpServlets.put(name, source);
      return source;
    } catch (Exception e) {
      throw new RuntimeException("can't load [" + name + "]", e);
    }
  }

  ServletConfig createServletConfig(final String name) {
    final Object rawServletConfigs = _scope.get("servletConfigs");
    final Object servletConfigObject =
        rawServletConfigs instanceof JSObject ? ((JSObject) rawServletConfigs).get(name) : null;
    final JSObject servletConfig;
    if (servletConfigObject instanceof JSObject) servletConfig = (JSObject) servletConfigObject;
    else servletConfig = null;

    return new ServletConfig() {
      public String getInitParameter(String name) {
        if (servletConfig == null) return null;
        Object foo = servletConfig.get(name);
        if (foo == null) return null;
        return foo.toString();
      }

      public Enumeration getInitParameterNames() {
        Collection keys;
        if (servletConfig == null) keys = new LinkedList();
        else keys = servletConfig.keySet();
        return new CollectionEnumeration(keys);
      }

      public ServletContext getServletContext() {
        return AppContext.this;
      }

      public String getServletName() {
        return name;
      }
    };
  }

  public static AppContext findThreadLocal() {

    AppContext context = _tl.get();
    if (context != null) return context;

    AppRequest req = AppRequest.getThreadLocal();
    if (req != null) return req._context;

    Scope s = Scope.getThreadLocal();
    if (s != null) {
      Object foo = s.get("__instance__");
      if (foo instanceof AppContext) return (AppContext) foo;
    }

    return null;
  }

  public void makeThreadLocal() {
    _tl.set(this);
  }

  public static void clearThreadLocal() {
    _tl.set(null);
  }

  public String getInitParameter(String name) {
    Object foo = _configScope.get(name);
    if (foo == null) return null;
    return foo.toString();
  }

  public Enumeration getInitParameterNames() {
    return new CollectionEnumeration(_configScope.keySet());
  }

  public Object getConfigObject(String name) {
    return _configScope.get(name);
  }

  public void setConfigObject(String name, Object value) {
    _configScope.set(name, value);
  }

  public String getContextPath() {
    return "";
  }

  public RequestDispatcher getNamedDispatcher(String name) {
    throw new RuntimeException("getNamedDispatcher not implemented");
  }

  public RequestDispatcher getRequestDispatcher(String name) {
    throw new RuntimeException("getRequestDispatcher not implemented");
  }

  public Set getResourcePaths(String path) {
    throw new RuntimeException("getResourcePaths not implemented");
  }

  public AppContext getSiteInstance() {
    if (_nonAdminParent == null) return this;
    return _nonAdminParent;
  }

  public long approxSize() {
    return approxSize(new SeenPath());
  }

  public long approxSize(SeenPath seen) {
    long size = 0;

    seen.visited(this);

    if (seen.shouldVisit(_scope, this)) size += _scope.approxSize(seen, false, true);
    if (seen.shouldVisit(_initScope, this)) size += _initScope.approxSize(seen, true, false);

    size += JSObjectSize.size(_localObject, seen, this);
    size += JSObjectSize.size(_core, seen, this);
    size += JSObjectSize.size(_external, seen, this);

    if (seen.shouldVisit(_adminContext, this)) size += _adminContext.approxSize(seen);

    size += JSObjectSize.size(_logger, seen, this);

    return size;
  }

  public int hashCode() {
    return System.identityHashCode(this);
  }

  public boolean equals(Object o) {
    return o == this;
  }

  public AppWork queueWork(String identifier, JSFunction work, Object... params) {
    return queueWork(new AppWork.FunctionAppWork(this, identifier, work, params));
  }

  public AppWork queueWork(AppWork work) {
    if (_workQueue == null) {
      _workQueue = new ArrayBlockingQueue<AppWork>(100);
      AppWork.addQueue(_workQueue);
    }

    if (_workQueue.offer(work)) return work;

    throw new RuntimeException("work queue full!");
  }

  public Logger getLogger(String sub) {
    return _logger.getChild(sub);
  }

  public ModuleRegistry getModuleRegistry() {
    return _moduleRegistry;
  }

  // ----  START JSObject INTERFACE

  public Object get(Object n) {
    return _scope.get(n);
  }

  public JSFunction getFunction(String name) {
    return _scope.getFunction(name);
  }

  public final Set<String> keySet() {
    return _scope.keySet();
  }

  public Set<String> keySet(boolean includePrototype) {
    return _scope.keySet(includePrototype);
  }

  public boolean containsKey(String s) {
    return _scope.containsKey(s);
  }

  public boolean containsKey(String s, boolean includePrototype) {
    return _scope.containsKey(s, includePrototype);
  }

  public Object set(Object n, Object v) {
    return _scope.putExplicit(n.toString(), v);
  }

  public Object setInt(int n, Object v) {
    throw new RuntimeException("not allowed");
  }

  public Object getInt(int n) {
    return _scope.getInt(n);
  }

  public Object removeField(Object n) {
    return _scope.removeField(n);
  }

  public JSFunction getConstructor() {
    return null;
  }

  public JSObject getSuper() {
    return null;
  }

  // ----  END BROKEN JSOBJET INTERFACE

  public TimeZone getTimeZone() {
    return _tz;
  }

  public void setTimeZone(String tz) {
    if (tz.length() == 3) tz = tz.toUpperCase();
    _tz = TimeZone.getTimeZone(tz);
    if (!_tz.getID().equals(tz)) throw new RuntimeException("can't find time zone[" + tz + "]");
  }

  final String _name;
  final String _root;
  final File _rootFile;
  final GitDir _git;

  private String _gitBranch;
  private String _gitHash;
  final String _environment;
  final boolean _admin;

  final AppContext _adminContext;
  final String _codePrefix;

  final AppContext _nonAdminParent;

  private JSFileLibrary _localObject;
  private JSFileLibrary _core;
  private JSFileLibrary _external;

  final Scope _scope;
  final SeenPath _rootContextReachable;
  final Scope _initScope;
  final Scope _configScope = new Scope();
  final UsageTracker _usage;
  final ModuleRegistry _moduleRegistry;

  final JSArray _globalHead = new JSArray();

  private final Map<String, File> _files = Collections.synchronizedMap(new HashMap<String, File>());
  private final Set<File> _initFlies = new HashSet<File>();
  private final Map<String, JxpSource> _httpServlets =
      Collections.synchronizedMap(new HashMap<String, JxpSource>());
  private final JSObject _libraryVersions = new JSObjectBase();

  private Queue<AppWork> _workQueue;
  private TimeZone _tz = TimeZone.getDefault();

  boolean _scopeInited = false;
  boolean _inScopeSetup = false;
  long _lastScopeInitTime = 0;

  final boolean _isGrid;

  boolean _reset = false;
  int _numRequests = 0;
  final JSDate _created = new JSDate();

  private File _gitFile = null;
  private long _lastGitCheckTime = 0;

  private Collection<JSFunction> _initRefreshHooks = new ArrayList<JSFunction>();

  /*
   *  adapter type - can have either a static ("all files in this app are X")
   *  or dynamic - the provided selector function dynamically chooses, falling
   *  back to the static if it returns null
   */
  public static final String INIT_ADAPTER_TYPE = "adapterType";
  public static final String INIT_ADAPTER_SELECTOR = "adapterSelector";

  private AdapterType _staticAdapterType = AdapterType.UNSET;
  private JSFunction _adapterSelector = null;

  private static Logger _libraryLogger = Logger.getLogger("library.load");

  static {
    _libraryLogger.setLevel(Level.INFO);
  }

  private static final Set<String> _knownInitScopeThings = new HashSet<String>();
  private static final ThreadLocal<AppContext> _tl = new ThreadLocal<AppContext>();

  static {
    _knownInitScopeThings.add("mapUrlToJxpFileCore");
    _knownInitScopeThings.add("mapUrlToJxpFile");
    _knownInitScopeThings.add("allowed");
    _knownInitScopeThings.add("staticCacheTime");
    _knownInitScopeThings.add("handle404");
    _knownInitScopeThings.add(INIT_ADAPTER_TYPE);
    _knownInitScopeThings.add(INIT_ADAPTER_SELECTOR);
  }

  public static final class AppContextReachable extends ReflectionVisitor.Reachable {
    public boolean follow(Object o, Class c, java.lang.reflect.Field f) {

      if (_reachableStoppers.contains(c)) return false;

      if (f != null && _reachableStoppers.contains(f.getType())) return false;

      return super.follow(o, c, f);
    }
  }

  private static final Set<Class> _reachableStoppers = new HashSet<Class>();

  static {
    _reachableStoppers.add(HttpServer.class);
    _reachableStoppers.add(AppServer.class);
    _reachableStoppers.add(DBTCP.class);
    _reachableStoppers.add(Mongo.class);
    _reachableStoppers.add(WeakBag.class);
    _reachableStoppers.add(WeakValueMap.class);
  }
}
Example #19
0
 public void setTimeZone(String tz) {
   if (tz.length() == 3) tz = tz.toUpperCase();
   _tz = TimeZone.getTimeZone(tz);
   if (!_tz.getID().equals(tz)) throw new RuntimeException("can't find time zone[" + tz + "]");
 }
 static {
   debug_utc_format.setTimeZone(TimeZone.getTimeZone("UTC"));
   utc_date_format.setTimeZone(TimeZone.getTimeZone("UTC"));
 }
  public static void test() {
    TimeZone.setDefault(TimeZone.getTimeZone("GMT-0800"));

    // Any characters not explicitly defined as conversions, date/time
    // conversion suffixes, or flags are illegal and are reserved for
    // future extensions.  Use of such a character in a format string will
    // cause an UnknownFormatConversionException or
    // UnknownFormatFlagsException to be thrown.
    tryCatch("%q", UnknownFormatConversionException.class);
    tryCatch("%t&", UnknownFormatConversionException.class);
    tryCatch("%&d", UnknownFormatConversionException.class);
    tryCatch("%^b", UnknownFormatConversionException.class);

    // ---------------------------------------------------------------------
    // Formatter.java class javadoc examples
    // ---------------------------------------------------------------------
    test(Locale.FRANCE, "e = %+10.4f", "e =    +2,7183", Math.E);
    test("%4$2s %3$2s %2$2s %1$2s", " d  c  b  a", "a", "b", "c", "d");
    test(
        "Amount gained or lost since last statement: $ %,(.2f",
        "Amount gained or lost since last statement: $ (6,217.58)", (new BigDecimal("-6217.58")));
    Calendar c = new GregorianCalendar(1969, JULY, 20, 16, 17, 0);
    testSysOut("Local time: %tT", "Local time: 16:17:00", c);

    test(
        "Unable to open file '%1$s': %2$s",
        "Unable to open file 'food': No such file or directory",
        "food",
        "No such file or directory");
    Calendar duke = new GregorianCalendar(1995, MAY, 23, 19, 48, 34);
    duke.set(Calendar.MILLISECOND, 584);
    test("Duke's Birthday: %1$tB %1$te, %1$tY", "Duke's Birthday: May 23, 1995", duke);
    test("Duke's Birthday: %1$tB %1$te, %1$tY", "Duke's Birthday: May 23, 1995", duke.getTime());
    test(
        "Duke's Birthday: %1$tB %1$te, %1$tY",
        "Duke's Birthday: May 23, 1995", duke.getTimeInMillis());

    test("%4$s %3$s %2$s %1$s %4$s %3$s %2$s %1$s", "d c b a d c b a", "a", "b", "c", "d");
    test("%s %s %<s %<s", "a b b b", "a", "b", "c", "d");
    test("%s %s %s %s", "a b c d", "a", "b", "c", "d");
    test("%2$s %s %<s %s", "b a a b", "a", "b", "c", "d");

    // ---------------------------------------------------------------------
    // %b
    //
    // General conversion applicable to any argument.
    // ---------------------------------------------------------------------
    test("%b", "true", true);
    test("%b", "false", false);
    test("%B", "TRUE", true);
    test("%B", "FALSE", false);
    test("%b", "true", Boolean.TRUE);
    test("%b", "false", Boolean.FALSE);
    test("%B", "TRUE", Boolean.TRUE);
    test("%B", "FALSE", Boolean.FALSE);
    test("%14b", "          true", true);
    test("%-14b", "true          ", true);
    test("%5.1b", "    f", false);
    test("%-5.1b", "f    ", false);

    test("%b", "true", "foo");
    test("%b", "false", (Object) null);

    // Boolean.java hardcodes the Strings for "true" and "false", so no
    // localization is possible.
    test(Locale.FRANCE, "%b", "true", true);
    test(Locale.FRANCE, "%b", "false", false);

    // If you pass in a single array to a varargs method, the compiler
    // uses it as the array of arguments rather than treating it as a
    // single array-type argument.
    test("%b", "false", (Object[]) new String[2]);
    test("%b", "true", new String[2], new String[2]);

    int[] ia = {1, 2, 3};
    test("%b", "true", ia);

    // ---------------------------------------------------------------------
    // %b - errors
    // ---------------------------------------------------------------------
    tryCatch("%#b", FormatFlagsConversionMismatchException.class);
    tryCatch("%-b", MissingFormatWidthException.class);
    // correct or side-effect of implementation?
    tryCatch("%.b", UnknownFormatConversionException.class);
    tryCatch("%,b", FormatFlagsConversionMismatchException.class);

    // ---------------------------------------------------------------------
    // %c
    //
    // General conversion applicable to any argument.
    // ---------------------------------------------------------------------
    test("%c", "i", 'i');
    test("%C", "I", 'i');
    test("%4c", "   i", 'i');
    test("%-4c", "i   ", 'i');
    test("%4C", "   I", 'i');
    test("%-4C", "I   ", 'i');
    test("%c", "i", new Character('i'));
    test("%c", "H", (byte) 72);
    test("%c", "i", (short) 105);
    test("%c", "!", (int) 33);
    test("%c", "\u007F", Byte.MAX_VALUE);
    test("%c", new String(Character.toChars(Short.MAX_VALUE)), Short.MAX_VALUE);
    test("%c", "null", (Object) null);

    // ---------------------------------------------------------------------
    // %c - errors
    // ---------------------------------------------------------------------
    tryCatch("%c", IllegalFormatConversionException.class, Boolean.TRUE);
    tryCatch("%c", IllegalFormatConversionException.class, (float) 0.1);
    tryCatch("%c", IllegalFormatConversionException.class, new Object());
    tryCatch("%c", IllegalFormatCodePointException.class, Byte.MIN_VALUE);
    tryCatch("%c", IllegalFormatCodePointException.class, Short.MIN_VALUE);
    tryCatch("%c", IllegalFormatCodePointException.class, Integer.MIN_VALUE);
    tryCatch("%c", IllegalFormatCodePointException.class, Integer.MAX_VALUE);

    tryCatch("%#c", FormatFlagsConversionMismatchException.class);
    tryCatch("%,c", FormatFlagsConversionMismatchException.class);
    tryCatch("%(c", FormatFlagsConversionMismatchException.class);
    tryCatch("%$c", UnknownFormatConversionException.class);
    tryCatch("%.2c", IllegalFormatPrecisionException.class);

    // ---------------------------------------------------------------------
    // %s
    //
    // General conversion applicable to any argument.
    // ---------------------------------------------------------------------
    test("%s", "Hello, Duke", "Hello, Duke");
    test("%S", "HELLO, DUKE", "Hello, Duke");
    test("%20S", "         HELLO, DUKE", "Hello, Duke");
    test("%20s", "         Hello, Duke", "Hello, Duke");
    test("%-20s", "Hello, Duke         ", "Hello, Duke");
    test("%-20.5s", "Hello               ", "Hello, Duke");
    test("%s", "null", (Object) null);

    StringBuffer sb = new StringBuffer("foo bar");
    test("%s", sb.toString(), sb);
    test("%S", sb.toString().toUpperCase(), sb);

    // ---------------------------------------------------------------------
    // %s - errors
    // ---------------------------------------------------------------------
    tryCatch("%-s", MissingFormatWidthException.class);
    tryCatch("%--s", DuplicateFormatFlagsException.class);
    tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
    tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
    tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
    tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);

    // ---------------------------------------------------------------------
    // %h
    //
    // General conversion applicable to any argument.
    // ---------------------------------------------------------------------
    test("%h", Integer.toHexString("Hello, Duke".hashCode()), "Hello, Duke");
    test("%10h", "  ddf63471", "Hello, Duke");
    test("%-10h", "ddf63471  ", "Hello, Duke");
    test("%-10H", "DDF63471  ", "Hello, Duke");
    test("%10h", "  402e0000", 15.0);
    test("%10H", "  402E0000", 15.0);

    // ---------------------------------------------------------------------
    // %h - errors
    // ---------------------------------------------------------------------
    tryCatch("%#h", FormatFlagsConversionMismatchException.class);

    // ---------------------------------------------------------------------
    // flag/conversion errors
    // ---------------------------------------------------------------------
    tryCatch("%F", UnknownFormatConversionException.class);

    tryCatch("%#g", FormatFlagsConversionMismatchException.class);

    // ---------------------------------------------------------------------
    // BigInteger - errors
    // ---------------------------------------------------------------------
    tryCatch("%f", IllegalFormatConversionException.class, new BigInteger("1"));

    // ---------------------------------------------------------------------
    // %d - BigInteger
    // ---------------------------------------------------------------------
    test("%d", "null", (Object) null);
    test("%d", "1234567", new BigInteger("1234567", 10));
    test("%,d", "1,234,567", new BigInteger("1234567", 10));
    test(Locale.FRANCE, "%,d", "1\u00a0234\u00a0567", new BigInteger("1234567", 10));
    test("%,d", "-1,234,567", new BigInteger("-1234567", 10));
    test("%(d", "1234567", new BigInteger("1234567", 10));
    test("%(d", "(1234567)", new BigInteger("-1234567", 10));
    test("% d", " 1234567", new BigInteger("1234567", 10));
    test("% d", "-1234567", new BigInteger("-1234567", 10));
    test("%+d", "+1234567", new BigInteger("1234567", 10));
    test("%+d", "-1234567", new BigInteger("-1234567", 10));
    test("%010d", "0001234567", new BigInteger("1234567", 10));
    test("%010d", "-001234567", new BigInteger("-1234567", 10));
    test("%(10d", " (1234567)", new BigInteger("-1234567", 10));
    test("%+d", "+1234567", new BigInteger("1234567", 10));
    test("%+d", "-1234567", new BigInteger("-1234567", 10));
    test("%-10d", "1234567   ", new BigInteger("1234567", 10));
    test("%-10d", "-1234567  ", new BigInteger("-1234567", 10));

    // ---------------------------------------------------------------------
    // %o - BigInteger
    // ---------------------------------------------------------------------
    test("%o", "null", (Object) null);
    test("%o", "1234567", new BigInteger("1234567", 8));
    test("%(o", "1234567", new BigInteger("1234567", 8));
    test("%(o", "(1234567)", new BigInteger("-1234567", 8));
    test("% o", " 1234567", new BigInteger("1234567", 8));
    test("% o", "-1234567", new BigInteger("-1234567", 8));
    test("%+o", "+1234567", new BigInteger("1234567", 8));
    test("%+o", "-1234567", new BigInteger("-1234567", 8));
    test("%010o", "0001234567", new BigInteger("1234567", 8));
    test("%010o", "-001234567", new BigInteger("-1234567", 8));
    test("%(10o", " (1234567)", new BigInteger("-1234567", 8));
    test("%+o", "+1234567", new BigInteger("1234567", 8));
    test("%+o", "-1234567", new BigInteger("-1234567", 8));
    test("%-10o", "1234567   ", new BigInteger("1234567", 8));
    test("%-10o", "-1234567  ", new BigInteger("-1234567", 8));
    test("%#10o", "  01234567", new BigInteger("1234567", 8));
    test("%#10o", " -01234567", new BigInteger("-1234567", 8));

    // ---------------------------------------------------------------------
    // %x - BigInteger
    // ---------------------------------------------------------------------
    test("%x", "null", (Object) null);
    test("%x", "1234567", new BigInteger("1234567", 16));
    test("%(x", "1234567", new BigInteger("1234567", 16));
    test("%(x", "(1234567)", new BigInteger("-1234567", 16));
    test("% x", " 1234567", new BigInteger("1234567", 16));
    test("% x", "-1234567", new BigInteger("-1234567", 16));
    test("%+x", "+1234567", new BigInteger("1234567", 16));
    test("%+x", "-1234567", new BigInteger("-1234567", 16));
    test("%010x", "0001234567", new BigInteger("1234567", 16));
    test("%010x", "-001234567", new BigInteger("-1234567", 16));
    test("%(10x", " (1234567)", new BigInteger("-1234567", 16));
    test("%+x", "+1234567", new BigInteger("1234567", 16));
    test("%+x", "-1234567", new BigInteger("-1234567", 16));
    test("%-10x", "1234567   ", new BigInteger("1234567", 16));
    test("%-10x", "-1234567  ", new BigInteger("-1234567", 16));
    test("%#10x", " 0x1234567", new BigInteger("1234567", 16));
    test("%#10x", "-0x1234567", new BigInteger("-1234567", 16));
    test("%#10X", " 0X1234567", new BigInteger("1234567", 16));
    test("%#10X", "-0X1234567", new BigInteger("-1234567", 16));
    test("%X", "1234567A", new BigInteger("1234567a", 16));
    test("%X", "-1234567A", new BigInteger("-1234567a", 16));

    // ---------------------------------------------------------------------
    // %t
    //
    // Date/Time conversions applicable to Calendar, Date, and long.
    // ---------------------------------------------------------------------
    test("%tA", "null", (Object) null);
    test("%TA", "NULL", (Object) null);

    // ---------------------------------------------------------------------
    // %t - errors
    // ---------------------------------------------------------------------
    tryCatch("%t", UnknownFormatConversionException.class);
    tryCatch("%T", UnknownFormatConversionException.class);
    tryCatch("%tP", UnknownFormatConversionException.class);
    tryCatch("%TP", UnknownFormatConversionException.class);
    tryCatch("%.5tB", IllegalFormatPrecisionException.class);
    tryCatch("%#tB", FormatFlagsConversionMismatchException.class);
    tryCatch("%-tB", MissingFormatWidthException.class);

    // ---------------------------------------------------------------------
    // %n
    // ---------------------------------------------------------------------
    test("%n", System.getProperty("line.separator"), (Object) null);
    test("%n", System.getProperty("line.separator"), "");

    tryCatch("%,n", IllegalFormatFlagsException.class);
    tryCatch("%.n", UnknownFormatConversionException.class);
    tryCatch("%5.n", UnknownFormatConversionException.class);
    tryCatch("%5n", IllegalFormatWidthException.class);
    tryCatch("%.7n", IllegalFormatPrecisionException.class);
    tryCatch("%<n", IllegalFormatFlagsException.class);

    // ---------------------------------------------------------------------
    // %%
    // ---------------------------------------------------------------------
    test("%%", "%", (Object) null);
    test("%%", "%", "");
    tryCatch("%%%", UnknownFormatConversionException.class);
    // perhaps an IllegalFormatArgumentIndexException should be defined?
    tryCatch("%<%", IllegalFormatFlagsException.class);
  }
Example #22
0
  /**
   * The constructor for this class has a bunch of arguments: The frame argument is required for all
   * printing in Java. The jobname appears left justified at the top of each printed page. The font
   * size is specified in points, as on-screen font sizes are. The margins are specified in inches
   * (or fractions of inches).
   */
  public HardcopyWriter(
      Frame frame,
      String jobname,
      int fontsize,
      double leftmargin,
      double rightmargin,
      double topmargin,
      double bottommargin)
      throws HardcopyWriter.PrintCanceledException {
    // Get the PrintJob object with which we'll do all the printing.
    // The call is synchronized on the static printprops object, which
    // means that only one print dialog can be popped up at a time.
    // If the user clicks Cancel in the print dialog, throw an exception.
    Toolkit toolkit = frame.getToolkit(); // get Toolkit from Frame
    synchronized (printprops) {
      job = toolkit.getPrintJob(frame, jobname, printprops);
    }
    if (job == null) throw new PrintCanceledException("User cancelled print request");

    pagesize = job.getPageDimension(); // query the page size
    pagedpi = job.getPageResolution(); // query the page resolution

    // Bug Workaround:
    // On windows, getPageDimension() and getPageResolution don't work, so
    // we've got to fake them.
    if (System.getProperty("os.name").regionMatches(true, 0, "windows", 0, 7)) {
      // Use screen dpi, which is what the PrintJob tries to emulate, anyway
      pagedpi = toolkit.getScreenResolution();
      System.out.println(pagedpi);
      // Assume a 8.5" x 11" page size.  A4 paper users have to change this.
      pagesize = new Dimension((int) (8.5 * pagedpi), 11 * pagedpi);
      System.out.println(pagesize);
      // We also have to adjust the fontsize.  It is specified in points,
      // (1 point = 1/72 of an inch) but Windows measures it in pixels.
      fontsize = fontsize * pagedpi / 72;
      System.out.println(fontsize);
      System.out.flush();
    }

    // Compute coordinates of the upper-left corner of the page.
    // I.e. the coordinates of (leftmargin, topmargin).  Also compute
    // the width and height inside of the margins.
    x0 = (int) (leftmargin * pagedpi);
    y0 = (int) (topmargin * pagedpi);
    width = pagesize.width - (int) ((leftmargin + rightmargin) * pagedpi);
    height = pagesize.height - (int) ((topmargin + bottommargin) * pagedpi);

    // Get body font and font size
    font = new Font("Monospaced", Font.PLAIN, fontsize);
    metrics = toolkit.getFontMetrics(font);
    lineheight = metrics.getHeight();
    lineascent = metrics.getAscent();
    charwidth = metrics.charWidth('0'); // Assumes a monospaced font!

    // Now compute columns and lines will fit inside the margins
    chars_per_line = width / charwidth;
    lines_per_page = height / lineheight;

    // Get header font information
    // And compute baseline of page header: 1/8" above the top margin
    headerfont = new Font("SansSerif", Font.ITALIC, fontsize);
    headermetrics = toolkit.getFontMetrics(headerfont);
    headery = y0 - (int) (0.125 * pagedpi) - headermetrics.getHeight() + headermetrics.getAscent();

    // Compute the date/time string to display in the page header
    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.SHORT);
    df.setTimeZone(TimeZone.getDefault());
    time = df.format(new Date());

    this.jobname = jobname; // save name
    this.fontsize = fontsize; // save font size
  }
Example #23
0
public class NetUtils {

  private static Logger logger = LoggerFactory.createLogger(NetUtils.class);

  public static final String DYNAMIC_RESOURCES_SESSION_KEY = "orbeon.resources.dynamic.";
  // Resources are served by the XForms server. It is not ideal to refer to XForms-related
  // functionality from here.
  public static final String DYNAMIC_RESOURCES_PATH = "/xforms-server/dynamic/";

  private static final Pattern PATTERN_NO_AMP;
  private static final Pattern PATTERN_AMP;
  //    private static final Pattern PATTERN_AMP_AMP;

  public static final String STANDARD_PARAMETER_ENCODING = "utf-8";

  private static final SimpleDateFormat dateHeaderFormats[] = {
    new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
    new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
    new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
  };

  private static final TimeZone gmtZone = TimeZone.getTimeZone("GMT");
  private static FileItemFactory fileItemFactory;

  public static final int REQUEST_SCOPE = 0;
  public static final int SESSION_SCOPE = 1;
  public static final int APPLICATION_SCOPE = 2;

  // Default HTTP 1.1 charset for text/* mediatype
  public static final String DEFAULT_HTTP_TEXT_READING_ENCODING = "iso-8859-1";
  // Default RFC 3023 default charset for txt/xml mediatype
  public static final String DEFAULT_TEXT_XML_READING_ENCODING = "us-ascii";
  public static final String APPLICATION_SOAP_XML = "application/soap+xml";

  static {
    // Set timezone to GMT as required for HTTP headers
    for (SimpleDateFormat dateHeaderFormat : dateHeaderFormats)
      dateHeaderFormat.setTimeZone(gmtZone);

    final String notEqNorAmpChar = "[^=&]";
    final String token = notEqNorAmpChar + "+";
    PATTERN_NO_AMP = Pattern.compile("(" + token + ")=(" + token + ")(?:&|(?<!&)\\z)");
    PATTERN_AMP = Pattern.compile("(" + token + ")=(" + token + ")(?:&amp;|&|(?<!&amp;|&)\\z)");
    //        PATTERN_AMP_AMP = Pattern.compile( "(" + token + ")=(" + token +
    // ")(?:&amp;amp;|&|(?<!&amp;amp;|&)\\z)" );
  }

  public static long getDateHeader(String stringValue) throws ParseException {
    for (SimpleDateFormat dateHeaderFormat : dateHeaderFormats) {
      try {
        Date date = dateHeaderFormat.parse(stringValue);
        return date.getTime();
      } catch (
          Exception
              e) { // used to be ParseException, but NumberFormatException may be thrown as well
        // Ignore and try next
      }
    }
    throw new ParseException(stringValue, 0);
  }

  /**
   * Return true if the document was modified since the given date, based on the If-Modified-Since
   * header. If the request method was not "GET", or if no valid lastModified value was provided,
   * consider the document modified.
   */
  public static boolean checkIfModifiedSince(HttpServletRequest request, long lastModified) {
    // Do the check only for the GET method
    if (!"GET".equals(request.getMethod()) || lastModified <= 0) return true;
    // Check dates
    String ifModifiedHeader = request.getHeader("If-Modified-Since");
    if (logger.isDebugEnabled()) logger.debug("Found If-Modified-Since header");
    if (ifModifiedHeader != null) {
      try {
        long dateTime = getDateHeader(ifModifiedHeader);
        if (lastModified <= (dateTime + 1000)) {
          if (logger.isDebugEnabled()) logger.debug("Sending SC_NOT_MODIFIED response");
          return false;
        }
      } catch (
          Exception
              e) { // used to be ParseException, but NumberFormatException may be thrown as well
        // Ignore
      }
    }
    return true;
  }

  /**
   * Return a request path info that looks like what one would expect. The path starts with a "/",
   * relative to the servlet context. If the servlet was included or forwarded to, return the path
   * by which the *current* servlet was invoked, NOT the path of the calling servlet.
   *
   * <p>Request path = servlet path + path info.
   *
   * @param request servlet HTTP request
   * @return path
   */
  public static String getRequestPathInfo(HttpServletRequest request) {

    // NOTE: Servlet 2.4 spec says: "These attributes [javax.servlet.include.*] are accessible from
    // the included
    // servlet via the getAttribute method on the request object and their values must be equal to
    // the request URI,
    // context path, servlet path, path info, and query string of the included servlet,
    // respectively."
    // NOTE: This is very different from the similarly-named forward attributes!

    // Get servlet path
    String servletPath = (String) request.getAttribute("javax.servlet.include.servlet_path");
    if (servletPath == null) {
      servletPath = request.getServletPath();
      if (servletPath == null) servletPath = "";
    }

    // Get path info
    String pathInfo = (String) request.getAttribute("javax.servlet.include.path_info");
    if (pathInfo == null) {
      pathInfo = request.getPathInfo();
      if (pathInfo == null) pathInfo = "";
    }

    // Concatenate servlet path and path info, avoiding a double slash
    String requestPath =
        servletPath.endsWith("/") && pathInfo.startsWith("/")
            ? servletPath + pathInfo.substring(1)
            : servletPath + pathInfo;

    // Add starting slash if missing
    if (!requestPath.startsWith("/")) requestPath = "/" + requestPath;

    return requestPath;
  }

  /**
   * Return the last modification date of the given absolute URL if it is "fast" to do so, i.e. if
   * it is an "oxf:" or a "file:" protocol.
   *
   * @param absoluteURL absolute URL to check
   * @return last modification date if "fast" or 0 if not fast or if an error occurred
   */
  public static long getLastModifiedIfFast(String absoluteURL) {
    final long lastModified;
    if (absoluteURL.startsWith("oxf:") || absoluteURL.startsWith("file:")) {
      try {
        lastModified = getLastModified(URLFactory.createURL(absoluteURL));
      } catch (IOException e) {
        throw new OXFException(e);
      }
    } else {
      // Value of 0 for lastModified will cause XFormsResourceServer to set Last-Modified and
      // Expires properly to "now".
      lastModified = 0;
    }
    return lastModified;
  }

  /**
   * Get the last modification date of a URL.
   *
   * @return last modified timestamp, null if le 0
   */
  public static Long getLastModifiedAsLong(URL url) throws IOException {
    final long connectionLastModified = getLastModified(url);
    // Zero and negative values often have a special meaning, make sure to normalize here
    return connectionLastModified <= 0 ? null : connectionLastModified;
  }

  /**
   * Get the last modification date of a URL.
   *
   * @return last modified timestamp "as is"
   */
  public static long getLastModified(URL url) throws IOException {
    if ("file".equals(url.getProtocol())) {
      // Optimize file: access. Also, this prevents throwing an exception if the file doesn't exist
      // as we try to close the stream below.
      return new File(URLDecoder.decode(url.getFile(), STANDARD_PARAMETER_ENCODING)).lastModified();
    } else {
      // Use URLConnection
      final URLConnection urlConnection = url.openConnection();
      if (urlConnection instanceof HttpURLConnection)
        ((HttpURLConnection) urlConnection).setRequestMethod("HEAD");
      try {
        return getLastModified(urlConnection);
      } finally {
        final InputStream is = urlConnection.getInputStream();
        if (is != null) is.close();
      }
    }
  }

  /**
   * Get the last modification date of an open URLConnection.
   *
   * <p>This handles the (broken at some point in the Java libraries) case of the file: protocol.
   *
   * @return last modified timestamp, null if le 0
   */
  public static Long getLastModifiedAsLong(URLConnection urlConnection) {
    final long connectionLastModified = getLastModified(urlConnection);
    // Zero and negative values often have a special meaning, make sure to normalize here
    return connectionLastModified <= 0 ? null : connectionLastModified;
  }

  /**
   * Get the last modification date of an open URLConnection.
   *
   * <p>This handles the (broken at some point in the Java libraries) case of the file: protocol.
   *
   * @return last modified timestamp "as is"
   */
  public static long getLastModified(URLConnection urlConnection) {
    try {
      long lastModified = urlConnection.getLastModified();
      if (lastModified == 0 && "file".equals(urlConnection.getURL().getProtocol()))
        lastModified =
            new File(
                    URLDecoder.decode(
                        urlConnection.getURL().getFile(), STANDARD_PARAMETER_ENCODING))
                .lastModified();
      return lastModified;
    } catch (UnsupportedEncodingException e) {
      // Should not happen as we are using a required encoding
      throw new OXFException(e);
    }
  }

  /** Check if an URL is relative to another URL. */
  public static boolean relativeURL(URL url1, URL url2) {
    return ((url1.getProtocol() == null && url2.getProtocol() == null)
            || url1.getProtocol().equals(url2.getProtocol()))
        && ((url1.getAuthority() == null && url2.getAuthority() == null)
            || url1.getAuthority().equals(url2.getAuthority()))
        && ((url1.getPath() == null && url2.getPath() == null)
            || url2.getPath().startsWith(url1.getPath()));
  }

  public static void copyStream(InputStream is, OutputStream os) throws IOException {
    int count;
    byte[] buffer = new byte[1024];
    while ((count = is.read(buffer)) > 0) os.write(buffer, 0, count);
  }

  public static void copyStream(Reader reader, Writer writer) throws IOException {
    int count;
    char[] buffer = new char[1024];
    while ((count = reader.read(buffer)) > 0) writer.write(buffer, 0, count);
  }

  public static String readStreamAsString(Reader reader) throws IOException {
    final StringBuilderWriter writer = new StringBuilderWriter();
    copyStream(reader, writer);
    return writer.toString();
  }

  public static String getContentTypeCharset(String contentType) {
    final Map<String, String> parameters = getContentTypeParameters(contentType);
    return (parameters == null) ? null : parameters.get("charset");
  }

  public static Map<String, String> getContentTypeParameters(String contentType) {
    if (contentType == null) return null;

    // Check whether there may be parameters
    final int semicolonIndex = contentType.indexOf(";");
    if (semicolonIndex == -1) return null;

    // Tokenize
    final StringTokenizer st = new StringTokenizer(contentType, ";");

    if (!st.hasMoreTokens())
      return null; // should not happen as there should be at least the content type

    st.nextToken();

    // No parameters
    if (!st.hasMoreTokens()) return null;

    // Parse parameters
    final Map<String, String> parameters = new HashMap<String, String>();
    while (st.hasMoreTokens()) {
      final String parameter = st.nextToken().trim();
      final int equalIndex = parameter.indexOf('=');
      if (equalIndex == -1) continue;
      final String name = parameter.substring(0, equalIndex).trim();
      final String value = parameter.substring(equalIndex + 1).trim();
      parameters.put(name, value);
    }
    return parameters;
  }

  public static Map<String, String> getCharsetHeaderCharsets(String header) {
    if (header == null) return null;
    int semicolonIndex = header.indexOf(";");
    final String charsets;
    if (semicolonIndex == -1) charsets = header.trim();
    else charsets = header.substring(0, semicolonIndex).trim();

    final StringTokenizer st = new StringTokenizer(charsets, ",");
    final Map<String, String> charsetsMap = new HashMap<String, String>();
    while (st.hasMoreTokens()) {
      charsetsMap.put(st.nextToken(), "");
    }

    return charsetsMap;
  }

  public static String getContentTypeMediaType(String contentType) {
    if (contentType == null || contentType.equalsIgnoreCase("content/unknown")) return null;
    int semicolonIndex = contentType.indexOf(";");
    if (semicolonIndex == -1) return contentType;
    return contentType.substring(0, semicolonIndex).trim();
  }

  /**
   * @param queryString a query string of the form n1=v1&n2=v2&... to decode. May be null.
   * @param acceptAmp -> "&amp;" if true, "&" if false
   * @return a Map of String[] indexed by name, an empty Map if the query string was null
   */
  public static Map<String, String[]> decodeQueryString(
      final CharSequence queryString, final boolean acceptAmp) {

    final Map<String, String[]> result = new TreeMap<String, String[]>();
    if (queryString != null) {
      final Matcher matcher =
          acceptAmp ? PATTERN_AMP.matcher(queryString) : PATTERN_NO_AMP.matcher(queryString);
      int matcherEnd = 0;
      while (matcher.find()) {
        matcherEnd = matcher.end();
        try {
          // Group 0 is the whole match, e.g. a=b, while group 1 is the first group
          // denoted ( with parens ) in the expression.  Hence we start with group 1.
          final String name =
              URLDecoder.decode(matcher.group(1), NetUtils.STANDARD_PARAMETER_ENCODING);
          final String value =
              URLDecoder.decode(matcher.group(2), NetUtils.STANDARD_PARAMETER_ENCODING);

          StringUtils.addValueToStringArrayMap(result, name, value);
        } catch (UnsupportedEncodingException e) {
          // Should not happen as we are using a required encoding
          throw new OXFException(e);
        }
      }
      if (queryString.length() != matcherEnd) {
        // There was garbage at the end of the query.
        throw new OXFException("Malformed URL: " + queryString);
      }
    }
    return result;
  }

  /** Encode a query string. The input Map contains names indexing Object[]. */
  public static String encodeQueryString(Map parameters) {
    final StringBuilder sb = new StringBuilder(100);
    boolean first = true;
    try {
      for (Object o : parameters.keySet()) {
        final String name = (String) o;
        final Object[] values = (Object[]) parameters.get(name);
        for (final Object currentValue : values) {
          if (currentValue instanceof String) {
            if (!first) sb.append('&');

            sb.append(URLEncoder.encode(name, NetUtils.STANDARD_PARAMETER_ENCODING));
            sb.append('=');
            sb.append(
                URLEncoder.encode((String) currentValue, NetUtils.STANDARD_PARAMETER_ENCODING));

            first = false;
          }
        }
      }
    } catch (UnsupportedEncodingException e) {
      // Should not happen as we are using a required encoding
      throw new OXFException(e);
    }
    return sb.toString();
  }

  /** Combine a path info and a parameters map to form a path info with a query string. */
  public static String pathInfoParametersToPathInfoQueryString(String pathInfo, Map parameters)
      throws IOException {
    final StringBuilder redirectURL = new StringBuilder(pathInfo);
    if (parameters != null) {
      boolean first = true;
      for (Object o : parameters.keySet()) {
        final String name = (String) o;
        final Object[] values = (Object[]) parameters.get(name);
        for (final Object currentValue : values) {
          if (currentValue instanceof String) {
            redirectURL.append(first ? "?" : "&");
            redirectURL.append(URLEncoder.encode(name, NetUtils.STANDARD_PARAMETER_ENCODING));
            redirectURL.append("=");
            redirectURL.append(
                URLEncoder.encode((String) currentValue, NetUtils.STANDARD_PARAMETER_ENCODING));
            first = false;
          }
        }
      }
    }
    return redirectURL.toString();
  }

  /**
   * Append a query string to an URL. This adds a '?' or a '&' or nothing, as needed.
   *
   * @param urlString existing URL string
   * @param queryString query string, or null
   * @return resulting URL
   */
  public static String appendQueryString(String urlString, String queryString) {
    if (org.apache.commons.lang.StringUtils.isBlank(queryString)) {
      return urlString;
    } else {
      final StringBuilder updatedActionStringBuilder = new StringBuilder(urlString);
      updatedActionStringBuilder.append((urlString.indexOf('?') == -1) ? '?' : '&');
      updatedActionStringBuilder.append(queryString);
      return updatedActionStringBuilder.toString();
    }
  }

  /**
   * Check whether a URL starts with a protocol.
   *
   * <p>We consider that a protocol consists only of ASCII letters and must be at least two
   * characters long, to avoid confusion with Windows drive letters.
   */
  public static boolean urlHasProtocol(String urlString) {
    int colonIndex = urlString.indexOf(":");

    // No protocol is there is no colon or if there is only one character in the protocol
    if (colonIndex == -1 || colonIndex == 1) return false;

    // Check that there is a protocol
    boolean allChar = true;
    for (int i = 0; i < colonIndex; i++) {
      char c = urlString.charAt(i);
      if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) {
        allChar = false;
        break;
      }
    }
    return allChar;
  }

  /**
   * Resolve a URI against a base URI. (Be sure to pay attention to the order or parameters.)
   *
   * @param href URI to resolve (accept human-readable URI)
   * @param base URI base (accept human-readable URI)
   * @return resolved URI
   */
  public static String resolveURI(String href, String base) {
    final String resolvedURIString;
    if (base != null) {
      final URI baseURI;
      try {
        baseURI = new URI(encodeHRRI(base, true));
      } catch (URISyntaxException e) {
        throw new OXFException(e);
      }
      resolvedURIString =
          baseURI
              .resolve(encodeHRRI(href, true))
              .normalize()
              .toString(); // normalize to remove "..", etc.
    } else {
      resolvedURIString = encodeHRRI(href, true);
    }
    return resolvedURIString;
  }

  public static String headersToString(HttpServletRequest request) {
    final StringBuffer sb = new StringBuffer();
    for (Enumeration e = request.getHeaderNames(); e.hasMoreElements(); ) {
      final String name = (String) e.nextElement();
      sb.append(name);
      sb.append("=");
      for (Enumeration f = request.getHeaders(name); f.hasMoreElements(); ) {
        final String value = (String) f.nextElement();
        sb.append(value);
        if (f.hasMoreElements()) sb.append(",");
      }
      if (e.hasMoreElements()) sb.append("|");
    }
    return sb.toString();
  }

  public static String readURIToLocalURI(String uri) throws URISyntaxException, IOException {
    final PipelineContext pipelineContext =
        StaticExternalContext.getStaticContext().getPipelineContext();
    final URLConnection urlConnection = new URI(uri).toURL().openConnection();
    InputStream inputStream = null;
    try {
      inputStream = urlConnection.getInputStream();
      return inputStreamToAnyURI(pipelineContext, inputStream, REQUEST_SCOPE);
    } finally {
      if (inputStream != null) inputStream.close();
    }
  }

  public static byte[] base64StringToByteArray(String base64String) {
    return Base64.decode(base64String);
  }

  /**
   * Convert a String in xs:base64Binary to an xs:anyURI.
   *
   * <p>NOTE: The implementation creates a temporary file. The Pipeline Context is required so that
   * the file can be deleted when no longer used.
   */
  public static String base64BinaryToAnyURI(
      PipelineContext pipelineContext, String value, int scope) {
    // Convert Base64 to binary first
    final byte[] bytes = base64StringToByteArray(value);

    return inputStreamToAnyURI(pipelineContext, new ByteArrayInputStream(bytes), scope);
  }

  /**
   * Read an InputStream into a byte array.
   *
   * @param is InputStream
   * @return byte array
   */
  public static byte[] inputStreamToByteArray(InputStream is) {
    try {
      final ByteArrayOutputStream os = new ByteArrayOutputStream();
      copyStream(new BufferedInputStream(is), os);
      os.close();
      return os.toByteArray();
    } catch (Exception e) {
      throw new OXFException(e);
    }
  }

  /**
   * Read a URI into a byte array.
   *
   * @param uri URI to read
   * @return byte array
   */
  public static byte[] uriToByteArray(String uri) {
    InputStream is = null;
    try {
      is = new URI(uri).toURL().openStream();
      return inputStreamToByteArray(is);
    } catch (Exception e) {
      throw new OXFException(e);
    } finally {
      try {
        if (is != null) is.close();
      } catch (IOException e) {
        throw new OXFException(e);
      }
    }
  }

  /**
   * Convert a URI to a FileItem.
   *
   * <p>The implementation creates a temporary file. The PipelineContext is required so that the
   * file can be deleted when no longer used.
   */
  public static FileItem anyURIToFileItem(PipelineContext pipelineContext, String uri, int scope) {
    InputStream inputStream = null;
    try {
      inputStream = new URI(uri).toURL().openStream();

      // Get FileItem
      return prepareFileItemFromInputStream(pipelineContext, inputStream, scope);

    } catch (Exception e) {
      throw new OXFException(e);
    } finally {
      try {
        if (inputStream != null) inputStream.close();
      } catch (IOException e) {
        throw new OXFException(e);
      }
    }
  }

  /**
   * Convert an InputStream to an xs:anyURI.
   *
   * <p>The implementation creates a temporary file. The PipelineContext is required so that the
   * file can be deleted when no longer used.
   */
  public static String inputStreamToAnyURI(
      PipelineContext pipelineContext, InputStream inputStream, int scope) {
    // Get FileItem
    final FileItem fileItem = prepareFileItemFromInputStream(pipelineContext, inputStream, scope);

    // Return a file URL
    final File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
    return storeLocation.toURI().toString();
  }

  private static FileItem prepareFileItemFromInputStream(
      PipelineContext pipelineContext, InputStream inputStream, int scope) {
    // Get FileItem
    final FileItem fileItem = prepareFileItem(pipelineContext, scope);
    // Write to file
    OutputStream os = null;
    try {
      os = fileItem.getOutputStream();
      copyStream(inputStream, os);
    } catch (IOException e) {
      throw new OXFException(e);
    } finally {
      if (os != null) {
        try {
          os.close();
        } catch (IOException e) {
          throw new OXFException(e);
        }
      }
    }
    // Create file if it doesn't exist (necessary when the file size is 0)
    final File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
    try {
      storeLocation.createNewFile();
    } catch (IOException e) {
      throw new OXFException(e);
    }

    return fileItem;
  }

  /**
   * Return a FileItem which is going to be automatically destroyed upon destruction of the request,
   * session or application.
   */
  public static FileItem prepareFileItem(PipelineContext pipelineContext, int scope) {
    // We use the commons file upload utilities to save a file
    if (fileItemFactory == null)
      fileItemFactory = new DiskFileItemFactory(0, SystemUtils.getTemporaryDirectory());
    final FileItem fileItem = fileItemFactory.createItem("dummy", "dummy", false, null);
    // Make sure the file is deleted appropriately
    if (scope == REQUEST_SCOPE) {
      deleteFileOnRequestEnd(pipelineContext, fileItem);
    } else if (scope == SESSION_SCOPE) {
      deleteFileOnSessionTermination(pipelineContext, fileItem);
    } else if (scope == APPLICATION_SCOPE) {
      deleteFileOnContextDestroyed(pipelineContext, fileItem);
    } else {
      throw new OXFException("Invalid context requested: " + scope);
    }
    // Return FileItem object
    return fileItem;
  }

  /**
   * Add listener to fileItem which is going to be automatically destroyed at the end of request
   *
   * @param pipelineContext PipelineContext
   * @param fileItem FileItem
   */
  public static void deleteFileOnRequestEnd(
      PipelineContext pipelineContext, final FileItem fileItem) {
    // Make sure the file is deleted at the end of request
    pipelineContext.addContextListener(
        new PipelineContext.ContextListenerAdapter() {
          public void contextDestroyed(boolean success) {
            deleteFileItem(fileItem, REQUEST_SCOPE);
          }
        });
  }

  /**
   * Add listener to fileItem which is going to be automatically destroyed on session destruction
   *
   * @param pipelineContext PipelineContext
   * @param fileItem FileItem
   */
  public static void deleteFileOnSessionTermination(
      PipelineContext pipelineContext, final FileItem fileItem) {
    // Try to delete the file on exit and on session termination
    final ExternalContext externalContext =
        (ExternalContext) pipelineContext.getAttribute(PipelineContext.EXTERNAL_CONTEXT);
    final ExternalContext.Session session = externalContext.getSession(false);
    if (session != null) {
      session.addListener(
          new ExternalContext.Session.SessionListener() {
            public void sessionDestroyed() {
              deleteFileItem(fileItem, SESSION_SCOPE);
            }
          });
    } else {
      logger.debug(
          "No existing session found so cannot register temporary file deletion upon session destruction: "
              + fileItem.getName());
    }
  }

  /**
   * Add listener to fileItem which is going to be automatically destroyed when the servlet is
   * destroyed
   *
   * @param pipelineContext PipelineContext
   * @param fileItem FileItem
   */
  public static void deleteFileOnContextDestroyed(
      PipelineContext pipelineContext, final FileItem fileItem) {
    // Try to delete the file on exit and on session termination
    final ExternalContext externalContext =
        (ExternalContext) pipelineContext.getAttribute(PipelineContext.EXTERNAL_CONTEXT);
    ExternalContext.Application application = externalContext.getApplication();
    if (application != null) {
      application.addListener(
          new ExternalContext.Application.ApplicationListener() {
            public void servletDestroyed() {
              deleteFileItem(fileItem, APPLICATION_SCOPE);
            }
          });
    } else {
      logger.debug(
          "No application object found so cannot register temporary file deletion upon session destruction: "
              + fileItem.getName());
    }
  }

  private static void deleteFileItem(FileItem fileItem, int scope) {
    if (logger.isDebugEnabled() && fileItem instanceof DiskFileItem) {
      final File storeLocation = ((DiskFileItem) fileItem).getStoreLocation();
      if (storeLocation != null) {
        final String temporaryFileName = storeLocation.getAbsolutePath();
        final String scopeString =
            (scope == REQUEST_SCOPE)
                ? "request"
                : (scope == SESSION_SCOPE) ? "session" : "application";
        logger.debug("Deleting temporary " + scopeString + "-scoped file: " + temporaryFileName);
      }
    }
    fileItem.delete();
  }

  /**
   * Convert a String in xs:anyURI to an xs:base64Binary.
   *
   * <p>The URI has to be a URL. It is read entirely
   */
  public static String anyURIToBase64Binary(String value) {
    InputStream is = null;
    try {
      // Read from URL and convert to Base64
      is = URLFactory.createURL(value).openStream();
      final StringBuffer sb = new StringBuffer();
      XMLUtils.inputStreamToBase64Characters(
          is,
          new ContentHandlerAdapter() {
            public void characters(char ch[], int start, int length) {
              sb.append(ch, start, length);
            }
          });
      // Return Base64 String
      return sb.toString();
    } catch (IOException e) {
      throw new OXFException(e);
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
          throw new OXFException(e);
        }
      }
    }
  }

  public static void anyURIToOutputStream(String value, OutputStream outputStream) {
    InputStream is = null;
    try {
      is = URLFactory.createURL(value).openStream();
      copyStream(is, outputStream);
    } catch (IOException e) {
      throw new OXFException(e);
    } finally {
      if (is != null) {
        try {
          is.close();
        } catch (IOException e) {
          throw new OXFException(e);
        }
      }
    }
  }

  /**
   * Return the charset associated with a text/* Content-Type header. If a charset is present,
   * return it. Otherwise, guess depending on whether the mediatype is text/xml or not.
   *
   * @param contentType Content-Type header value
   * @return charset
   */
  public static String getTextCharsetFromContentType(String contentType) {
    final String charset;
    final String connectionCharset = getContentTypeCharset(contentType);
    if (connectionCharset != null) {
      charset = connectionCharset;
    } else {

      // RFC 3023: "Conformant with [RFC2046], if a text/xml entity is
      // received with the charset parameter omitted, MIME processors and
      // XML processors MUST use the default charset value of
      // "us-ascii"[ASCII]. In cases where the XML MIME entity is
      // transmitted via HTTP, the default charset value is still
      // "us-ascii". (Note: There is an inconsistency between this
      // specification and HTTP/1.1, which uses ISO-8859-1[ISO8859] as the
      // default for a historical reason. Since XML is a new format, a new
      // default should be chosen for better I18N. US-ASCII was chosen,
      // since it is the intersection of UTF-8 and ISO-8859-1 and since it
      // is already used by MIME.)"

      if (XMLUtils.isXMLMediatype(contentType)) charset = DEFAULT_TEXT_XML_READING_ENCODING;
      else charset = DEFAULT_HTTP_TEXT_READING_ENCODING;
    }
    return charset;
  }

  /**
   * Remove the first path element of a path. Return null if there is only one path element
   *
   * <p>E.g. /foo/bar => /bar?a=b
   *
   * @param path path to modify
   * @return modified path or null
   */
  public static String removeFirstPathElement(String path) {
    final int secondSlashIndex = path.indexOf('/', 1);
    if (secondSlashIndex == -1) return null;

    return path.substring(secondSlashIndex);
  }

  /**
   * Return the first path element of a path. If there is only one path element, return the entire
   * path.
   *
   * <p>E.g. /foo/bar => /foo
   *
   * @param path path to analyze
   * @return first path element
   */
  public static String getFirstPathElement(String path) {
    final int secondSlashIndex = path.indexOf('/', 1);
    if (secondSlashIndex == -1) return path;

    return path.substring(0, secondSlashIndex);
  }

  /**
   * Transform an URI accessible from the server into a URI accessible from the client. The mapping
   * expires with the session.
   *
   * @param propertyContext context to obtain session
   * @param uri server URI to transform
   * @param filename file name
   * @param contentType type of the content referred to by the URI, or null if unknown
   * @param lastModified last modification timestamp
   * @return client URI
   */
  public static String proxyURI(
      PropertyContext propertyContext,
      String uri,
      String filename,
      String contentType,
      long lastModified) {

    // Create a digest, so that for a given URI we always get the same key
    final String digest = SecureUtils.digestString(uri, "MD5", "hex");

    // Get session
    final ExternalContext externalContext =
        (ExternalContext) propertyContext.getAttribute(PipelineContext.EXTERNAL_CONTEXT);
    final ExternalContext.Session session =
        externalContext.getSession(
            true); // NOTE: We force session creation here. Should we? What's the alternative?

    if (session != null) {
      // Store mapping into session
      session
          .getAttributesMap(ExternalContext.Session.APPLICATION_SCOPE)
          .put(
              DYNAMIC_RESOURCES_SESSION_KEY + digest,
              new DynamicResource(uri, filename, contentType, -1, lastModified));
    }

    // Rewrite new URI to absolute path without the context
    return DYNAMIC_RESOURCES_PATH + digest;
  }

  /**
   * Utility method to decode a multipart/fomr-data stream and return a Map of parameters of type
   * Object[], each of which can be a String or FileData.
   */
  public static Map<String, Object[]> getParameterMapMultipart(
      PipelineContext pipelineContext,
      final ExternalContext.Request request,
      String headerEncoding) {

    final Map<String, Object[]> uploadParameterMap = new HashMap<String, Object[]>();
    try {
      // Setup commons upload

      // Read properties
      // NOTE: We use properties scoped in the Request generator for historical reasons. Not too
      // good.
      int maxSize = RequestGenerator.getMaxSizeProperty();
      int maxMemorySize = RequestGenerator.getMaxMemorySizeProperty();

      final DiskFileItemFactory diskFileItemFactory =
          new DiskFileItemFactory(maxMemorySize, SystemUtils.getTemporaryDirectory());

      final ServletFileUpload upload =
          new ServletFileUpload(diskFileItemFactory) {
            protected FileItem createItem(Map headers, boolean isFormField)
                throws FileUploadException {
              if (isFormField) {
                // Handle externalized values
                final String externalizeFormValuesPrefix =
                    org.orbeon.oxf.properties.Properties.instance()
                        .getPropertySet()
                        .getString(ServletExternalContext.EXTERNALIZE_FORM_VALUES_PREFIX_PROPERTY);
                final String fieldName = getFieldName(headers);
                if (externalizeFormValuesPrefix != null
                    && fieldName.startsWith(externalizeFormValuesPrefix)) {
                  // In this case, we do as if the value content is an uploaded file so that it can
                  // be externalized
                  return super.createItem(headers, false);
                } else {
                  // Just create the FileItem using the default way
                  return super.createItem(headers, isFormField);
                }
              } else {
                // Just create the FileItem using the default way
                return super.createItem(headers, isFormField);
              }
            }
          };
      upload.setHeaderEncoding(headerEncoding);
      upload.setSizeMax(maxSize);

      // Add a listener to destroy file items when the pipeline context is destroyed
      pipelineContext.addContextListener(
          new PipelineContext.ContextListenerAdapter() {
            public void contextDestroyed(boolean success) {
              for (final String name : uploadParameterMap.keySet()) {
                final Object values[] = uploadParameterMap.get(name);
                for (final Object currentValue : values) {
                  if (currentValue instanceof FileItem) {
                    final FileItem fileItem = (FileItem) currentValue;
                    fileItem.delete();
                  }
                }
              }
            }
          });

      // Wrap and implement just the required methods for the upload code
      final InputStream inputStream;
      try {
        inputStream = request.getInputStream();
      } catch (IOException e) {
        throw new OXFException(e);
      }

      final RequestContext requestContext =
          new RequestContext() {

            public int getContentLength() {
              return request.getContentLength();
            }

            public InputStream getInputStream() {
              // NOTE: The upload code does not actually check that it doesn't read more than the
              // content-length
              // sent by the client! Maybe here would be a good place to put an interceptor and make
              // sure we
              // don't read too much.
              return new InputStream() {
                public int read() throws IOException {
                  return inputStream.read();
                }
              };
            }

            public String getContentType() {
              return request.getContentType();
            }

            public String getCharacterEncoding() {
              return request.getCharacterEncoding();
            }
          };

      // Parse the request and add file information
      try {
        for (Object o : upload.parseRequest(requestContext)) {
          final FileItem fileItem = (FileItem) o;
          // Add value to existing values if any
          if (fileItem.isFormField()) {
            // Simple form field
            // Assume that form fields are in UTF-8. Can they have another encoding? If so, how is
            // it specified?
            StringUtils.addValueToObjectArrayMap(
                uploadParameterMap,
                fileItem.getFieldName(),
                fileItem.getString(STANDARD_PARAMETER_ENCODING));
          } else {
            // File
            StringUtils.addValueToObjectArrayMap(
                uploadParameterMap, fileItem.getFieldName(), fileItem);
          }
        }
      } catch (FileUploadBase.SizeLimitExceededException e) {
        // Should we do something smart so we can use the Presentation
        // Server error page anyway? Right now, this is going to fail
        // miserably with an error.
        throw e;
      } catch (UnsupportedEncodingException e) {
        // Should not happen
        throw new OXFException(e);
      } finally {
        // Close the input stream; if we don't nobody does, and if this stream is
        // associated with a temporary file, that file may resist deletion
        if (inputStream != null) {
          try {
            inputStream.close();
          } catch (IOException e) {
            throw new OXFException(e);
          }
        }
      }

      return uploadParameterMap;
    } catch (FileUploadException e) {
      throw new OXFException(e);
    }
  }

  /**
   * Encode a Human Readable Resource Identifier to a URI. Leading and trailing spaces are removed
   * first.
   *
   * <p>NOTE: See more recent W3C note: http://www.w3.org/TR/2008/NOTE-leiri-20081103/
   *
   * @param uriString URI to encode
   * @param processSpace whether to process the space character or leave it unchanged
   * @return encoded URI, or null if uriString was null
   */
  public static String encodeHRRI(String uriString, boolean processSpace) {

    if (uriString == null) return null;

    // Note that the XML Schema spec says "Spaces are, in principle, allowed in the ·lexical space·
    // of anyURI,
    // however, their use is highly discouraged (unless they are encoded by %20).".

    // We assume that we never want leading or trailing spaces. You can use %20 if you really want
    // this.
    uriString = uriString.trim();

    // We try below to follow the "Human Readable Resource Identifiers" RFC, in draft as of
    // 2007-06-06.
    // * the control characters #x0 to #x1F and #x7F to #x9F
    // * space #x20
    // * the delimiters "<" #x3C, ">" #x3E, and """ #x22
    // * the unwise characters "{" #x7B, "}" #x7D, "|" #x7C, "\" #x5C, "^" #x5E, and "`" #x60
    final StringBuilder sb = new StringBuilder(uriString.length() * 2);
    for (int i = 0; i < uriString.length(); i++) {
      final char currentChar = uriString.charAt(i);

      if (currentChar >= 0
          && (currentChar <= 0x1f
              || (processSpace && currentChar == 0x20)
              || currentChar == 0x22
              || currentChar == 0x3c
              || currentChar == 0x3e
              || currentChar == 0x5c
              || currentChar == 0x5e
              || currentChar == 0x60
              || (currentChar >= 0x7b && currentChar <= 0x7d)
              || (currentChar >= 0x7f && currentChar <= 0x9f))) {
        sb.append('%');
        sb.append(NumberUtils.toHexString((byte) currentChar).toUpperCase());
      } else {
        sb.append(currentChar);
      }
    }

    return sb.toString();
  }

  public static class DynamicResource {
    private String uri;
    private String filename;
    private String contentType;
    private long size;
    private long lastModified;

    public DynamicResource(
        String uri, String filename, String contentType, long size, long lastModified) {
      this.uri = uri;
      this.filename = filename;
      this.contentType = contentType;
      this.size = size;
      this.lastModified = lastModified;
    }

    public String getURI() {
      return uri;
    }

    public String getFilename() {
      return filename;
    }

    public String getContentType() {
      return contentType;
    }

    public long getSize() {
      return size;
    }

    public long getLastModified() {
      return lastModified;
    }
  }
}
Example #24
0
 /**
  * Get the day and date information for today, depending upon user option.
  *
  * @return String Today.
  * @see java.util.Calendar
  * @see java.util.GregorianCalendar
  * @see java.util.TimeZone
  */
 public String today() {
   Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
   return calendar.getTime().toString();
 }