text:
from EXOSIMS.Prototypes.SurveySimulation import SurveySimulation
import numpy as np
import astropy.units as u
import time

class ExoC_Scheduler(SurveySimulation):
    """Survey Simulation class template

    This class contains all variables and methods necessary to perform
    Survey Simulation Module calculations in exoplanet mission simulation.

    It inherits from the prototype SurveySimulation module.

    The ExoC_Scheduler is designed to perform detections as normal
    and characterizations in series.

    Args:
        **specs:
            user specified values

    """

    def __init__(self, **specs):

        SurveySimulation.__init__(self, **specs)

        OS = self.OpticalSystem
        SU = self.SimulatedUniverse

        allModes = OS.observingModes
        num_char_modes = len(
            list(filter(lambda mode: "spec" in mode["inst"]["name"], allModes))
        )
        self.fullSpectra = np.zeros((num_char_modes, SU.nPlans), dtype=int)
        self.partialSpectra = np.zeros((num_char_modes, SU.nPlans), dtype=int)

    def run_sim(self):
        """Performs the survey simulation"""

        OS = self.OpticalSystem
        TL = self.TargetList
        SU = self.SimulatedUniverse
        Obs = self.Observatory
        TK = self.TimeKeeping

        # TODO: start using this self.currentSep
        # set occulter separation if haveOcculter
        if OS.haveOcculter:
            self.currentSep = Obs.occulterSep

        # choose observing modes selected for detection (default marked with a flag)
        allModes = OS.observingModes
        det_mode = list(filter(lambda mode: mode["detectionMode"], allModes))[0]
        # and for characterization (default is first spectro/IFS mode)
        spectroModes = list(
            filter(lambda mode: "spec" in mode["inst"]["name"], allModes)
        )
        if np.any(spectroModes):
            char_modes = spectroModes
        # if no spectro mode, default char mode is first observing mode
        else:
            char_modes = [allModes[0]]

        # begin Survey, and loop until mission is finished
        log_begin = "OB%s: survey beginning." % (TK.OBnumber)
        self.logger.info(log_begin)
        self.vprint(log_begin)
        t0 = time.time()
        sInd = None
        ObsNum = 0
        while not TK.mission_is_over(OS, Obs, det_mode):

            # acquire the NEXT TARGET star index and create DRM
            old_sInd = sInd  # used to save sInd if returned sInd is None
            DRM, sInd, det_intTime, waitTime = self.next_target(sInd, det_mode)

            if sInd is not None:
                ObsNum += (
                    1  # we're making an observation so increment observation number
                )

                if OS.haveOcculter:
                    # advance to start of observation
                    # (add slew time for selected target)
                    _ = TK.advanceToAbsTime(TK.currentTimeAbs.copy() + waitTime)

                # beginning of observation, start to populate DRM
                DRM["star_ind"] = sInd
                DRM["star_name"] = TL.Name[sInd]
                DRM["arrival_time"] = TK.currentTimeNorm.to("day").copy()
                DRM["OB_nb"] = TK.OBnumber
                DRM["ObsNum"] = ObsNum
                pInds = np.where(SU.plan2star == sInd)[0]
                DRM["plan_inds"] = pInds.astype(int)
                log_obs = (
                    "  Observation #%s, star ind %s (of %s) with %s planet(s), "
                    + "mission time at Obs start: %s, exoplanetObsTime: %s"
                ) % (
                    ObsNum,
                    sInd,
                    TL.nStars,
                    len(pInds),
                    TK.currentTimeNorm.to("day").copy().round(2),
                    TK.exoplanetObsTime.to("day").copy().round(2),
                )
                self.logger.info(log_obs)
                self.vprint(log_obs)

                # PERFORM DETECTION and populate revisit list attribute
                (
                    detected,
                    det_fZ,
                    det_systemParams,
                    det_SNR,
                    FA,
                ) = self.observation_detection(sInd, det_intTime.copy(), det_mode)
                # update the occulter wet mass
                if OS.haveOcculter:
                    DRM = self.update_occulter_mass(
                        DRM, sInd, det_intTime.copy(), "det"
                    )
                # populate the DRM with detection results
                DRM["det_time"] = det_intTime.to("day")
                DRM["det_status"] = detected
                DRM["det_SNR"] = det_SNR
                DRM["det_fZ"] = det_fZ.to("1/arcsec2")
                DRM["det_params"] = det_systemParams
                DRM["det_mode"] = dict(det_mode)
                del DRM["det_mode"]["inst"], DRM["det_mode"]["syst"]

                # PERFORM CHARACTERIZATION and populate spectra list attribute
                DRM["char_info"] = []
                for mode_index, char_mode in enumerate(char_modes):
                    char_data = {}
                    if char_mode["SNR"] not in [0, np.inf]:
                        (
                            characterized,
                            char_fZ,
                            char_systemParams,
                            char_SNR,
                            char_intTime,
                        ) = self.observation_characterization(
                            sInd, char_mode, mode_index
                        )
                    else:
                        char_intTime = None
                        lenChar = len(pInds) + 1 if FA else len(pInds)
                        characterized = np.zeros(lenChar, dtype=float)
                        char_SNR = np.zeros(lenChar, dtype=float)
                        char_fZ = 0.0 / u.arcsec**2
                        char_systemParams = SU.dump_system_params(sInd)
                    assert char_intTime != 0, "Integration time can't be 0."
                    # update the occulter wet mass
                    if OS.haveOcculter and char_intTime is not None:
                        DRM = self.update_occulter_mass(DRM, sInd, char_intTime, "char")
                    # populate the DRM with characterization results
                    char_data["char_time"] = (
                        char_intTime.to("day") if char_intTime else 0.0 * u.day
                    )
                    char_data["char_status"] = (
                        characterized[:-1] if FA else characterized
                    )
                    char_data["char_SNR"] = char_SNR[:-1] if FA else char_SNR
                    char_data["char_fZ"] = char_fZ.to("1/arcsec2")
                    char_data["char_params"] = char_systemParams
                    # populate the DRM with FA results
                    char_data["FA_det_status"] = int(FA)
                    char_data["FA_char_status"] = characterized[-1] if FA else 0
                    char_data["FA_char_SNR"] = char_SNR[-1] if FA else 0.0
                    char_data["FA_char_fEZ"] = (
                        self.lastDetected[sInd, 1][-1] / u.arcsec**2
                        if FA
                        else 0.0 / u.arcsec**2
                    )
                    char_data["FA_char_dMag"] = (
                        self.lastDetected[sInd, 2][-1] if FA else 0.0
                    )
                    char_data["FA_char_WA"] = (
                        self.lastDetected[sInd, 3][-1] * u.arcsec
                        if FA
                        else 0.0 * u.arcsec
                    )

                    # populate the DRM with observation modes
                    char_data["char_mode"] = dict(char_mode)
                    del char_data["char_mode"]["inst"], char_data["char_mode"]["syst"]

                    char_data["exoplanetObsTime"] = TK.exoplanetObsTime.copy()
                    DRM["char_info"].append(char_data)

                # append result values to self.DRM
                self.DRM.append(DRM)

                # handle case of inf OBs and missionPortion < 1
                if np.isinf(TK.OBduration) and (TK.missionPortion < 1.0):
                    self.arbitrary_time_advancement(
                        TK.currentTimeNorm.to("day").copy() - DRM["arrival_time"]
                    )

            else:  # sInd == None
                sInd = old_sInd  # Retain the last observed star
                if (
                    TK.currentTimeNorm.copy() >= TK.OBendTimes[TK.OBnumber]
                ):  # currentTime is at end of OB
                    # Conditional Advance To Start of Next OB
                    if not TK.mission_is_over(
                        OS, Obs, det_mode
                    ):  # as long as the mission is not over
                        TK.advancetToStartOfNextOB()  # Advance To Start of Next OB
                elif waitTime is not None:
                    # CASE 1: Advance specific wait time
                    _ = TK.advanceToAbsTime(TK.currentTimeAbs.copy() + waitTime)
                    self.vprint("waitTime is not None")
                else:
                    startTimes = (
                        TK.currentTimeAbs.copy() + np.zeros(TL.nStars) * u.d
                    )  # Start Times of Observations
                    observableTimes = Obs.calculate_observableTimes(
                        TL,
                        np.arange(TL.nStars),
                        startTimes,
                        self.koMaps,
                        self.koTimes,
                        det_mode,
                    )[0]
                    # CASE 2 If There are no observable targets for the
                    # rest of the mission
                    # Are there any stars coming out of keepout before end of mission?
                    if (
                        observableTimes[
                            (
                                TK.missionFinishAbs.copy().value * u.d
                                > observableTimes.value * u.d
                            )
                            * (
                                observableTimes.value * u.d
                                >= TK.currentTimeAbs.copy().value * u.d
                            )
                        ].shape[0]
                    ) == 0:
                        self.vprint(
                            (
                                "No Observable Targets for Remainder of mission at "
                                "currentTimeNorm = {}".format(TK.currentTimeNorm)
                            )
                        )
                        # Manually advancing time to mission end
                        TK.currentTimeNorm = TK.missionLife
                        TK.currentTimeAbs = TK.missionFinishAbs
                    else:
                        # CASE 3 nominal wait time if at least 1 target is still in
                        # list and observable
                        # TODO: ADD ADVANCE TO WHEN FZMIN OCURS
                        inds1 = np.arange(TL.nStars)[
                            observableTimes.value * u.d
                            > TK.currentTimeAbs.copy().value * u.d
                        ]
                        # apply intTime filter
                        inds2 = np.intersect1d(self.intTimeFilterInds, inds1)
                        # apply revisit Filter #NOTE this means stars you added to
                        # the revisit list
                        inds3 = self.revisitFilter(
                            inds2, TK.currentTimeNorm.copy() + self.dt_max.to(u.d)
                        )
                        self.vprint(
                            "Filtering %d stars from advanceToAbsTime"
                            % (TL.nStars - len(inds3))
                        )
                        oTnowToEnd = observableTimes[inds3]
                        if not oTnowToEnd.value.shape[0] == 0:
                            # there is at least one observableTime between now and
                            # the end of the mission
                            tAbs = np.min(oTnowToEnd)  # advance to that observable time
                        else:
                            tAbs = (
                                TK.missionStart + TK.missionLife
                            )  # advance to end of mission
                        tmpcurrentTimeNorm = TK.currentTimeNorm.copy()
                        # Advance Time to this time OR start of next OB following
                        # this time
                        _ = TK.advanceToAbsTime(tAbs)
                        self.vprint(
                            (
                                "No Observable Targets a currentTimeNorm = {:.2f} "
                                "Advanced To currentTimeNorm = {:.2f}"
                            ).format(
                                tmpcurrentTimeNorm.to("day").value,
                                TK.currentTimeNorm.to("day").value,
                            )
                        )
        else:  # TK.mission_is_over()
            dtsim = (time.time() - t0) * u.s
            log_end = (
                "Mission complete: no more time available.\n"
                + "Simulation duration: %s.\n" % dtsim.astype("int")
                + "Results stored in SurveySimulation.DRM (Design Reference Mission)."
            )
            self.logger.info(log_end)
            self.vprint(log_end)

    def observation_characterization(self, sInd, mode, mode_index):
        """Finds if characterizations are possible and relevant information

        Args:
            sInd (integer):
                Integer index of the star of interest
            mode (dict):
                Selected observing mode for characterization

        Returns:
            characterized (integer list):
                Characterization status for each planet orbiting the observed
                target star including False Alarm if any, where 1 is full spectrum,
                -1 partial spectrum, and 0 not characterized
            fZ (astropy Quantity):
                Surface brightness of local zodiacal light in units of 1/arcsec2
            systemParams (dict):
                Dictionary of time-dependant planet properties averaged over the
                duration of the integration
            SNR (float ndarray):
                Characterization signal-to-noise ratio of the observable planets.
                Defaults to None.
            intTime (astropy Quantity):
                Selected star characterization time in units of day. Defaults to None.

        """

        OS = self.OpticalSystem
        ZL = self.ZodiacalLight
        TL = self.TargetList
        SU = self.SimulatedUniverse
        Obs = self.Observatory
        TK = self.TimeKeeping

        # find indices of planets around the target
        pInds = np.where(SU.plan2star == sInd)[0]

        # get the detected status, and check if there was a FA
        det = self.lastDetected[sInd, 0]
        FA = len(det) == len(pInds) + 1
        if FA:
            pIndsDet = np.append(pInds, -1)[det]
        else:
            pIndsDet = pInds[det]

        # initialize outputs, and check if there's anything (planet or FA)
        # to characterize
        characterized = np.zeros(len(det), dtype=int)
        fZ = 0.0 / u.arcsec**2.0
        systemParams = SU.dump_system_params(
            sInd
        )  # write current system params by default
        SNR = np.zeros(len(det))
        intTime = None
        if len(det) == 0:  # nothing to characterize
            return characterized, fZ, systemParams, SNR, intTime

        # look for last detected planets that have not been fully characterized
        if not (FA):  # only true planets, no FA
            tochar = self.fullSpectra[mode_index][pIndsDet] == 0
        else:  # mix of planets and a FA
            truePlans = pIndsDet[:-1]
            tochar = np.append((self.fullSpectra[mode_index][truePlans] == 0), True)

        # 1/ find spacecraft orbital START position including overhead time,
        # and check keepout angle
        if np.any(tochar):
            # start times
            startTime = (
                TK.currentTimeAbs.copy() + mode["syst"]["ohTime"] + Obs.settlingTime
            )
            startTimeNorm = (
                TK.currentTimeNorm.copy() + mode["syst"]["ohTime"] + Obs.settlingTime
            )
            # planets to characterize
            koTimeInd = np.where(np.round(startTime.value) - self.koTimes.value == 0)[
                0
            ][
                0
            ]  # find indice where koTime is startTime[0]
            # wherever koMap is 1, the target is observable
            koMap = self.koMaps[mode["syst"]["name"]]
            tochar[tochar] = koMap[sInd][koTimeInd]

        # 2/ if any planet to characterize, find the characterization times
        # at the detected fEZ, dMag, and WA
        if np.any(tochar):
            fZ = ZL.fZ(Obs, TL, sInd, startTime, mode)
            fEZ = self.lastDetected[sInd, 1][det][tochar] / u.arcsec**2
            dMag = self.lastDetected[sInd, 2][det][tochar]
            WA = self.lastDetected[sInd, 3][det][tochar] * u.arcsec
            intTimes = np.zeros(len(tochar)) * u.day
            intTimes[tochar] = OS.calc_intTime(TL, sInd, fZ, fEZ, dMag, WA, mode)
            # add a predetermined margin to the integration times
            intTimes = intTimes * (1.0 + self.charMargin)
            # apply time multiplier
            totTimes = intTimes * (mode["timeMultiplier"])
            # end times
            endTimes = startTime + totTimes
            endTimesNorm = startTimeNorm + totTimes
            # planets to characterize
            tochar = (
                (totTimes > 0)
                & (totTimes <= OS.intCutoff)
                & (endTimesNorm <= TK.OBendTimes[TK.OBnumber])
            )
        # 3/ is target still observable at the end of any char time?
        if np.any(tochar) and Obs.checkKeepoutEnd:
            koTimeInds = np.zeros(len(endTimes.value[tochar]), dtype=int)
            # find index in koMap where each endTime is closest to koTimes
            for t, endTime in enumerate(endTimes.value[tochar]):
                if endTime > self.koTimes.value[-1]:
                    # case where endTime exceeds largest koTimes element
                    endTimeInBounds = np.where(
                        np.floor(endTime) - self.koTimes.value == 0
                    )[0]
                    koTimeInds[t] = (
                        endTimeInBounds[0] if endTimeInBounds.size != 0 else -1
                    )
                else:
                    koTimeInds[t] = np.where(
                        np.round(endTime) - self.koTimes.value == 0
                    )[0][
                        0
                    ]  # find indice where koTime is endTimes[0]
            tochar[tochar] = [koMap[sInd][koT] if koT >= 0 else 0 for koT in koTimeInds]

        # 4/ if yes, allocate the overhead time, and perform the characterization
        # for the maximum char time
        if np.any(tochar):
            # Save Current Time before attempting time allocation
            currentTimeNorm = TK.currentTimeNorm.copy()
            currentTimeAbs = TK.currentTimeAbs.copy()

            # Allocate Time
            intTime = np.max(intTimes[tochar])
            extraTime = intTime * (mode["timeMultiplier"] - 1.0)  # calculates extraTime
            success = TK.allocate_time(
                intTime + extraTime + mode["syst"]["ohTime"] + Obs.settlingTime, True
            )  # allocates time
            if not (success):  # Time was not successfully allocated
                # Identical to when "if char_mode['SNR'] not in [0, np.inf]:"
                # in run_sim()
                char_intTime = None
                lenChar = len(pInds) + 1 if FA else len(pInds)
                characterized = np.zeros(lenChar, dtype=float)
                char_SNR = np.zeros(lenChar, dtype=float)
                char_fZ = 0.0 / u.arcsec**2
                char_systemParams = SU.dump_system_params(sInd)
                return characterized, char_fZ, char_systemParams, char_SNR, char_intTime

            pIndsChar = pIndsDet[tochar]
            log_char = "   - Charact. planet inds %s (%s/%s detected)" % (
                pIndsChar,
                len(pIndsChar),
                len(pIndsDet),
            )
            self.logger.info(log_char)
            self.vprint(log_char)

            # SNR CALCULATION:
            # first, calculate SNR for observable planets (without false alarm)
            planinds = pIndsChar[:-1] if pIndsChar[-1] == -1 else pIndsChar
            SNRplans = np.zeros(len(planinds))
            if len(planinds) > 0:
                # initialize arrays for SNR integration
                fZs = np.zeros(self.ntFlux) / u.arcsec**2.0
                systemParamss = np.empty(self.ntFlux, dtype="object")
                Ss = np.zeros((self.ntFlux, len(planinds)))
                Ns = np.zeros((self.ntFlux, len(planinds)))
                # integrate the signal (planet flux) and noise
                dt = intTime / float(self.ntFlux)
                timePlus = (
                    Obs.settlingTime.copy() + mode["syst"]["ohTime"].copy()
                )  # accounts for the time since the current time
                for i in range(self.ntFlux):
                    # allocate first half of dt
                    timePlus += dt / 2.0
                    # calculate current zodiacal light brightness
                    fZs[i] = ZL.fZ(Obs, TL, sInd, currentTimeAbs + timePlus, mode)[0]
                    # propagate the system to match up with current time
                    SU.propag_system(
                        sInd, currentTimeNorm + timePlus - self.propagTimes[sInd]
                    )
                    self.propagTimes[sInd] = currentTimeNorm + timePlus
                    # save planet parameters
                    systemParamss[i] = SU.dump_system_params(sInd)
                    # calculate signal and noise (electron count rates)
                    Ss[i, :], Ns[i, :] = self.calc_signal_noise(
                        sInd, planinds, dt, mode, fZ=fZs[i]
                    )
                    # allocate second half of dt
                    timePlus += dt / 2.0

                # average output parameters
                fZ = np.mean(fZs)
                systemParams = {
                    key: sum([systemParamss[x][key] for x in range(self.ntFlux)])
                    / float(self.ntFlux)
                    for key in sorted(systemParamss[0])
                }
                # calculate planets SNR
                S = Ss.sum(0)
                N = Ns.sum(0)
                SNRplans[N > 0] = S[N > 0] / N[N > 0]
                # allocate extra time for timeMultiplier

            # if only a FA, just save zodiacal brightness in the middle of the
            # integration
            else:
                totTime = intTime * (mode["timeMultiplier"])
                fZ = ZL.fZ(Obs, TL, sInd, currentTimeAbs + totTime / 2.0, mode)[0]

            # calculate the false alarm SNR (if any)
            SNRfa = []
            if pIndsChar[-1] == -1:
                fEZ = self.lastDetected[sInd, 1][-1] / u.arcsec**2.0
                dMag = self.lastDetected[sInd, 2][-1]
                WA = self.lastDetected[sInd, 3][-1] * u.arcsec
                C_p, C_b, C_sp = OS.Cp_Cb_Csp(TL, sInd, fZ, fEZ, dMag, WA, mode)
                S = (C_p * intTime).decompose().value
                N = np.sqrt((C_b * intTime + (C_sp * intTime) ** 2.0).decompose().value)
                SNRfa = S / N if N > 0.0 else 0.0

            # save all SNRs (planets and FA) to one array
            SNRinds = np.where(det)[0][tochar]
            SNR[SNRinds] = np.append(SNRplans, SNRfa)

            # now, store characterization status: 1 for full spectrum,
            # -1 for partial spectrum, 0 for not characterized
            char = SNR >= mode["SNR"]
            # initialize with full spectra
            characterized = char.astype(int)
            WAchar = self.lastDetected[sInd, 3][char] * u.arcsec
            # find the current WAs of characterized planets
            WAs = systemParams["WA"]
            if FA:
                WAs = np.append(WAs, self.lastDetected[sInd, 3][-1] * u.arcsec)
            # check for partial spectra
            IWA_max = mode["IWA"] * (1.0 + mode["BW"] / 2.0)
            OWA_min = mode["OWA"] * (1.0 - mode["BW"] / 2.0)
            char[char] = (WAchar < IWA_max) | (WAchar > OWA_min)
            characterized[char] = -1
            # encode results in spectra lists (only for planets, not FA)
            charplans = characterized[:-1] if FA else characterized
            self.fullSpectra[mode_index][pInds[charplans == 1]] += 1
            self.partialSpectra[mode_index][pInds[charplans == -1]] += 1

        return characterized.astype(int), fZ, systemParams, SNR, intTime


text:
package com.google.gerrit.server.query.change;

import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeAccess;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.query.IntPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryRewriter;
import com.google.gerrit.server.query.RewritePredicate;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.inject.Inject;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.name.Named;

import java.util.Collection;

public class ChangeQueryRewriter extends QueryRewriter<ChangeData> {
  private static final QueryRewriter.Definition<ChangeData, ChangeQueryRewriter> mydef =
      new QueryRewriter.Definition<ChangeData, ChangeQueryRewriter>(
          ChangeQueryRewriter.class, new ChangeQueryBuilder(
              new ChangeQueryBuilder.Arguments( //
                  new InvalidProvider<ReviewDb>(), //
                  new InvalidProvider<ChangeQueryRewriter>(), //
                  null, null, null, null, null, null, null, null, null, null), null));

  private final Provider<ReviewDb> dbProvider;

  @Inject
  ChangeQueryRewriter(Provider<ReviewDb> dbProvider) {
    super(mydef);
    this.dbProvider = dbProvider;
  }

  @Override
  public Predicate<ChangeData> and(Collection<? extends Predicate<ChangeData>> l) {
    return hasSource(l) ? new AndSource(l) : super.and(l);
  }

  @Override
  public Predicate<ChangeData> or(Collection<? extends Predicate<ChangeData>> l) {
    return hasSource(l) ? new OrSource(l) : super.or(l);
  }

  @Rewrite("-status:open")
  @NoCostComputation
  public Predicate<ChangeData> r00_notOpen() {
    return ChangeStatusPredicate.closed(dbProvider);
  }

  @Rewrite("-status:closed")
  @NoCostComputation
  public Predicate<ChangeData> r00_notClosed() {
    return ChangeStatusPredicate.open(dbProvider);
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("-status:merged")
  public Predicate<ChangeData> r00_notMerged() {
    return or(ChangeStatusPredicate.open(dbProvider),
        new ChangeStatusPredicate(dbProvider, Change.Status.ABANDONED));
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("-status:abandoned")
  public Predicate<ChangeData> r00_notAbandoned() {
    return or(ChangeStatusPredicate.open(dbProvider),
        new ChangeStatusPredicate(dbProvider, Change.Status.MERGED));
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("sortkey_before:z A=(age:*)")
  public Predicate<ChangeData> r00_ageToSortKey(@Named("A") AgePredicate a) {
    String cut = ChangeUtil.sortKey(a.getCut(), Integer.MAX_VALUE);
    return and(new SortKeyPredicate.Before(dbProvider, cut), a);
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(limit:*) B=(limit:*)")
  public Predicate<ChangeData> r00_smallestLimit(
      @Named("A") IntPredicate<ChangeData> a,
      @Named("B") IntPredicate<ChangeData> b) {
    return a.intValue() <= b.intValue() ? a : b;
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(sortkey_before:*) B=(sortkey_before:*)")
  public Predicate<ChangeData> r00_oldestSortKey(
      @Named("A") SortKeyPredicate.Before a,
      @Named("B") SortKeyPredicate.Before b) {
    return a.getValue().compareTo(b.getValue()) <= 0 ? a : b;
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(sortkey_after:*) B=(sortkey_after:*)")
  public Predicate<ChangeData> r00_newestSortKey(
      @Named("A") SortKeyPredicate.After a, @Named("B") SortKeyPredicate.After b) {
    return a.getValue().compareTo(b.getValue()) >= 0 ? a : b;
  }

  @Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectOpenPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectOpenPrev(p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() //
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:open P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectOpenNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectOpenNext(p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() //
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:merged P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectMergedPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedPrev(Change.Status.MERGED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:merged P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectMergedNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedNext(Change.Status.MERGED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:abandoned P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectAbandonedPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedPrev(Change.Status.ABANDONED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:abandoned P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectAbandonedNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedNext(Change.Status.ABANDONED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:open S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byOpenPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allOpenPrev(key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
      }
    };
  }

  @Rewrite("status:open S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byOpenNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allOpenNext(key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:merged S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byMergedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byMergedPrev", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedPrev(Change.Status.MERGED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:merged S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byMergedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byMergedNext", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedNext(Change.Status.MERGED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:abandoned S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byAbandonedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byAbandonedPrev", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedPrev(Change.Status.ABANDONED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:abandoned S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byAbandonedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byAbandonedNext", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedNext(Change.Status.ABANDONED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byClosedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return or(r20_byMergedPrev(s, l), r20_byAbandonedPrev(s, l));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byClosedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return or(r20_byMergedNext(s, l), r20_byAbandonedNext(s, l));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:open O=(owner:*)")
  public Predicate<ChangeData> r25_byOwnerOpen(
      @Named("O") final OwnerPredicate o) {
    return new ChangeSource(50) {
      {
        init("r25_byOwnerOpen", o);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byOwnerOpen(o.getAccountId());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && o.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed O=(owner:*)")
  public Predicate<ChangeData> r25_byOwnerClosed(
      @Named("O") final OwnerPredicate o) {
    return new ChangeSource(5000) {
      {
        init("r25_byOwnerClosed", o);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byOwnerClosedAll(o.getAccountId());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isClosed() && o.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("O=(owner:*)")
  public Predicate<ChangeData> r26_byOwner(@Named("O") OwnerPredicate o) {
    return or(r25_byOwnerOpen(o), r25_byOwnerClosed(o));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:open R=(reviewer:*)")
  public Predicate<ChangeData> r30_byReviewerOpen(
      @Named("R") final ReviewerPredicate r) {
    return new Source() {
      {
        init("r30_byReviewerOpen", r);
      }

      @Override
      public ResultSet<ChangeData> read() throws OrmException {
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
            .patchSetApprovals().openByUser(r.getAccountId()));
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        Change change = cd.change(dbProvider);
        return change != null && change.getStatus().isOpen() && r.match(cd);
      }

      @Override
      public int getCardinality() {
        return 50;
      }

      @Override
      public int getCost() {
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed R=(reviewer:*)")
  public Predicate<ChangeData> r30_byReviewerClosed(
      @Named("R") final ReviewerPredicate r) {
    return new Source() {
      {
        init("r30_byReviewerClosed", r);
      }

      @Override
      public ResultSet<ChangeData> read() throws OrmException {
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
            .patchSetApprovals().closedByUserAll(r.getAccountId()));
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        Change change = cd.change(dbProvider);
        return change != null && change.getStatus().isClosed() && r.match(cd);
      }

      @Override
      public int getCardinality() {
        return 5000;
      }

      @Override
      public int getCost() {
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("R=(reviewer:*)")
  public Predicate<ChangeData> r31_byReviewer(
      @Named("R") final ReviewerPredicate r) {
    return or(r30_byReviewerOpen(r), r30_byReviewerClosed(r));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:submitted")
  public Predicate<ChangeData> r99_allSubmitted() {
    return new ChangeSource(50) {
      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.allSubmitted();
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.SUBMITTED;
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("P=(project:*)")
  public Predicate<ChangeData> r99_byProject(
      @Named("P") final ProjectPredicate p) {
    return new ChangeSource(1000000) {
      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byProject(p.getValueKey());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return p.match(cd);
      }
    };
  }

  private static boolean hasSource(Collection<? extends Predicate<ChangeData>> l) {
    for (Predicate<ChangeData> p : l) {
      if (p instanceof ChangeDataSource) {
        return true;
      }
    }
    return false;
  }

  private abstract static class Source extends RewritePredicate<ChangeData>
      implements ChangeDataSource {
    @Override
    public boolean hasChange() {
      return false;
    }
  }

  private abstract class ChangeSource extends Source {
    private final int cardinality;

    ChangeSource(int card) {
      this.cardinality = card;
    }

    abstract ResultSet<Change> scan(ChangeAccess a) throws OrmException;

    @Override
    public ResultSet<ChangeData> read() throws OrmException {
      return ChangeDataResultSet.change(scan(dbProvider.get().changes()));
    }

    @Override
    public boolean hasChange() {
      return true;
    }

    @Override
    public int getCardinality() {
      return cardinality;
    }

    @Override
    public int getCost() {
      return ChangeCosts.cost(ChangeCosts.CHANGES_SCAN, getCardinality());
    }
  }

  private abstract class PaginatedSource extends ChangeSource implements
      Paginated {
    private final String startKey;
    private final int limit;

    PaginatedSource(int card, String start, int lim) {
      super(card);
      this.startKey = start;
      this.limit = lim;
    }

    @Override
    public int limit() {
      return limit;
    }

    @Override
    ResultSet<Change> scan(ChangeAccess a) throws OrmException {
      return scan(a, startKey, limit);
    }

    @Override
    public ResultSet<ChangeData> restart(ChangeData last) throws OrmException {
      return ChangeDataResultSet.change(scan(dbProvider.get().changes(), //
          last.change(dbProvider).getSortKey(), //
          limit));
    }

    abstract ResultSet<Change> scan(ChangeAccess a, String key, int limit)
        throws OrmException;
  }

  private static final class InvalidProvider<T> implements Provider<T> {
    @Override
    public T get() {
      throw new OutOfScopeException("Not available at init");
    }
  }
}

redpajama_set_name: RedPajamaGithub


text:
// .NAME vtkOBJExporter - export a scene into Wavefront format.
// .SECTION Description
// vtkOBJExporter is a concrete subclass of vtkExporter that writes wavefront
// .OBJ files in ASCII form. It also writes out a mtl file that contains the
// material properties. The filenames are derived by appending the .obj and
// .mtl suffix onto the user specified FilePrefix.
//
// .SECTION See Also
// vtkExporter

#ifndef __vtkOBJExporter_h
#define __vtkOBJExporter_h

#include "vtkIOExportModule.h" // For export macro
#include "vtkExporter.h"

class vtkActor;

class VTKIOEXPORT_EXPORT vtkOBJExporter : public vtkExporter
{
public:
  static vtkOBJExporter *New();
  vtkTypeMacro(vtkOBJExporter,vtkExporter);
  void PrintSelf(ostream& os, vtkIndent indent);

  // Description:
  // Specify the prefix of the files to write out. The resulting filenames
  // will have .obj and .mtl appended to them.
  vtkSetStringMacro(FilePrefix);
  vtkGetStringMacro(FilePrefix);

protected:
  vtkOBJExporter();
  ~vtkOBJExporter();

  void WriteData();
  void WriteAnActor(vtkActor *anActor, FILE *fpObj, FILE *fpMat, int &id);
  char *FilePrefix;
private:
  vtkOBJExporter(const vtkOBJExporter&);  // Not implemented.
  void operator=(const vtkOBJExporter&);  // Not implemented.
};

#endif


text:
package org.openbaton.nfvo.vnfm_reg.tasks;

import java.util.concurrent.ExecutionException;
import org.openbaton.catalogue.mano.common.Event;
import org.openbaton.catalogue.mano.record.NetworkServiceRecord;
import org.openbaton.catalogue.mano.record.Status;
import org.openbaton.catalogue.mano.record.VirtualNetworkFunctionRecord;
import org.openbaton.catalogue.nfvo.Action;
import org.openbaton.catalogue.nfvo.messages.Interfaces.NFVMessage;
import org.openbaton.catalogue.nfvo.messages.OrVnfmStartStopMessage;
import org.openbaton.exceptions.BadFormatException;
import org.openbaton.exceptions.NotFoundException;
import org.openbaton.nfvo.vnfm_reg.VnfmRegister;
import org.openbaton.nfvo.vnfm_reg.tasks.abstracts.AbstractTask;
import org.openbaton.vnfm.interfaces.sender.VnfmSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

/** Created by lto on 06/08/15. */
@Service
@Scope("prototype")
@ConfigurationProperties(prefix = "nfvo.start")
public class ModifyTask extends AbstractTask {

  @Autowired private VnfmRegister vnfmRegister;

  private String ordered;

  @Override
  protected NFVMessage doWork() throws Exception, BadFormatException {
    description = "All the configuration scripts setting up dependencies were correctly executed";
    virtualNetworkFunctionRecord.setStatus(Status.INACTIVE);
    NetworkServiceRecord nsr =
        networkServiceRecordRepository.findFirstById(
            virtualNetworkFunctionRecord.getParent_ns_id());
    log.info("MODIFY finished for VNFR: " + virtualNetworkFunctionRecord.getName());
    log.trace(
        "VNFR ("
            + virtualNetworkFunctionRecord.getId()
            + ") received hibernate version = "
            + virtualNetworkFunctionRecord.getHbVersion());
    setHistoryLifecycleEvent();
    saveVirtualNetworkFunctionRecord();
    log.trace(
        "VNFR ("
            + virtualNetworkFunctionRecord.getId()
            + ") current hibernate version is: "
            + virtualNetworkFunctionRecord.getHbVersion());
    log.debug(
        "VNFR "
            + virtualNetworkFunctionRecord.getName()
            + " Status is: "
            + virtualNetworkFunctionRecord.getStatus());
    boolean allVnfrInInactive = allVnfrInInactive(nsr);
    log.debug(
        "Are all VNFR of NSR (" + nsr.getId() + ") in an INACTIVE state? " + allVnfrInInactive);

    log.trace("Is ordered execution of VNFs enabled? " + Boolean.parseBoolean(ordered));
    if (ordered != null && Boolean.parseBoolean(ordered)) {
      if (allVnfrInInactive) {
        VirtualNetworkFunctionRecord nextToCallStart =
            getNextToCallStart(virtualNetworkFunctionRecord);
        if (nextToCallStart != null) {
          vnfmManager.removeVnfrName(
              virtualNetworkFunctionRecord.getParent_ns_id(), nextToCallStart.getName());
          sendStart(nextToCallStart);
        }
        log.info("Not found next VNFR to call start");
      } else {
        log.debug(
            "After MODIFY of "
                + virtualNetworkFunctionRecord.getName()
                + ", not calling start to next VNFR because not all VNFRs are in state INACTIVE");
      }
    } else {
      sendStart(virtualNetworkFunctionRecord);
    }
    return null;
  }

  private void sendStart(VirtualNetworkFunctionRecord virtualNetworkFunctionRecord)
      throws NotFoundException, BadFormatException, ExecutionException, InterruptedException {
    VnfmSender vnfmSender;
    log.info("Calling START to: " + virtualNetworkFunctionRecord.getName() + " after MODIFY");
    vnfmSender =
        this.getVnfmSender(
            vnfmRegister.getVnfm(virtualNetworkFunctionRecord.getEndpoint()).getEndpointType());
    vnfStateHandler.executeAction(
        vnfmSender.sendCommand(
            new OrVnfmStartStopMessage(virtualNetworkFunctionRecord, null, Action.START),
            vnfmRegister.getVnfm(virtualNetworkFunctionRecord.getEndpoint())));
  }

  @Override
  public boolean isAsync() {
    return true;
  }

  public void setOrdered(String ordered) {
    this.ordered = ordered;
  }

  @Override
  protected void setEvent() {
    event = Event.CONFIGURE.name();
  }

  @Override
  protected void setDescription() {
    description = "The Modify task was executed and the dependencies set up";
  }
}


text:
=head1 NAME

Mail::SpamAssassin::Plugin::DCC - perform DCC check of messages

=head1 SYNOPSIS

  loadplugin Mail::SpamAssassin::Plugin::DCC

  full DCC_CHECK	eval:check_dcc()
  full DCC_CHECK_50_79	eval:check_dcc_reputation_range('50','79')

=head1 DESCRIPTION

The DCC or Distributed Checksum Clearinghouse is a system of servers
collecting and counting checksums of millions of mail messages.
The counts can be used by SpamAssassin to detect and filter spam.

See http://www.dcc-servers.net/dcc/ for more information about DCC.

Note that DCC is disabled by default in C<v310.pre> because its use requires
software that is not distributed with SpamAssassin and that has license
restrictions for certain commercial uses.
See the DCC license at http://www.dcc-servers.net/dcc/LICENSE for details.

Enable it by uncommenting the "loadplugin Mail::SpamAssassin::Plugin::DCC"
confdir/v310.pre or by adding this line to your local.pre.  It might also
be necessary to install a DCC package, port, rpm, or equivalent from your
operating system distributor or a tarball from the primary DCC source
at http://www.dcc-servers.net/dcc/#download
See also http://www.dcc-servers.net/dcc/INSTALL.html

=head1 TAGS

The following tags are added to the set, available for use in reports,
header fields, other plugins, etc.:

  _DCCB_    DCC server ID in X-DCC-*-Metrics header field name
  _DCCR_    X-DCC-*-Metrics header field body
  _DCCREP_  DCC Reputation or percent bulk mail (0..100) from
	      commercial DCC software

=cut

package Mail::SpamAssassin::Plugin::DCC;

use strict;
use warnings;
use bytes;
use re 'taint';

use Mail::SpamAssassin::Plugin;
use Mail::SpamAssassin::Logger;
use Mail::SpamAssassin::Timeout;
use Mail::SpamAssassin::Util qw(untaint_var untaint_file_path
                                proc_status_ok exit_status_str);
use Errno qw(ENOENT EACCES);
use IO::Socket;

use vars qw(@ISA);
@ISA = qw(Mail::SpamAssassin::Plugin);

sub new {
  my $class = shift;
  my $mailsaobject = shift;

  $class = ref($class) || $class;
  my $self = $class->SUPER::new($mailsaobject);
  bless ($self, $class);

  # are network tests enabled?
  if ($mailsaobject->{local_tests_only}) {
    $self->{use_dcc} = 0;
    dbg("dcc: local tests only, disabling DCC");
  }
  else {
    dbg("dcc: network tests on, registering DCC");
  }

  $self->register_eval_rule("check_dcc");
  $self->register_eval_rule("check_dcc_reputation_range");

  $self->set_config($mailsaobject->{conf});

  return $self;
}

sub set_config {
  my($self, $conf) = @_;
  my @cmds;

=head1 USER OPTIONS

=over 4

=item use_dcc (0|1)		(default: 1)

Whether to use DCC, if it is available.

=cut

  push(@cmds, {
    setting => 'use_dcc',
    default => 1,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_BOOL,
  });

=item dcc_body_max NUMBER

=item dcc_fuz1_max NUMBER

=item dcc_fuz2_max NUMBER

Sets how often a message's body/fuz1/fuz2 checksum must have been reported
to the DCC server before SpamAssassin will consider the DCC check hit.
C<999999> is DCC's MANY count.

The default is C<999999> for all these options.

=item dcc_rep_percent NUMBER

Only the commercial DCC software provides DCC Reputations.  A DCC Reputation
is the percentage of bulk mail received from the last untrusted relay in the
path taken by a mail message as measured by all commercial DCC installations.
See http://www.rhyolite.com/dcc/reputations.html
You C<must> whitelist your trusted relays or MX servers with MX or
MXDCC lines in /var/dcc/whiteclnt as described in the main DCC man page
to avoid seeing your own MX servers as sources of bulk mail.
See http://www.dcc-servers.net/dcc/dcc-tree/dcc.html#White-and-Blacklists
The default is C<90>.

=cut

  push (@cmds, {
    setting => 'dcc_body_max',
    default => 999999,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC
  },
  {
    setting => 'dcc_fuz1_max',
    default => 999999,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC
  },
  {
    setting => 'dcc_fuz2_max',
    default => 999999,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC
  },
  {
    setting => 'dcc_rep_percent',
    default => 90,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC
  });

=back

=head1 ADMINISTRATOR OPTIONS

=over 4

=item dcc_timeout n		(default: 8)

How many seconds you wait for DCC to complete, before scanning continues
without the DCC results. A numeric value is optionally suffixed by a
time unit (s, m, h, d, w, indicating seconds (default), minutes, hours,
days, weeks).

=cut

  push (@cmds, {
    setting => 'dcc_timeout',
    is_admin => 1,
    default => 8,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_DURATION,
  });

=item dcc_home STRING

This option tells SpamAssassin where to find the dcc homedir.
If not specified, try to use the locally configured directory
from the C<cdcc homedir> command.
Try /var/dcc if that command fails.

=cut

  push (@cmds, {
    setting => 'dcc_home',
    is_admin => 1,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
    code => sub {
      my ($self, $key, $value, $line) = @_;
      if (!defined $value || $value eq '') {
	return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
      }
      $value = untaint_file_path($value);
      my $stat_errn = stat($value) ? 0 : 0+$!;
      if ($stat_errn != 0 || !-d _) {
	my $msg = $stat_errn == ENOENT ? "does not exist"
		  : !-d _ ? "is not a directory" : "not accessible: $!";
	info("config: dcc_home \"$value\" $msg");
	return $Mail::SpamAssassin::Conf::INVALID_VALUE;
      }

      $self->{dcc_home} = $value;
    }
  });

=item dcc_dccifd_path STRING

This option tells SpamAssassin where to find the dccifd socket instead
of a local Unix socket named C<dccifd> in the C<dcc_home> directory.
If a socket is specified or found, use it instead of C<dccproc>.

If specifed, C<dcc_dccifd_path> is the absolute path of local Unix socket
or an INET socket specified as C<[Host]:Port> or C<Host:Port>.
Host can be an IPv4 or IPv6 address or a host name
Port is a TCP port number. The brackets are required for an IPv6 address.

The default is C<undef>.

=cut

  push (@cmds, {
    setting => 'dcc_dccifd_path',
    is_admin => 1,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
    code => sub {
      my ($self, $key, $value, $line) = @_;

      if (!defined $value || $value eq '') {
	return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
      }

      local($1,$2,$3);
      if ($value =~ m{^ (?: \[ ([^\]]*) \] | ([^:]*) ) : ([^:]*) \z}sx) {
	my $host = untaint_var(defined $1 ? $1 : $2);
	my $port = untaint_var($3);
	if (!$host) {
	  info("config: missing or bad host name in dcc_dccifd_path '$value'");
	  return $Mail::SpamAssassin::Conf::INVALID_VALUE;
	}
	if (!$port || $port !~ /^\d+\z/ || $port < 1 || $port > 65535) {
	  info("config: bad TCP port number in dcc_dccifd_path '$value'");
	  return $Mail::SpamAssassin::Conf::INVALID_VALUE;
	}

	$self->{dcc_dccifd_host} = $host;
	$self->{dcc_dccifd_port} = $port;
	if ($host !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/) {
	  # remember to try IPv6 if we can with a host name or non-IPv4 address
	  $self->{dcc_dccifd_IPv6} = eval { require IO::Socket::INET6 };
	}
	dbg("config: dcc_dccifd_path set to [%s]:%s", $host, $port);

      } else {
	# assume a unix socket
	if ($value !~ m{^/}) {
	  info("config: dcc_dccifd_path '$value' is not an absolute path");
	  # return $Mail::SpamAssassin::Conf::INVALID_VALUE;  # abort or accept?
	}
	$value = untaint_file_path($value);

	$self->{dcc_dccifd_socket} = $value;
	dbg("config: dcc_dccifd_path set to local socket %s", $value);
	dbg("dcc: dcc_dccifd_path set to local socket %s", $value);
      }

      $self->{dcc_dccifd_path_raw} = $value;
    }
  });

=item dcc_path STRING

Where to find the C<dccproc> client program instead of relying on SpamAssassin
to find it in the current PATH or C<dcc_home/bin>. This must often be set,
because the current PATH is cleared by I<taint mode> in the Perl interpreter,

If a C<dccifd> socket is found in C<dcc_home> or specified explicitly
with C<dcc_dccifd_path>, use the C<dccifd(8)> interface instead of C<dccproc>.

The default is C<undef>.

=cut

  push (@cmds, {
    setting => 'dcc_path',
    is_admin => 1,
    default => undef,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
    code => sub {
      my ($self, $key, $value, $line) = @_;
      if (!defined $value || $value eq '') {
	return $Mail::SpamAssassin::Conf::MISSING_REQUIRED_VALUE;
      }
      $value = untaint_file_path($value);
      if (!-x $value) {
	info("config: dcc_path '$value' is not executable");
	return $Mail::SpamAssassin::Conf::INVALID_VALUE;
      }

      $self->{dcc_path} = $value;
    }
  });

=item dcc_options options

Specify additional options to the dccproc(8) command.  Only
characters in the range [0-9A-Za-z ,._/-] are allowed for security reasons.

The default is C<undef>.

=cut

  push (@cmds, {
    setting => 'dcc_options',
    is_admin => 1,
    default => undef,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
    code => sub {
      my ($self, $key, $value, $line) = @_;
      if ($value !~ m{^([0-9A-Za-z ,._/-]+)$}) {
	info("config: dcc_options '$value' contains impermissible characters");
	return $Mail::SpamAssassin::Conf::INVALID_VALUE;
      }
      $self->{dcc_options} = $1;
    }
  });

=item dccifd_options options

Specify additional options to send to the dccifd daemon with
the ASCII protocol described on the dccifd(8) man page.
Only characters in the range [0-9A-Za-z ,._/-] are allowed for security reasons.

The default is C<undef>.

=cut

  push (@cmds, {
    setting => 'dccifd_options',
    is_admin => 1,
    default => undef,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_STRING,
    code => sub {
      my ($self, $key, $value, $line) = @_;
      if ($value !~ m{^([0-9A-Za-z ,._/-]+)$}) {
	info("config: dccifd_options '$value' contains impermissible characters");
	return $Mail::SpamAssassin::Conf::INVALID_VALUE;
      }
      $self->{dccifd_options} = $1;
    }
  });

=item dcc_learn_score n		(default: undef)

Report messages with total scores this much larger than the
SpamAssassin spam threshold to DCC as spam.

=cut

  push (@cmds, {
    setting => 'dcc_learn_score',
    is_admin => 1,
    default => undef,
    type => $Mail::SpamAssassin::Conf::CONF_TYPE_NUMERIC,
  });

  $conf->{parser}->register_commands(\@cmds);
}

sub ck_dir {
  my ($self, $dir, $tgt, $src) = @_;

  $dir = untaint_file_path($dir);
  if (!stat($dir)) {
    my $dir_errno = 0+$!;
    if ($dir_errno == ENOENT) {
      dbg("dcc: $tgt $dir from $src does not exist");
    } else {
      dbg("dcc: $tgt $dir from $src is not accessible: $!");
    }
    return;
  }
  if (!-d _) {
    dbg("dcc: $tgt $dir from $src is not a directory");
    return;
  }

  $self->{main}->{conf}->{$tgt} = $dir;
  dbg("dcc: use '$tgt $dir' from $src");
}

sub find_dcc_home {
  my ($self) = @_;

  # just once
  return if defined $self->{dcc_version};
  $self->{dcc_version} = '?';

  my $conf = $self->{main}->{conf};

  # Get the DCC software version for talking to dccifd and formating the
  # dccifd options and the built-in DCC homedir.  Use -q to prevent delays.
  my $cdcc_home;
  my $cdcc = $self->dcc_pgm_path('cdcc');
  my $cmd = '-qV homedir libexecdir';
  if ($cdcc && open(CDCC, "$cdcc $cmd 2>&1 |")) {
    my $cdcc_output = do { local $/ = undef; <CDCC> };
    close CDCC;

    $cdcc_output =~ s/\n/ /g;		# everything in 1 line for debugging
    dbg("dcc: `%s %s` reports '%s'", $cdcc, $cmd, $cdcc_output);
    $self->{dcc_version} = ($cdcc_output =~ /^(\d+\.\d+\.\d+)/) ? $1 : '';
    $cdcc_home = ($cdcc_output =~ /\s+homedir=(\S+)/) ? $1 : '';
    if ($cdcc_output =~ /\s+libexecdir=(\S+)/) {
      $self->ck_dir($1, 'dcc_libexec', 'cdcc');
    }
  }

  # without a home, try the homedir from cdcc
  if (!$conf->{dcc_home} && $cdcc_home) {
    $self->ck_dir($cdcc_home, 'dcc_home', 'cdcc');
  }
  # finally fall back to /var/dcc
  if (!$conf->{dcc_home}) {
    $self->ck_dir($conf->{dcc_home} = '/var/dcc', 'dcc_home', 'default')
  }

  # fall back to $conf->{dcc_home}/libexec or /var/dcc/libexec for dccsight
  if (!$conf->{dcc_libexec}) {
    $self->ck_dir($conf->{dcc_home} . '/libexec', 'dcc_libexec', 'dcc_home');
  }
  if (!$conf->{dcc_libexec}) {
    $self->ck_dir('/var/dcc/libexec', 'dcc_libexec', 'dcc_home');
  }

  # format options for dccifd
  my $opts = ($conf->{dccifd_options} || '') . "\n";
  if ($self->{dcc_version} =~ /\d+\.(\d+)\.(\d+)$/ &&
      ($1 < 3 || ($1 == 3 && $2 < 123))) {
    if ($1 < 3 || ($1 == 3 && $2 < 50)) {
      info("dcc: DCC version $self->{dcc_version} is years old, ".
           "obsolete, and likely to cause problems.  ".
           "See http://www.dcc-servers.net/dcc/old-versions.html");
    }
    $self->{dccifd_lookup_options} = "header " . $opts;
    $self->{dccifd_report_options} = "header spam " . $opts;
  } else {
    # dccifd after version 1.2.123 understands "cksums" and "no-grey"
    $self->{dccifd_lookup_options} = "cksums grey-off " . $opts;
    $self->{dccifd_report_options} = "header spam grey-off " . $opts;
  }
}

sub dcc_pgm_path {
  my ($self, $pgm) = @_;
  my $pgmpath;
  my $conf = $self->{main}->{conf};

  $pgmpath = $conf->{dcc_path};
  if (defined $pgmpath && $pgmpath ne '') {
    # accept explicit setting for dccproc
    return $pgmpath if $pgm eq 'dccproc';
    # try adapting it for cdcc and everything else
    if ($pgmpath =~ s{[^/]+\z}{$pgm}s) {
      $pgmpath = untaint_file_path($pgmpath);
      if (-x $pgmpath) {
        dbg("dcc: dcc_pgm_path, found %s in dcc_path: %s", $pgm,$pgmpath);
        return $pgmpath;
      }
    }
  }

  $pgmpath = Mail::SpamAssassin::Util::find_executable_in_env_path($pgm);
  if (defined $pgmpath) {
    dbg("dcc: dcc_pgm_path, found %s in env.path: %s", $pgm,$pgmpath);
    return $pgmpath;
  }

  # try dcc_home/bin, dcc_libexec, and some desperate last attempts
  foreach my $dir (!defined $conf->{dcc_home} ? () : $conf->{dcc_home}.'/bin',
                   $conf->{dcc_libexec},
                   '/usr/local/bin', '/usr/local/dcc', '/var/dcc') {
    next unless defined $dir;
    $pgmpath = $dir . '/' . $pgm;
    if (-x $pgmpath) {
      dbg("dcc: dcc_pgm_path, found %s in %s: %s", $pgm,$dir,$pgmpath);
      return $pgmpath;
    }
  }

  return;
}

sub is_dccifd_available {
  my ($self) = @_;
  my $conf = $self->{main}->{conf};

  # dccifd remains available until it breaks
  return $self->{dccifd_available} if $self->{dccifd_available};

  # deal with configured INET socket
  if (defined $conf->{dcc_dccifd_host}) {
    dbg("dcc: dccifd is available via INET socket [%s]:%s",
	$conf->{dcc_dccifd_host}, $conf->{dcc_dccifd_port});
    return ($self->{dccifd_available} = 1);
  }

  # the first time here, compute a default local socket based on DCC home
  # from self->find_dcc_home() called elsewhere
  my $sockpath = $conf->{dcc_dccifd_socket};
  if (!$sockpath) {
      if ($conf->{dcc_dccifd_path_raw}) {
	$sockpath = $conf->{dcc_dccifd_path_raw};
      } else {
	$sockpath = "$conf->{dcc_home}/dccifd";
      }
      $conf->{dcc_dccifd_socket} = $sockpath;
  }

  # check the socket every time because it can appear and disappear
  return ($self->{dccifd_available} = 1) if (-S $sockpath && -w _ && -r _);

  dbg("dcc: dccifd is not available; no r/w socket at %s", $sockpath);
  return ($self->{dccifd_available} = 0);
}

sub is_dccproc_available {
  my ($self) = @_;
  my $conf = $self->{main}->{conf};

  # dccproc remains (un)available so check only once
  return $self->{dccproc_available} if  defined $self->{dccproc_available};

  my $dccproc = $conf->{dcc_path};
  if (!defined $dccproc || $dccproc eq '') {
    $dccproc = $self->dcc_pgm_path('dccproc');
    $conf->{dcc_path} = $dccproc;
    if (!$dccproc || ! -x $dccproc) {
      dbg("dcc: dccproc is not available: no dccproc executable found");
      return ($self->{dccproc_available} = 0);
    }
  }

  dbg("dcc: %s is available", $conf->{dcc_path});
  return ($self->{dccproc_available} = 1);
}

sub dccifd_connect {
  my($self, $tag) = @_;
  my $conf = $self->{main}->{conf};
  my $sockpath = $conf->{dcc_dccifd_socket};
  my $sock;

  if (defined $sockpath) {
    $sock = IO::Socket::UNIX->new(Type => SOCK_STREAM, Peer => $sockpath);
    if ($sock) {
      dbg("$tag connected to local socket $sockpath");
      return $sock;
    }
    $self->{dccifd_available} = 0;
    info("$tag failed to connect to local socket $sockpath");
    return $sock
  }

  # must be TCP/IP
  my $host = $conf->{dcc_dccifd_host};
  my $port = $conf->{dcc_dccifd_port};

  if ($conf->{dcc_dccifd_IPv6}) {
    # try IPv6 if we can with a host name or non-IPv4 address
    dbg("$tag connecting to inet6 socket [$host]:$port");
    $sock = IO::Socket::INET6->new(
		  Proto => 'tcp', PeerAddr => $host, PeerPort => $port);
    # fall back to IPv4 if that failed
  }
  if (!$sock) {
    dbg("$tag connecting to inet4 socket [$host]:$port");
    $sock = IO::Socket::INET->new(
		Proto => 'tcp', PeerAddr => $host, PeerPort => $port);
  }

  info("failed to connect to [$host]:$port : $!") if !$sock;
  return $sock;
}

# check for dccifd every time in case enough uses of dccproc starts dccifd
sub get_dcc_interface {
  my ($self) = @_;
  my $conf = $self->{main}->{conf};

  if (!$conf->{use_dcc}) {
    $self->{dcc_disabled} = 1;
    return;
  }

  $self->find_dcc_home();
  if (!$self->is_dccifd_available() && !$self->is_dccproc_available()) {
    dbg("dcc: dccifd and dccproc are not available");
    $self->{dcc_disabled} = 1;
  }

  $self->{dcc_disabled} = 0;
}

sub dcc_query {
  my ($self, $permsgstatus, $fulltext) = @_;

  $permsgstatus->{dcc_checked} = 1;

  if (!$self->{main}->{conf}->{use_dcc}) {
    dbg("dcc: DCC is not available: use_dcc is 0");
    return;
  }

  # initialize valid tags
  $permsgstatus->{tag_data}->{DCCB} = "";
  $permsgstatus->{tag_data}->{DCCR} = "";
  $permsgstatus->{tag_data}->{DCCREP} = "";

  if ($$fulltext eq '') {
    dbg("dcc: empty message; skipping dcc check");
    return;
  }

  if ($permsgstatus->get('ALL') =~ /^(X-DCC-.*-Metrics:.*)$/m) {
    $permsgstatus->{dcc_raw_x_dcc} = $1;
    # short-circuit if there is already a X-DCC header with value of
    # "bulk" from an upstream DCC check
    # require "bulk" because then at least one body checksum will be "many"
    # and so we know the X-DCC header is not forged by spammers
    return if $permsgstatus->{dcc_raw_x_dcc} =~ / bulk /;
  }

  my $timer = $self->{main}->time_method("check_dcc");

  $self->get_dcc_interface();
  return if $self->{dcc_disabled};

  my $envelope = $permsgstatus->{relays_external}->[0];
  ($permsgstatus->{dcc_raw_x_dcc},
   $permsgstatus->{dcc_cksums}) = $self->ask_dcc("dcc:", $permsgstatus,
						 $fulltext, $envelope);
}

sub check_dcc {
  my ($self, $permsgstatus, $full) = @_;
  my $conf = $self->{main}->{conf};

  $self->dcc_query($permsgstatus, $full)  if !$permsgstatus->{dcc_checked};

  my $x_dcc = $permsgstatus->{dcc_raw_x_dcc};
  return 0  if !defined $x_dcc || $x_dcc eq '';

  if ($x_dcc =~ /^X-DCC-(.*)-Metrics: (.*)$/) {
    $permsgstatus->set_tag('DCCB', $1);
    $permsgstatus->set_tag('DCCR', $2);
  }
  $x_dcc =~ s/many/999999/ig;
  $x_dcc =~ s/ok\d?/0/ig;

  my %count = (body => 0, fuz1 => 0, fuz2 => 0, rep => 0);
  if ($x_dcc =~ /\bBody=(\d+)/) {
    $count{body} = $1+0;
  }
  if ($x_dcc =~ /\bFuz1=(\d+)/) {
    $count{fuz1} = $1+0;
  }
  if ($x_dcc =~ /\bFuz2=(\d+)/) {
    $count{fuz2} = $1+0;
  }
  if ($x_dcc =~ /\brep=(\d+)/) {
    $count{rep}  = $1+0;
  }
  if ($count{body} >= $conf->{dcc_body_max} ||
      $count{fuz1} >= $conf->{dcc_fuz1_max} ||
      $count{fuz2} >= $conf->{dcc_fuz2_max} ||
      $count{rep}  >= $conf->{dcc_rep_percent})
  {
    dbg(sprintf("dcc: listed: BODY=%s/%s FUZ1=%s/%s FUZ2=%s/%s REP=%s/%s",
		map { defined $_ ? $_ : 'undef' } (
		  $count{body}, $conf->{dcc_body_max},
		  $count{fuz1}, $conf->{dcc_fuz1_max},
		  $count{fuz2}, $conf->{dcc_fuz2_max},
		  $count{rep},  $conf->{dcc_rep_percent})
		));
    return 1;
  }
  return 0;
}

sub check_dcc_reputation_range {
  my ($self, $permsgstatus, $fulltext, $min, $max) = @_;

  # this is called several times per message, so parse the X-DCC header once
  my $dcc_rep = $permsgstatus->{dcc_rep};
  if (!defined $dcc_rep) {
    $self->dcc_query($permsgstatus, $fulltext)  if !$permsgstatus->{dcc_checked};
    my $x_dcc = $permsgstatus->{dcc_raw_x_dcc};
    if (defined $x_dcc && $x_dcc =~ /\brep=(\d+)/) {
      $dcc_rep = $1+0;
      $permsgstatus->set_tag('DCCREP', $dcc_rep);
    } else {
      $dcc_rep = -1;
    }
    $permsgstatus->{dcc_rep} = $dcc_rep;
  }

  # no X-DCC header or no reputation in the X-DCC header, perhaps for lack
  # of data in the DCC Reputation server
  return 0 if $dcc_rep < 0;

  # cover the entire range of reputations if not told otherwise
  $min = 0   if !defined $min;
  $max = 100 if !defined $max;

  my $result = $dcc_rep >= $min && $dcc_rep <= $max ? 1 : 0;
  dbg("dcc: dcc_rep %s, min %s, max %s => result=%s",
      $dcc_rep, $min, $max, $result?'YES':'no');
  return $result;
}

# get the X-DCC header line and save the checksums from dccifd or dccproc
sub parse_dcc_response {
  my ($self, $resp) = @_;
  my ($raw_x_dcc, $cksums);

  # The first line is the header we want.  It uses SMTP folded whitespace
  # if it is long.  The folded whitespace is always a single \t.
  chomp($raw_x_dcc = shift @$resp);
  my $v;
  while (($v = shift @$resp) && $v =~ s/^\t(.+)\s*\n/ $1/) {
    $raw_x_dcc .= $v;
  }

  # skip the "reported:" line between the X-DCC header and any checksums
  # remove ':' to avoid a bug in versions 1.3.115 - 1.3.122 in dccsight
  # with the length of "Message-ID:"
  $cksums = '';
  while (($v = shift @$resp) && $v =~ s/^([^:]*):/$1/) {
    $cksums .= $v;
  }

  return ($raw_x_dcc, $cksums);
}

sub ask_dcc {
  my ($self, $tag, $permsgstatus, $fulltext, $envelope) = @_;
  my $conf = $self->{main}->{conf};
  my ($pgm, $err, $sock, $pid, @resp);
  my ($client, $clientname, $helo, $opts);

  $permsgstatus->enter_helper_run_mode();

  my $timeout = $conf->{dcc_timeout};
  my $timer = Mail::SpamAssassin::Timeout->new(
	  { secs => $timeout, deadline => $permsgstatus->{master_deadline} });

  $err = $timer->run_and_catch(sub {
    local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };

    # prefer dccifd to dccproc
    if ($self->{dccifd_available}) {
      $pgm = 'dccifd';

      $sock = $self->dccifd_connect($tag);
      if (!$sock) {
	$self->{dccifd_available} = 0;
	die("dccproc not available") if (!$self->is_dccproc_available());

	# fall back on dccproc if the socket is an orphan from
	# a killed dccifd daemon or some other obvious (no timeout) problem
	dbg("$tag fall back on dccproc");
      }
    }

    if ($self->{dccifd_available}) {

      # send the options and other parameters to the daemon
      $client = $envelope->{ip};
      $clientname = $envelope->{rdns};
      if (!defined $client) {
	$client = '';
      } else {
	$client .= ("\r" . $clientname) if defined $clientname;
      }
      $helo = $envelope->{helo} || '';
      if ($tag ne "dcc:") {
	$opts = $self->{dccifd_report_options}
      } else {
	$opts = $self->{dccifd_lookup_options};
	if (defined $permsgstatus->{dcc_raw_x_dcc}) {
	  # only query if there is an X-DCC header
	  $opts =~ s/grey-off/grey-off query/;
	}
      }

      $sock->print($opts)	   or die "failed write options\n";
      $sock->print($client . "\n") or die "failed write SMTP client\n";
      $sock->print($helo . "\n")   or die "failed write HELO value\n";
      $sock->print("\n")	   or die "failed write sender\n";
      $sock->print("unknown\n\n")  or die "failed write 1 recipient\n";
      $sock->print($$fulltext)     or die "failed write mail message\n";
      $sock->shutdown(1) or die "failed socket shutdown: $!";

      $sock->getline()   or die "failed read status\n";
      $sock->getline()   or die "failed read multistatus\n";

      @resp = $sock->getlines();
      die "failed to read dccifd response\n" if !@resp;

    } else {
      $pgm = 'dccproc';
      # use a temp file -- open2() is unreliable, buffering-wise, under spamd
      # first ensure that we do not hit a stray file from some other filter.
      $permsgstatus->delete_fulltext_tmpfile();
      my $tmpf = $permsgstatus->create_fulltext_tmpfile($fulltext);

      my $path = $conf->{dcc_path};
      $opts = $conf->{dcc_options};
      my @opts = !defined $opts ? () : split(' ',$opts);
      untaint_var(\@opts);
      unshift(@opts, '-w', 'whiteclnt');
      $client = $envelope->{ip};
      if ($client) {
	unshift(@opts, '-a', untaint_var($client));
      } else {
	# get external relay IP address from Received: header if not available
	unshift(@opts, '-R');
      }
      if ($tag eq "dcc:") {
	# query instead of report if there is an X-DCC header from upstream
	unshift(@opts, '-Q') if defined $permsgstatus->{dcc_raw_x_dcc};
      } else {
	# learn or report spam
	unshift(@opts, '-t', 'many');
      }

      defined $path  or die "no dcc_path found\n";
      dbg("$tag opening pipe to " .
	  join(' ', $path, "-C", "-x", "0", @opts, "<$tmpf"));

      $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
		$tmpf, 1, $path, "-C", "-x", "0", @opts);
      $pid or die "DCC: $!\n";

      # read+split avoids a Perl I/O bug (Bug 5985)
      my($inbuf,$nread,$resp); $resp = '';
      while ( $nread=read(DCC,$inbuf,8192) ) { $resp .= $inbuf }
      defined $nread  or die "error reading from pipe: $!";
      @resp = split(/^/m, $resp, -1);  undef $resp;

      my $errno = 0;  close DCC or $errno = $!;
      proc_status_ok($?,$errno)
	  or info("$tag [%s] finished: %s", $pid, exit_status_str($?,$errno));

      die "failed to read X-DCC header from dccproc\n" if !@resp;
    }
  });

  if (defined $pgm && $pgm eq 'dccproc') {
    if (defined(fileno(*DCC))) {	# still open
      if ($pid) {
	if (kill('TERM',$pid)) {
	  dbg("$tag killed stale dccproc process [$pid]")
	} else {
	  dbg("$tag killing dccproc process [$pid] failed: $!")
	}
      }
      my $errno = 0;  close(DCC) or $errno = $!;
      proc_status_ok($?,$errno) or info("$tag [%s] dccproc terminated: %s",
					$pid, exit_status_str($?,$errno));
    }
  }

  $permsgstatus->leave_helper_run_mode();

  if ($timer->timed_out()) {
    dbg("$tag $pgm timed out after $timeout seconds");
    return (undef, undef);
  }

  if ($err) {
    chomp $err;
    info("$tag $pgm failed: $err\n");
    return (undef, undef);
  }

  my ($raw_x_dcc, $cksums) = $self->parse_dcc_response(\@resp);
  if (!defined $raw_x_dcc || $raw_x_dcc !~ /^X-DCC/) {
    info("$tag instead of X-DCC header, $pgm returned '$raw_x_dcc'");
    return (undef, undef);
  }
  dbg("$tag $pgm responded with '$raw_x_dcc'");
  return ($raw_x_dcc, $cksums);
}

# tell DCC server that the message is spam according to SpamAssassin
sub check_post_learn {
  my ($self, $options) = @_;

  # learn only if allowed
  return if $self->{learn_disabled};
  my $conf = $self->{main}->{conf};
  if (!$conf->{use_dcc}) {
    $self->{learn_disabled} = 1;
    return;
  }
  my $learn_score = $conf->{dcc_learn_score};
  if (!defined $learn_score || $learn_score eq '') {
    dbg("dcc: DCC learning not enabled by dcc_learn_score");
    $self->{learn_disabled} = 1;
    return;
  }

  # and if SpamAssassin concluded that the message is spam
  # worse than our threshold
  my $permsgstatus = $options->{permsgstatus};
  if ($permsgstatus->is_spam()) {
    my $score = $permsgstatus->get_score();
    my $required_score = $permsgstatus->get_required_score();
    if ($score < $required_score + $learn_score) {
      dbg("dcc: score=%d required_score=%d dcc_learn_score=%d",
	  $score, $required_score, $learn_score);
      return;
    }
  }

  # and if we checked the message
  return if (!defined $permsgstatus->{dcc_raw_x_dcc});

  # and if the DCC server thinks it was not spam
  if ($permsgstatus->{dcc_raw_x_dcc} !~ /\b(Body|Fuz1|Fuz2)=\d/) {
    dbg("dcc: already known as spam; no need to learn");
    return;
  }

  # dccsight is faster than dccifd or dccproc if we have checksums,
  #   which we do not have with dccifd before 1.3.123
  my $old_cksums = $permsgstatus->{dcc_cksums};
  return if ($old_cksums && $self->dccsight_learn($permsgstatus, $old_cksums));

  # Fall back on dccifd or dccproc without saved checksums or dccsight.
  # get_dcc_interface() was called when the message was checked

  # is getting the full text this way kosher?  Is get_pristine() public?
  my $fulltext = $permsgstatus->{msg}->get_pristine();
  my $envelope = $permsgstatus->{relays_external}->[0];
  my ($raw_x_dcc, $cksums) = $self->ask_dcc("dcc: learn:", $permsgstatus,
					    \$fulltext, $envelope);
  dbg("dcc: learned as spam") if defined $raw_x_dcc;
}

sub dccsight_learn {
  my ($self, $permsgstatus, $old_cksums) = @_;
  my ($raw_x_dcc, $new_cksums);

  return 0 if !$old_cksums;

  my $dccsight = $self->dcc_pgm_path('dccsight');
  if (!$dccsight) {
    info("dcc: cannot find dccsight") if $dccsight eq '';
    return 0;
  }

  $permsgstatus->enter_helper_run_mode();

  # use a temp file here -- open2() is unreliable, buffering-wise, under spamd
  # ensure that we do not hit a stray file from some other filter.
  $permsgstatus->delete_fulltext_tmpfile();
  my $tmpf = $permsgstatus->create_fulltext_tmpfile(\$old_cksums);
  my $pid;

  my $timeout = $self->{main}->{conf}->{dcc_timeout};
  my $timer = Mail::SpamAssassin::Timeout->new(
	   { secs => $timeout, deadline => $permsgstatus->{master_deadline} });
  my $err = $timer->run_and_catch(sub {
    local $SIG{PIPE} = sub { die "__brokenpipe__ignore__\n" };

    dbg("dcc: opening pipe to %s",
	join(' ', $dccsight, "-t", "many", "<$tmpf"));

    $pid = Mail::SpamAssassin::Util::helper_app_pipe_open(*DCC,
	    $tmpf, 1, $dccsight, "-t", "many");
    $pid or die "$!\n";

    # read+split avoids a Perl I/O bug (Bug 5985)
    my($inbuf,$nread,$resp); $resp = '';
    while ( $nread=read(DCC,$inbuf,8192) ) { $resp .= $inbuf }
    defined $nread  or die "error reading from pipe: $!";
    my @resp = split(/^/m, $resp, -1);  undef $resp;

    my $errno = 0;  close DCC or $errno = $!;
    proc_status_ok($?,$errno)
	  or info("dcc: [%s] finished: %s", $pid, exit_status_str($?,$errno));

    die "dcc: failed to read learning response\n" if !@resp;

    ($raw_x_dcc, $new_cksums) = $self->parse_dcc_response(\@resp);
  });

  if (defined(fileno(*DCC))) {	  # still open
    if ($pid) {
      if (kill('TERM',$pid)) {
	dbg("dcc: killed stale dccsight process [$pid]")
      } else {
	dbg("dcc: killing stale dccsight process [$pid] failed: $!") }
    }
    my $errno = 0;  close(DCC) or $errno = $!;
    proc_status_ok($?,$errno) or info("dcc: dccsight [%s] terminated: %s",
				      $pid, exit_status_str($?,$errno));
  }
  $permsgstatus->delete_fulltext_tmpfile();
  $permsgstatus->leave_helper_run_mode();

  if ($timer->timed_out()) {
    dbg("dcc: dccsight timed out after $timeout seconds");
    return 0;
  }

  if ($err) {
    chomp $err;
    info("dcc: dccsight failed: $err\n");
    return 0;
  }

  if ($raw_x_dcc) {
    dbg("dcc: learned response: %s", $raw_x_dcc);
    return 1;
  }

  return 0;
}

sub plugin_report {
  my ($self, $options) = @_;

  return if $options->{report}->{options}->{dont_report_to_dcc};
  $self->get_dcc_interface();
  return if $self->{dcc_disabled};

  # get the metadata from the message so we can report the external relay
  $options->{msg}->extract_message_metadata($options->{report}->{main});
  my $envelope = $options->{msg}->{metadata}->{relays_external}->[0];
  my ($raw_x_dcc, $cksums) = $self->ask_dcc("reporter:", $options->{report},
					    $options->{text}, $envelope);

  if (defined $raw_x_dcc) {
    $options->{report}->{report_available} = 1;
    info("reporter: spam reported to DCC");
    $options->{report}->{report_return} = 1;
  } else {
    info("reporter: could not report spam to DCC");
  }
}

1;


text:
<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    </head>
    <body>
    </body>

    <script>
        (function() {
            function callPompt() {
                var name = prompt("Enter your name","");
                if(confirm(name)){
                   alert(name);
                   console.log(name);
                   document.write(name);
                }
                else {
                   callPompt();
                }

            } callPompt();
        })();

    </script>
</html>


text:
package org.apache.lucene.analysis.pattern;

import org.apache.lucene.analysis.BaseTokenStreamTestCase;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.TokenStream;

import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

/**
 * Simple tests to ensure this factory is working
 */
public class TestPatternReplaceFilterFactory extends BaseTokenStreamTestCase {

  public void testReplaceAll() throws Exception {
    String input = "aabfooaabfooabfoob ab caaaaaaaaab";
    PatternReplaceFilterFactory factory = new PatternReplaceFilterFactory();
    Map<String,String> args = new HashMap<String,String>();
    args.put("pattern", "a*b");
    args.put("replacement", "-");
    factory.init(args);
    TokenStream ts = factory.create
            (new MockTokenizer(new StringReader(input), MockTokenizer.WHITESPACE, false));

    assertTokenStreamContents(ts,
        new String[] { "-foo-foo-foo-", "-", "c-" });
  }
}


text:
define( [
 	"/uiplugin/backbone-ext/src/backbone-ext.js",
	"./gdrive.js"
], function( Backbone) {
	var exports = this;//{};

	exports.DashboardView = Backbone.DashboardView.extend({
		afterInitialize:function(){
			var self = this;

			var dashboardarguments = {dashboard:true};
			if(self.options.uriarguments && self.options.uriarguments.length > 2){
				self.options.uri=self.options.uri  +'/' + self.options.uriarguments[1];
				self.options.dashboardsourceurl = '/api/dashboardservice/'+ self.options.uriarguments[1];
			} else{
				self.options.dashboardsourceurl = Backbone.Utils.appendToUrl(('/api/displayfilter/search'||defaulturl), dashboardarguments);
			}
		}, dashboardsource:function(defaulturl){
			var self = this;

			return self.options.dashboardsourceurl||defaulturl;
		}
	});

	return exports;
});


text:
Setup KVM on Ubuntu

- http://hinish.com/?p=338

Setup network bridge

`/etc/network/interfaces` need to comment out the original wired link, and setup br0 with it
```
# The primary network interface
# auto p2p1
# iface p2p1 inet dhcp

auto br0
iface br0 inet dhcp

bridge_ports p2p1

```
Create br0 and attach tap0 to it
```
brctl addbr br0
brctl addif br0 p2p1
openvpn --mktun --dev tap0
ifconfig tap0 0.0.0.0 up
brctl addif br0 tap0
```

Then when start the qemu, use this for network
```
-net nic,macaddr=00:15:5D:CC:E7:BF -net tap,ifname=tap0,script=no
```


text:
class NullAdapter
  def success(*args)
  end

  def created(*args)
  end

  def params
    {}
  end
end


text:
if Reset == True:
    agent_pts = []
    agent_crvs = []
    agents_v = []

    if Initial_Boids:
        Agents_run(Initial_Boids)
        counter += 1
        print counter
    else:
        Initial_Boids = Agents_Init(Agents_N)
        print len(agent_pts),"flocking agents"
    Agents_pos = agent_pts
    Trails = agent_crvs
    Agents_View = agents_v

elif Reset == False:
    print("Idle")
    Initial_Boids= []
    counter = 0


text:
package net.thunderklaus

import sbt._
import sbt.Keys._
import java.io.File
import com.earldouglas.xsbtwebplugin.PluginKeys._
import com.earldouglas.xsbtwebplugin.Container

object GwtPlugin extends Plugin {

  lazy val Gwt = config("gwt") extend (Compile)

  val gwtModules = TaskKey[Seq[String]]("gwt-modules")
  val gwtCompile = TaskKey[Int]("gwt-compile", "Runs the GWT compiler")
  val gwtForceCompile = TaskKey[Boolean]("gwt-force-compile", "Always recompile gwt modules")
  val gwtDevMode = TaskKey[Unit]("gwt-devmode", "Runs the GWT devmode shell")
  val gwtSuperDevMode = TaskKey[Int]("gwt-superdev", "Runs the GWT super devmode code server")
  val gwtVersion = SettingKey[String]("gwt-version")
  val gwtTemporaryPath = SettingKey[File]("gwt-temporary-path")
  val gwtDevTemporaryPath = SettingKey[File]("gwt-dev-temporary-path")
  val gwtWebappPath = SettingKey[File]("gwt-webapp-path")
  val gaeSdkPath = SettingKey[Option[String]]("gae-sdk-path")
  val gwtBindAddress = SettingKey[Option[String]]("gwt-bind-address")

  var gwtModule: Option[String] = None
//  val gwtSetModule = Command.single("gwt-set-module") { (state, arg) =>
//    Project.runTask(gwtModules, state) match {
//      case Some(Value(mods)) => {
//        gwtModule = mods.find(_.toLowerCase.contains(arg.toLowerCase))
//        gwtModule match {
//          case Some(m) => println("gwt-devmode will run: " + m)
//          case None => println("No match for '" + arg + "' in " + mods.mkString(", "))
//        }
//      }
//      case _ => None
//    }
//    state
//  }

  lazy val gwtSettings: Seq[Setting[_]] = com.earldouglas.xsbtwebplugin.WebPlugin.webSettings ++ gwtOnlySettings

  lazy val gwtOnlySettings: Seq[Setting[_]] = inConfig(Gwt)(Defaults.configSettings) ++ Seq(

    managedClasspath in Gwt <<= (managedClasspath in Compile, update) map {
      (cp, up) => cp ++ Classpaths.managedJars(Provided, Set("src"), up)
    },
    unmanagedClasspath in Gwt := { (unmanagedClasspath in Compile).value },
    gwtTemporaryPath <<= (target) { (target) =>
      val t = target / "gwt"
      t.mkdirs()
      t
    },
    gwtDevTemporaryPath <<= (target) { (target) =>
      val t = target / "gwt-dev"
      t.mkdirs()
      t
    },
    gwtBindAddress := None,
    gwtWebappPath <<= (baseDirectory) { (bd) => bd / "war" },
    gwtVersion := "2.5.1",
    gwtForceCompile := false,
    gaeSdkPath := None,
    libraryDependencies <++= gwtVersion{ v =>
      val s = Seq(
        "com.google.gwt" % "gwt-user" % v % "provided",
        "com.google.gwt" % "gwt-dev" % v % "provided",
        "javax.validation" % "validation-api" % "1.0.0.GA" % "provided" withSources (),
        "com.google.gwt" % "gwt-servlet" % v)

      import Version._
      v match {
        case Version(VersionInfo(major, minor, _)) if major >=2 && minor >= 5 =>
          s :+ "com.google.gwt" % "gwt-codeserver" % v % "provided"
        case _ =>
          s
      }
    },
    gwtModules <<= (javaSource in Compile, resourceDirectory in Compile) map {
      (javaSource, resources) => findGwtModules(javaSource) ++ findGwtModules(resources)
    },
    gwtDevMode <<= (dependencyClasspath in Gwt, thisProject in Gwt,  state in Gwt, javaSource in Compile, javaOptions in Gwt,
                    gwtModules, gaeSdkPath, gwtWebappPath, streams) map {
      (dependencyClasspath, thisProject, pstate, javaSource, javaOpts, gwtModules, gaeSdkPath, warPath, s) => {
        def gaeFile (path :String*) = gaeSdkPath.map(_ +: path mkString(File.separator))
        val module = gwtModule.getOrElse(gwtModules.headOption.getOrElse{s.log.error("Found no .gwt.xml files."); ""})
        val cp = reorderClasspath(dependencyClasspath) ++ getDepSources(thisProject.dependencies, pstate) ++
          gaeFile("lib", "appengine-tools-api.jar").toList :+ javaSource.absolutePath
        val javaArgs = javaOpts ++ (gaeFile("lib", "agent", "appengine-agent.jar") match {
          case None => Nil
          case Some(path) => List("-javaagent:" + path)
        })
        val gwtArgs = gaeSdkPath match {
          case None => Nil
          case Some(path) => List(
            "-server", "com.google.appengine.tools.development.gwt.AppEngineLauncher")
        }
        val command = mkGwtCommand(
          cp, javaArgs, "com.google.gwt.dev.DevMode", warPath, gwtArgs, module)
        s.log.info("Running GWT devmode on: " + module)
        s.log.debug("Running GWT devmode command: " + command)
        command.!
      }
    },

    gwtSuperDevMode := {
//    <<= (baseDirectory, dependencyClasspath in Gwt, thisProject in Gwt,  state in Gwt, javaSource in Compile, javaOptions in Gwt,
//      gwtModules, gaeSdkPath, gwtWebappPath, streams, gwtDevTemporaryPath, gwtBindAddress) map {
//      (bd, dependencyClasspath, thisProject, pstate, javaSource, javaOpts,  gwtModules, gaeSdkPath, warPath, s, gwtTmp, bindAddress) => {

        val bd = baseDirectory.value
        val depClasspath = (dependencyClasspath in Gwt).value
        val pstate = (state in Gwt).value
        val s = streams.value
        val project = thisProject.value
        val jSource = (javaSource in Compile).value

        val srcDirs =
          for(d <- (Seq(jSource.absolutePath) ++ getDepSources(project.dependencies, pstate)) map(new File(_)) if d.isDirectory)
          yield d.getAbsolutePath
        s.log.info("src dirs:" + srcDirs.mkString(", "))
        def gaeFile (path :String*) = gaeSdkPath.value.map(_ +: path mkString(File.separator))
        val module = gwtModule.getOrElse(gwtModules.value.headOption.getOrElse{s.log.error("Found no .gwt.xml files."); "nomodule"})
        val srcs = getDepSources(project.dependencies, pstate)

        val cp = reorderClasspath(depClasspath) ++ srcs ++
          gaeFile("lib", "appengine-tools-api.jar").toList :+ jSource.absolutePath
        val javaArgs = (javaOptions in Gwt).value ++ (gaeFile("lib", "agent", "appengine-agent.jar") match {
          case None => Nil
          case Some(path) => List("-javaagent:" + path)
        })

        def mkGwtSuperDevCmd = {
          val b = Seq.newBuilder[String]
          b += "java"
          b ++= Seq("-cp", cp.mkString(File.pathSeparator))
          b ++= javaArgs
          b += "com.google.gwt.dev.codeserver.CodeServer"
          (gwtBindAddress.value) map (b ++= Seq("-bindAddress", _))
          b ++= srcDirs.flatMap(Seq("-src", _))
          b ++= Seq("-workDir", gwtDevTemporaryPath.value.getAbsolutePath)
          b += module
          b.result.mkString(" ")
        }

        val command = mkGwtSuperDevCmd
        s.log.debug("gwt superdev cmd:\n" + command)
        s.log.info("Start GWT super dev mode")
        command.!
    },

    gwtCompile <<= ((classDirectory in Compile,
      dependencyClasspath in Gwt,
      thisProject in Gwt,
      state in Gwt,
      javaSource in Compile,
      javaOptions in Gwt,
      gwtModules,
      gwtTemporaryPath,
      streams,
      gwtForceCompile) map {
      (classDirectory, dependencyClasspath, thisProject, pstate, javaSource, javaOpts, gwtModules, warPath, s, force) => {

        val srcDirs = Seq(javaSource.absolutePath) ++ getDepSources(thisProject.dependencies, pstate)

        val cp = Seq(classDirectory.absolutePath) ++ reorderClasspath(dependencyClasspath) ++ srcDirs

        s.log.info("GWT output path: " + warPath.absolutePath)

        val needToCompile : Boolean = {
          s.log.info("Checking GWT module updates: " + gwtModules.mkString(", "))
          val gwtFiles : Seq[File] = (warPath ** "*.nocache.js").get
          if(gwtFiles.isEmpty) {
            s.log.info("No GWT output is found in " + warPath)
            true
          }
          else {
            val lastCompiled = gwtFiles.map(_.lastModified).max
            val moduleDirs = for(d <- srcDirs; m <- (new File(d) ** "*.gwt.xml").get) yield { m.getParentFile }
            val gwtSrcs = for(m <- moduleDirs; f <- (m ** "*").get) yield f
            gwtSrcs.find(lastCompiled < _.lastModified).isDefined
          }
        }
        if(force || needToCompile) {
          IO.createDirectory(new File(warPath.absolutePath))
          val command = mkGwtCommand(
            cp, javaOpts, "com.google.gwt.dev.Compiler", warPath, Nil, gwtModules.mkString(" "))
          s.log.info("Compiling GWT modules: " + gwtModules.mkString(","))
          s.log.debug("Running GWT compiler command: " + command)
          command.!
        }
        else {
          s.log.info("GWT modules are up to date")
          0
        }
      }
    }).dependsOn(compile in Compile, copyResources in Compile),
    unmanagedResourceDirectories in Compile <+= (javaSource in Compile) { (js:File) => js },
    excludeFilter in Compile in unmanagedResources := "*.java",
    webappResources in Compile <+= (gwtTemporaryPath) { (t: File) => t },
    packageBin in Compile <<= (packageBin in Compile).dependsOn(gwtCompile),
    packageWar in Compile <<= (packageWar in Compile).dependsOn(gwtCompile)

    //commands ++= Seq(gwtSetModule)
  )

  def reorderClasspath(cp:Id[Keys.Classpath]) = {
    val (gwtLibs, others) = cp.map(_.data.absolutePath).partition(_.contains("gwt-"))
    gwtLibs ++ others
  }

  def getDepSources(deps : Seq[ClasspathDep[ProjectRef]], state : State) : Set[String] = {
    var sources = Set.empty[String]
    val structure = Project.extract(state).structure
    def get[A] = setting[A](structure)_
    deps.foreach{
    dep=>
      sources +=  (get(dep.project, Keys.sourceDirectory, Compile).get.toString + "/java")
      sources ++= getDepSources(Project.getProject(dep.project, structure).get.dependencies, state)
    }
    sources
  }

  def setting[T](structure: BuildStructure)(ref: ProjectRef, key: SettingKey[T], configuration: Configuration): Option[T] = key in (ref, configuration) get structure.data

  private def mkGwtCommand(cp: Seq[String], javaArgs: Seq[String], clazz: String, warPath: File,
                           gwtArgs: Seq[String], modules: String) =
    (List("java", "-cp", cp.mkString(File.pathSeparator)) ++ javaArgs ++
     List(clazz, "-war", warPath.absolutePath) ++ gwtArgs :+ modules).mkString(" ")

  private def findGwtModules(srcRoot: File): Seq[String] = {
    import Path.relativeTo
    val files = (srcRoot ** "*.gwt.xml").get
    val relativeStrings = files.flatMap(_ x relativeTo(srcRoot)).map(_._2)
    relativeStrings.map(_.dropRight(".gwt.xml".length).replace(File.separator, "."))
  }

}

object Version {

  case class VersionInfo(major:Int, minor:Int, remaining:String)

  def unapply(s:String) : Option[VersionInfo] = {
    try {
      val c = s.split("\\.")
      if(c.length >= 2)
        Some(VersionInfo(c(0).toInt, c(1).toInt, c.takeRight(2).mkString(".")))
      else
        None
    }
    catch {
      case e:NumberFormatException => None
    }
  }
}


text:
/**
 * A custom library to establish a database connection
 */
'use strict';
var mongoose = require('mongoose');

var db = function () {
    return {

        /**
         * Open a connection to the database
         * @param conf
         */
        config: function (conf) {
            mongoose.connect('mongodb://' + conf.host + '/' + conf.database);
            var db = mongoose.connection;
            db.on('error', console.error.bind(console, 'connection error:'));
            db.once('open', function callback() {
                console.log('db connection open');
            });
        }
    };
};

module.exports = db();