/** * Returns true if key is valid. Uses cache of keys so doesn't have to access database each time. * If key not in cache then will reread keys from database in case it was just added. But won't do * so more than every few seconds since more frequent access could allow an app with a bad key to * cause the db to be queried to often putting an unneeded burden on the db. * * <p>Synchronized because can have simultaneous access and using a cache. * * @param key The key to investigate * @return True if key is valid */ public synchronized boolean isKeyValid(String key) { try { // If key is already in cache return true if (apiKeyCache.get(key) != null) return true; // Want to make sure a user doesn't overwhelm the system by // repeatedly trying to use an invalid key. So if the cache was // just updated a few x seconds ago then don't update it again // right now. Simply return false. if (System.currentTimeMillis() < lastTimeKeysReadIntoCache + lastTimeKeysReadLimitSec.getValue() * Time.MS_PER_SEC) return false; lastTimeKeysReadIntoCache = System.currentTimeMillis(); // Key wasn't in cache so update the cache in case it was added apiKeyCache.clear(); for (ApiKey apiKey : getApiKeys()) { apiKeyCache.put(apiKey.getKey(), apiKey); } return apiKeyCache.get(key) != null; } catch (Exception e) { logger.error("Problem checking key \"{}\" to see if valid.", key, e); return false; } }
/** * Called when AVL data is read from URL. Processes the JSON data and calls processAvlReport() for * each AVL report. */ @Override protected Collection<AvlReport> processData(InputStream in) throws Exception { // Get the JSON string containing the AVL data String jsonStr = getJsonString(in); try { // Convert JSON string to a JSON object JSONObject jsonObj = new JSONObject(jsonStr); // The JSON feed is really odd. Instead of having an // array of vehicles there is a separate JSON object // for each vehicle, and the name of the object is the // trip ID. Therefore need to get names of all the objects // so that each one can be accessed by name. String tripNames[] = JSONObject.getNames(jsonObj); // The return value for the method Collection<AvlReport> avlReportsReadIn = new ArrayList<AvlReport>(); // For each vehicle... for (String tripName : tripNames) { JSONObject v = jsonObj.getJSONObject(tripName); // Create the AvlReport from the JSON data String vehicleId = Integer.toString(v.getInt("vehicle_id")); Double lat = v.getDouble("vehicle_lat"); Double lon = v.getDouble("vehicle_lon"); // Guessing that the speed is in mph since getting values up to 58. // Therefore need to convert to m/s. float speed = (float) v.getDouble("vehicle_speed") * Geo.MPH_TO_MPS; // Not sure if bearing is the same as heading. float heading = (float) v.getDouble("vehicle_bearing"); // The time is really strange. It is off by 4-5 hours for some // strange reason. It appears to be 4 hours off during daylight // savings time but 5 hours during normal winter hours. Yikes! // Therefore using the parameter keolisFeedAvlTimeOffset to // specify the offset. long gpsTime = v.getLong("vehicle_timestamp") * Time.MS_PER_SEC + keolisFeedAvlTimeOffset.getValue() * Time.HOUR_IN_MSECS; // Create the AvlReport AvlReport avlReport = new AvlReport(vehicleId, gpsTime, lat, lon, speed, heading, "Keolis"); // Need to set assignment info separately. Unfortunately the // trip ID in the Keolis feed doesn't correspond exactly to the // trip IDs in the GTFS data. In Keolis feed it will be // something like "CR-FRAMINGHAM-Weekday-515" but in GTFS it will // be "CR-Worcester-CR-Weekday-Worcester-Jun15-515". Therefore // it is best to just use the trip short name, such as "515". String tripShortName = tripName.substring(tripName.lastIndexOf('-') + 1); // Actually set the assignment avlReport.setAssignment(tripShortName, AssignmentType.TRIP_SHORT_NAME); logger.debug("From KeolisAvlModule {}", avlReport); if (shouldProcessAvl) { avlReportsReadIn.add(avlReport); } } // Return all the AVL reports read in return avlReportsReadIn; } catch (JSONException e) { logger.error("Error parsing JSON. {}. {}", e.getMessage(), jsonStr, e); return new ArrayList<AvlReport>(); } }