public boolean logEvent( final IClient client, final String eventText, final InputStream logFileStream) { Integer id = executeWithConnection( new ConnectionExecuteFunction<Integer>() { public Integer execute(Connection c) throws SQLException { return logEvent(client, eventText, logFileStream, c); } }); if (id == null) { // DB error would have already been logged. return false; } boolean ok = false; if (logFileStream == null) { ok = true; } else { File userMailDir = client.getUserMailbox().getBaseDir(); File logFile = getEventLogFile(userMailDir, id.intValue()); try { FileUtils.copyStreamToFile(logFileStream, logFile); ok = true; } catch (IOException ioe) { m_logger .log("Can't write log file") .param(LoggingConsts.USER_ID, client.getUserId()) .param(LoggingConsts.FILENAME, logFile == null ? "" : logFile.getAbsolutePath()) .param(LoggingConsts.CONTENT, eventText) .error(ioe); } } return ok; }
public ClientSession createClientSession(IClientInfo client, String clientType) { // Both OE and BB share the session file. Don't stomp an existing file. if (client == null || !client.isConfigured()) { throw new IllegalStateException("Client not configured."); } clientType = clientType == null ? "" : clientType; ClientSession session = null; String tmpName = null; String targetName = null; try { File targetFile = getSessionFile(client.getLastActivationToken()); targetName = targetFile.getAbsolutePath(); if (targetFile.exists()) { session = new ClientSession(); session.read(targetFile); if (session.getLastActivationId() != client.getLastActivationId() || session.getUserId() != client.getUserId()) { // Existing session file found but it's clearly not ours. // A hash collision is improbable. If this occurs, its more likely to be a // bug. We can't safely rewrite the session file because another client // might later call getClientSession() and read our email. // This is a support concern. LogMessageGen lmg = new LogMessageGen(); lmg.setSubject("Found existing session, but the content is unexpected."); lmg.param(LoggingConsts.FILENAME, targetFile.getAbsolutePath()); m_logCategory.error(lmg.toString()); throw new ClientServiceException(""); } session.setActivationToken(client.getLastActivationToken()); } // targetFile already found. if (session == null) { UserAccount user = m_userService.getUserAccount(client.getCustomerId(), client.getUserId()); session = client.createSession(user); // What if the BB and OE create a session at the same time? // This ensures a unique filename. // The client who does the last renameTo() below wins the race // and that becomes the common session file. tmpName = targetFile.getAbsolutePath() + "_tmp_" + clientType; File tmpFile = new File(tmpName); session.write(tmpFile); // If 'targetFile' already exists it'll get clobbered. // Makes the session targetFile generation atomic. boolean ok = FileUtils.clobberingRename(tmpFile, targetFile); if (!ok) { throw new IOException("Rename failed"); } } // need to create session. } catch (Exception ex) { if (ex instanceof ClientServiceException) { // We already logged it. throw (ClientServiceException) ex; } LogMessageGen lmg = new LogMessageGen(); lmg.setSubject("Unable to generate session file."); lmg.param(LoggingConsts.USER_ID, client.getUserId()); lmg.param(LoggingConsts.TEMP_NAME, tmpName); lmg.param(LoggingConsts.FILENAME, targetName); m_logCategory.error(lmg.toString(), ex); throw new ClientServiceException(""); } return session; }
/** * Given the activationToken, return the filename that would be used for the session. Only returns * the File object; nothing hits the spindle. Note that an activationToken looks like a filename * because that's what it is :) * * @param activationToken * @return never null; but the file might not exist. */ private File getSessionFile(String activationToken) { FileUtils.validateForPathManipulationViolation(activationToken); return new File(getCacheBase(), "userdata/" + activationToken); }