@Test
  public void testIndex() throws Exception {

    Date now = new Date();
    DatabaseInfo info = createMock(DatabaseInfo.class);
    expect(info.getDate()).andReturn(now).anyTimes();
    expect(info.isPremium()).andReturn(true).anyTimes();

    AutoUpdateScheduler scheduler = createMock(AutoUpdateScheduler.class);
    GeoIPCity geoIPCity = createMock(GeoIPCity.class);
    expect(scheduler.getLastModified()).andReturn(100L).anyTimes();
    expect(scheduler.getLastCheckpoint()).andReturn(80L).anyTimes();
    expect(scheduler.getNextCheckpoint()).andReturn(280L).anyTimes();
    expect(scheduler.getDatabase()).andReturn(new File("/")).anyTimes();
    expect(scheduler.getGeoIPCity()).andReturn(geoIPCity).anyTimes();
    expect(geoIPCity.getDatabaseInfo()).andReturn(info).anyTimes();
    replay(info, scheduler, geoIPCity);
    AboutController subject = new AboutController(geoIPCity, Providers.of(scheduler));
    String result = subject.index();
    assertEquals(new File("/"), scheduler.getDatabase());
    assertEquals(now, info.getDate());
    assertEquals(true, info.isPremium());
    assertEquals(100L, scheduler.getLastModified());
    assertEquals(80L, scheduler.getLastCheckpoint());
    assertTrue(result.indexOf("Refresh pending") > 0);
  }
  @Test
  public void testScopeEnterLeaveEvents() throws Exception {
    final ThreadDelegatedContext plate = new ThreadDelegatedContext();
    final EventRecordingObject fooEventTest = new EventRecordingObject();

    plate.putIfAbsent(fooStringKey, Providers.of(fooEventTest));
    Assert.assertEquals(1, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());

    scope.changeScope(plate);

    Assert.assertSame(plate, scope.getContext());

    Assert.assertEquals(2, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());

    scope.changeScope(null);

    Assert.assertNotSame(plate, scope.getContext());
    Assert.assertEquals(3, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.LEAVE, fooEventTest.getLastEvent());

    // Put the plate back in.
    scope.changeScope(plate);

    Assert.assertSame(plate, scope.getContext());

    Assert.assertEquals(4, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());

    // Replace with a new plate
    scope.changeScope(new ThreadDelegatedContext());

    Assert.assertNotSame(plate, scope.getContext());

    Assert.assertEquals(5, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.LEAVE, fooEventTest.getLastEvent());

    // Put it back in one more time...
    scope.changeScope(plate);

    Assert.assertSame(plate, scope.getContext());

    Assert.assertEquals(6, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());

    // Pathologic case: Replace with itself.
    scope.changeScope(plate);

    Assert.assertSame(plate, scope.getContext());

    Assert.assertEquals(6, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());
  }
Example #3
0
 @Override
 protected void configure() {
   bindProviders();
   bindSingletons();
   bindTransport();
   install(new FactoryModuleBuilder().build(RadioProcessBufferProcessor.Factory.class));
   SecurityContextFactory instance = null;
   bind(SecurityContextFactory.class).toProvider(Providers.of(instance));
   bindDynamicFeatures();
   bindContainerResponseFilters();
 }
Example #4
0
  @Override
  public void configure(Binder binder) {
    JsonConfigProvider.bind(binder, "druid.emitter.http", HttpEmitterConfig.class);

    final SSLContext context;
    try {
      context = SSLContext.getDefault();
    } catch (NoSuchAlgorithmException e) {
      throw Throwables.propagate(e);
    }

    binder.bind(SSLContext.class).toProvider(Providers.of(context)).in(LazySingleton.class);
  }
Example #5
0
 public ITypeArgumentContext apply(JvmFeatureDescription from) {
   JvmIdentifiableElement feature = from.getEObjectOrProxy();
   if (feature instanceof JvmExecutable && expression instanceof XAbstractFeatureCall) {
     XAbstractFeatureCall featureCall = (XAbstractFeatureCall) expression;
     List<XExpression> arguments =
         featureCallToJavaMapping.getActualArguments(
             featureCall, feature, from.getImplicitReceiver(), from.getImplicitArgument());
     ITypeArgumentContext result =
         typeArgumentContextHelper.getTypeArgumentContext(
             featureCall, arguments, Providers.of(receiverType), feature);
     return result;
   }
   return null;
 }
  protected RequestContext newRequestContext(Account.Id requestUserId) {
    final CurrentUser requestUser = userFactory.create(Providers.of(db), requestUserId);
    return new RequestContext() {
      @Override
      public CurrentUser getCurrentUser() {
        return requestUser;
      }

      @Override
      public Provider<ReviewDb> getReviewDbProvider() {
        return Providers.of(db);
      }
    };
  }
  @Before
  public void setUp() {

    subscribeRequestSecondsRetries.add(1);
    unsubscribeRequestSecondsRetries.add(1);
    keepAliveRequestSecondsRetries.add(3);

    context.checking(
        new Expectations() {
          {
            oneOf(timer).onTime(with(any(OnTimeCallBack.class)));
          }
        });

    pushChannel =
        new PushChannelApiImpl(
            pushChannelServiceAsync,
            channel,
            timer,
            Providers.of(subscriber),
            Providers.of(subscribeRequestSecondsRetries),
            Providers.of(unsubscribeRequestSecondsRetries),
            Providers.of(keepAliveRequestSecondsRetries));
  }
Example #8
0
 public IdentifiedUser create(SocketAddress remotePeer, Account.Id id) {
   return new IdentifiedUser(
       capabilityControlFactory,
       authConfig,
       realm,
       anonymousCowardName,
       canonicalUrl,
       accountCache,
       groupBackend,
       disableReverseDnsLookup,
       Providers.of(remotePeer),
       null,
       id,
       null);
 }
Example #9
0
 public CurrentUser runAs(
     SocketAddress remotePeer, Account.Id id, @Nullable CurrentUser caller) {
   return new IdentifiedUser(
       capabilityControlFactory,
       starredChangesUtil,
       authConfig,
       realm,
       anonymousCowardName,
       canonicalUrl,
       accountCache,
       groupBackend,
       disableReverseDnsLookup,
       Providers.of(remotePeer),
       null,
       id,
       caller);
 }
  @Test
  public void testChangeScopeEvents() throws Exception {
    final ThreadDelegatedContext plate = scope.getContext();
    Assert.assertNotNull(plate);
    Assert.assertEquals(0, plate.size());

    final EventRecordingObject fooEventTest = new EventRecordingObject();

    plate.putIfAbsent(fooStringKey, Providers.of(fooEventTest));
    Assert.assertEquals(1, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.ENTER, fooEventTest.getLastEvent());

    scope.changeScope(null);

    Assert.assertEquals(2, fooEventTest.getEventCount());
    Assert.assertEquals(ScopeEvent.LEAVE, fooEventTest.getLastEvent());
  }
  @Before
  public void setUpInjector() throws Exception {
    lifecycle = new LifecycleManager();
    Injector injector = createInjector();
    lifecycle.add(injector);
    injector.injectMembers(this);
    lifecycle.start();

    db = schemaFactory.open();
    schemaCreator.create(db);
    userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
    Account userAccount = db.accounts().get(userId);
    userAccount.setPreferredEmail("*****@*****.**");
    db.accounts().update(ImmutableList.of(userAccount));
    user = userFactory.create(Providers.of(db), userId);
    requestContext.setContext(newRequestContext(userAccount.getId()));
  }
  protected ChangeInserter newChange(
      TestRepository<Repo> repo,
      @Nullable RevCommit commit,
      @Nullable String key,
      @Nullable Integer owner,
      @Nullable String branch)
      throws Exception {
    if (commit == null) {
      commit = repo.parseBody(repo.commit().message("message").create());
    }
    Account.Id ownerId = owner != null ? new Account.Id(owner) : userId;
    branch = MoreObjects.firstNonNull(branch, "refs/heads/master");
    if (!branch.startsWith("refs/heads/")) {
      branch = "refs/heads/" + branch;
    }
    Project.NameKey project =
        new Project.NameKey(repo.getRepository().getDescription().getRepositoryName());

    Change.Id id = new Change.Id(db.nextChangeId());
    if (key == null) {
      key =
          "I"
              + Hashing.sha1()
                  .newHasher()
                  .putInt(id.get())
                  .putString(project.get(), UTF_8)
                  .putString(commit.name(), UTF_8)
                  .putInt(ownerId.get())
                  .putString(branch, UTF_8)
                  .hash()
                  .toString();
    }

    Change change =
        new Change(
            new Change.Key(key),
            id,
            ownerId,
            new Branch.NameKey(project, branch),
            TimeUtil.nowTs());
    IdentifiedUser user = userFactory.create(Providers.of(db), ownerId);
    return changeFactory.create(projectControlFactory.controlFor(project, user), change, commit);
  }
 @SuppressWarnings("unchecked")
 private EC2CreateNodesInGroupThenAddToSet setupStrategy(TemplateBuilder template) {
   EC2Client client = createMock(EC2Client.class);
   CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
       createKeyPairAndSecurityGroupsAsNeededAndReturncustomize =
           createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
   InstancePresent instancePresent = createMock(InstancePresent.class);
   RunningInstanceToNodeMetadata runningInstanceToNodeMetadata =
       createMock(RunningInstanceToNodeMetadata.class);
   Cache<RunningInstance, Credentials> instanceToCredentials = createMock(Cache.class);
   Map<String, Credentials> credentialStore = createMock(Map.class);
   ComputeUtils utils = createMock(ComputeUtils.class);
   return new EC2CreateNodesInGroupThenAddToSet(
       client,
       Providers.<TemplateBuilder>of(template),
       createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
       instancePresent,
       runningInstanceToNodeMetadata,
       instanceToCredentials,
       credentialStore,
       utils);
 }
 public GraphUpdatingObjectDatabase(Provider<GraphDatabase> graphDb, ObjectDatabase subject) {
   super(Providers.of(subject));
   this.graphDb = graphDb;
 }
  @Override
  protected void configure() {
    this.bind(File.class)
        .annotatedWith(Names.named("KeyStorageFile"))
        .toInstance(this.configuration.getKeyStorageFile());
    this.bind(File.class)
        .annotatedWith(Names.named("IssuerSecretKeyStorageFile"))
        .toInstance(this.configuration.getIssuerSecretKeyFile());
    this.bind(File.class)
        .annotatedWith(Names.named("InspectorSecretKeyStorageFile"))
        .toInstance(this.configuration.getInspectorSecretKeyFile());
    this.bind(File.class)
        .annotatedWith(Names.named("RevocationAuthoritySecretKeyStorageFile"))
        .toInstance(this.configuration.getRevocationAuthoritySecretKeyFile());
    this.bind(File.class)
        .annotatedWith(Names.named("RevocationAuthorityStorageFile"))
        .toInstance(this.configuration.getRevocationAuthorityStorageFile());
    this.bind(File.class)
        .annotatedWith(Names.named("TokenStorageFile"))
        .toInstance(this.configuration.getTokensFile());
    this.bind(File.class)
        .annotatedWith(Names.named("PseudonymsStorageFile"))
        .toInstance(this.configuration.getPseudonymsFile());
    this.bind(File.class)
        .annotatedWith(Names.named("TokenLogFile"))
        .toInstance(this.configuration.getIssuerLogFile());
    this.bind(File.class)
        .annotatedWith(Names.named("CredentialStorageFile"))
        .toInstance(this.configuration.getCredentialFile());
    this.bind(File.class)
        .annotatedWith(Names.named("SecretStorageFile"))
        .toInstance(this.configuration.getSecretStorageFile());
    this.bind(String.class)
        .annotatedWith(Names.named("DefaultImagePath"))
        .toInstance(this.configuration.getDefaultImagePath());
    this.bind(File.class)
        .annotatedWith(Names.named("ImageCacheBaseDir"))
        .toInstance(this.configuration.getImageCacheDir());
    this.bind(Random.class)
        .annotatedWith(Names.named("RandomNumberGenerator"))
        .toInstance(this.configuration.getPrng());

    // Uprove extras
    Integer numberOfCredentialsToGenerate =
        this.configuration.getUProveNumberOfCredentialsToGenerate();
    if (numberOfCredentialsToGenerate == null) {
      numberOfCredentialsToGenerate = 10;
    }
    this.bind(Integer.class)
        .annotatedWith(Names.named("NumberOfCredentialsToGenerate"))
        .toInstance(numberOfCredentialsToGenerate);
    File uProveWorkingDirectory = this.configuration.getUProveWorkingDirectory();

    // We bind to providers, since the variables might be null
    this.bind(File.class)
        .annotatedWith(Names.named("UProveWorkingDirectory"))
        .toProvider(Providers.of(uProveWorkingDirectory));
    this.bind(String.class)
        .annotatedWith(Names.named("PathToUProveExe"))
        .toProvider(Providers.of(this.configuration.getUProvePathToExe()));
    this.bind(Integer.class)
        .annotatedWith(Names.named("UProveRetryTimeout"))
        .toProvider(Providers.of(this.configuration.getUProveRetryTimeout()));
    this.bind(Integer.class)
        .annotatedWith(Names.named("RetryTimeout"))
        .toProvider(Providers.of(this.configuration.getUProveRetryTimeout()));
    this.bind(Integer.class)
        .annotatedWith(Names.named("UProvePortNumber"))
        .toProvider(Providers.of(this.configuration.getUProvePortNumber()));
  }
 public Provider<? extends T> getProviderInstance() {
   return Providers.guicify(providerInstance);
 }
 private Context newRequestContext(TestAccount account) {
   return atrScope.newContext(
       reviewDbProvider,
       new SshSession(server, admin),
       identifiedUserFactory.create(Providers.of(db), account.getId()));
 }
Example #18
0
/**
 * Represents a complete set of Soy files for compilation as one bundle. The files may depend on
 * each other but should not have dependencies outside of the set.
 *
 * <p>Note: Soy file (or resource) contents must be encoded in UTF-8.
 */
public final class SoyFileSet {

  /** Injectable factory for creating an instance of this class. */
  static interface SoyFileSetFactory {

    /**
     * @param soyFileSuppliers The suppliers for the input Soy files.
     * @param options The general compiler options.
     */
    public SoyFileSet create(List<SoyFileSupplier> soyFileSuppliers, SoyGeneralOptions options);
  }

  /** Builder for a {@code SoyFileSet}. */
  public static final class Builder {

    /** Factory for creating an instance of SoyFileSet (statically injected). */
    @Inject private static SoyFileSetFactory soyFileSetFactory = null;

    /** The list of SoyFileSuppliers collected so far. */
    private final ImmutableList.Builder<SoyFileSupplier> listBuilder;

    /** The general compiler options. */
    private SoyGeneralOptions generalOptions;

    /**
     * Constructs a builder that starts with a default {@link SoyGeneralOptions} object (options can
     * be modified via methods on the builder).
     */
    @Inject
    public Builder() {
      this(new SoyGeneralOptions());
    }

    /**
     * Constructs a builder with a specified {@link SoyGeneralOptions} object.
     *
     * @param generalOptions The {@code SoyGeneralOptions} object to use.
     */
    public Builder(SoyGeneralOptions generalOptions) {

      this.listBuilder = ImmutableList.builder();
      this.generalOptions = generalOptions.clone();

      // Bootstrap Guice for Soy API users that don't use Guice. This is done by statically
      // injecting an instance of SoyFileSetFactory into this Builder class. Everything derived
      // from this SoyFileSetFactory will be Guice-enabled.
      GuiceInitializer.initializeIfNecessary();
    }

    /**
     * Builds the new {@code SoyFileSet}.
     *
     * @return The new {@code SoyFileSet}.
     */
    public SoyFileSet build() {
      return soyFileSetFactory.create(listBuilder.build(), generalOptions);
    }

    /**
     * Adds an input Soy file, given an {@code InputSupplier} for the file content, as well as the
     * desired file path for messages.
     *
     * @param contentSupplier Supplier of a Reader for the Soy file content.
     * @param filePath The path to the Soy file (used for messages only).
     * @return This builder.
     */
    public Builder add(InputSupplier<? extends Reader> contentSupplier, String filePath) {
      listBuilder.add(SoyFileSupplier.Factory.create(contentSupplier, filePath));
      return this;
    }

    /**
     * Adds an input Soy file, given a {@code File}.
     *
     * @param inputFile The Soy file.
     * @return This builder.
     */
    public Builder add(File inputFile) {
      listBuilder.add(SoyFileSupplier.Factory.create(inputFile));
      return this;
    }

    /**
     * Adds an input Soy file that the system will watch for changes, given a {@code File}.
     *
     * @param inputFile The Soy file.
     * @return This builder.
     */
    public Builder addVolatile(File inputFile) {
      listBuilder.add(new VolatileSoyFileSupplier(inputFile));
      return this;
    }

    /**
     * Adds an input Soy file, given a resource {@code URL}, as well as the desired file path for
     * messages.
     *
     * @param inputFileUrl The Soy file.
     * @param filePath The path to the Soy file (used for messages only).
     * @return This builder.
     */
    public Builder add(URL inputFileUrl, String filePath) {
      listBuilder.add(SoyFileSupplier.Factory.create(inputFileUrl, filePath));
      return this;
    }

    /**
     * Adds an input Soy file, given a resource {@code URL}.
     *
     * <p>Important: This function assumes that the desired file path is returned by {@code
     * inputFileUrl.toString()}. If this is not the case, please use {@link #add(URL, String)}
     * instead.
     *
     * @see #add(URL, String)
     * @param inputFileUrl The Soy file.
     * @return This builder.
     */
    public Builder add(URL inputFileUrl) {
      listBuilder.add(SoyFileSupplier.Factory.create(inputFileUrl));
      return this;
    }

    /**
     * Adds an input Soy file, given the file content provided as a string, as well as the desired
     * file path for messages.
     *
     * @param content The Soy file content.
     * @param filePath The path to the Soy file (used for messages only).
     * @return This builder.
     */
    public Builder add(CharSequence content, String filePath) {
      listBuilder.add(SoyFileSupplier.Factory.create(content, filePath));
      return this;
    }

    /**
     * Sets whether to allow external calls (calls to undefined templates).
     *
     * @param allowExternalCalls Whether to allow external calls (calls to undefined templates).
     * @return This builder.
     */
    public Builder setAllowExternalCalls(boolean allowExternalCalls) {
      this.generalOptions.setAllowExternalCalls(allowExternalCalls);
      return this;
    }

    /**
     * Sets the scheme for handling {@code css} commands.
     *
     * @param cssHandlingScheme The scheme for handling {@code css} commands.
     * @return This builder.
     */
    public Builder setCssHandlingScheme(CssHandlingScheme cssHandlingScheme) {
      this.generalOptions.setCssHandlingScheme(cssHandlingScheme);
      return this;
    }

    /**
     * Sets the map from compile-time global name to value.
     *
     * <p>The values can be any of the Soy primitive types: null, boolean, integer, float (Java
     * double), or string.
     *
     * @param compileTimeGlobalsMap Map from compile-time global name to value. The values can be
     *     any of the Soy primitive types: null, boolean, integer, float (Java double), or string.
     * @return This builder.
     * @throws SoySyntaxException If one of the values is not a valid Soy primitive type.
     */
    public Builder setCompileTimeGlobals(Map<String, ?> compileTimeGlobalsMap) {
      this.generalOptions.setCompileTimeGlobals(compileTimeGlobalsMap);
      return this;
    }

    /**
     * Sets the file containing compile-time globals.
     *
     * <p>Each line of the file should have the format
     *
     * <pre>
     *     &lt;global_name&gt; = &lt;primitive_data&gt;
     * </pre>
     *
     * where primitive_data is a valid Soy expression literal for a primitive type (null, boolean,
     * integer, float, or string). Empty lines and lines beginning with "//" are ignored. The file
     * should be encoded in UTF-8.
     *
     * <p>If you need to generate a file in this format from Java, consider using the utility {@code
     * SoyUtils.generateCompileTimeGlobalsFile()}.
     *
     * @param compileTimeGlobalsFile The file containing compile-time globals.
     * @return This builder.
     * @throws IOException If there is an error reading the compile-time globals file.
     */
    public Builder setCompileTimeGlobals(File compileTimeGlobalsFile) throws IOException {
      this.generalOptions.setCompileTimeGlobals(compileTimeGlobalsFile);
      return this;
    }

    /**
     * Sets the resource file containing compile-time globals.
     *
     * <p>Each line of the file should have the format
     *
     * <pre>
     *     &lt;global_name&gt; = &lt;primitive_data&gt;
     * </pre>
     *
     * where primitive_data is a valid Soy expression literal for a primitive type (null, boolean,
     * integer, float, or string). Empty lines and lines beginning with "//" are ignored. The file
     * should be encoded in UTF-8.
     *
     * <p>If you need to generate a file in this format from Java, consider using the utility {@code
     * SoyUtils.generateCompileTimeGlobalsFile()}.
     *
     * @param compileTimeGlobalsResource The resource containing compile-time globals.
     * @return This builder.
     * @throws IOException If there is an error reading the compile-time globals file.
     */
    public Builder setCompileTimeGlobals(URL compileTimeGlobalsResource) throws IOException {
      this.generalOptions.setCompileTimeGlobals(compileTimeGlobalsResource);
      return this;
    }
  }

  /** Default SoyMsgBundleHandler uses the XLIFF message plugin. */
  private static final Provider<SoyMsgBundleHandler> DEFAULT_SOY_MSG_BUNDLE_HANDLER_PROVIDER =
      Providers.of(new SoyMsgBundleHandler(new XliffMsgPlugin()));

  /** Provider for getting an instance of SoyMsgBundleHandler. */
  private Provider<SoyMsgBundleHandler> msgBundleHandlerProvider;

  /** Factory for creating an instance of BaseTofu. */
  private final BaseTofuFactory baseTofuFactory;

  /** Provider for getting an instance of JsSrcMain. */
  private final Provider<JsSrcMain> jsSrcMainProvider;

  /** Provider for getting an instance of JavaSrcMain. */
  private final Provider<JavaSrcMain> javaSrcMainProvider;

  /** Provider for getting an instance of GoSrcMain. */
  private final Provider<GoSrcMain> goSrcMainProvider;

  /** The instance of PerformAutoescapeVisitor to use. */
  private final PerformAutoescapeVisitor performAutoescapeVisitor;

  /** The instance of ContextualAutoescaper to use. */
  private final ContextualAutoescaper contextualAutoescaper;

  /** The instance of CheckFunctionCallsVisitor to use. */
  private final CheckFunctionCallsVisitor checkFunctionCallsVisitor;

  /** The instance of SimplifyVisitor to use. */
  private final SimplifyVisitor simplifyVisitor;

  /** The suppliers for the input Soy files. */
  private final List<SoyFileSupplier> soyFileSuppliers;

  /** The general compiler options. */
  private final SoyGeneralOptions generalOptions;

  /**
   * @param baseTofuFactory Factory for creating an instance of BaseTofu.
   * @param jsSrcMainProvider Provider for getting an instance of JsSrcMain.
   * @param javaSrcMainProvider Provider for getting an instance of JavaSrcMain.
   * @param performAutoescapeVisitor The instance of PerformAutoescapeVisitor to use.
   * @param contextualAutoescaper The instance of ContextualAutoescaper to use.
   * @param simplifyVisitor The instance of SimplifyVisitor to use.
   * @param soyFileSuppliers The suppliers for the input Soy files.
   * @param generalOptions The general compiler options.
   */
  @Inject
  SoyFileSet(
      BaseTofuFactory baseTofuFactory,
      Provider<JsSrcMain> jsSrcMainProvider,
      Provider<JavaSrcMain> javaSrcMainProvider,
      Provider<GoSrcMain> goSrcMainProvider,
      PerformAutoescapeVisitor performAutoescapeVisitor,
      ContextualAutoescaper contextualAutoescaper,
      SimplifyVisitor simplifyVisitor,
      CheckFunctionCallsVisitor checkFunctionCallsVisitor,
      @Assisted List<SoyFileSupplier> soyFileSuppliers,
      @Assisted SoyGeneralOptions generalOptions) {

    // Default value is optionally replaced using method injection.
    this.msgBundleHandlerProvider = DEFAULT_SOY_MSG_BUNDLE_HANDLER_PROVIDER;

    this.baseTofuFactory = baseTofuFactory;
    this.jsSrcMainProvider = jsSrcMainProvider;
    this.javaSrcMainProvider = javaSrcMainProvider;
    this.goSrcMainProvider = goSrcMainProvider;
    this.performAutoescapeVisitor = performAutoescapeVisitor;
    this.contextualAutoescaper = contextualAutoescaper;
    this.simplifyVisitor = simplifyVisitor;
    this.checkFunctionCallsVisitor = checkFunctionCallsVisitor;

    Preconditions.checkArgument(
        soyFileSuppliers.size() > 0, "Must have non-zero number of input Soy files.");
    this.soyFileSuppliers = soyFileSuppliers;
    this.generalOptions = generalOptions.clone();
  }

  /** @param msgBundleHandlerProvider Provider for getting an instance of SoyMsgBundleHandler. */
  @Inject(optional = true)
  void setMsgBundleHandlerProvider(Provider<SoyMsgBundleHandler> msgBundleHandlerProvider) {
    this.msgBundleHandlerProvider = msgBundleHandlerProvider;
  }

  /** Returns the list of suppliers for the input Soy files. For testing use only! */
  @VisibleForTesting
  List<SoyFileSupplier> getSoyFileSuppliersForTesting() {
    return soyFileSuppliers;
  }

  /** Returns the general compiler options. For testing use only! */
  @VisibleForTesting
  SoyGeneralOptions getOptionsForTesting() {
    return generalOptions;
  }

  /**
   * Generates Java classes containing parse info (param names, template names, meta info). There
   * will be one Java class per Soy file.
   *
   * @param javaPackage The Java package for the generated classes.
   * @param javaClassNameSource Source of the generated class names. Must be one of "filename",
   *     "namespace", or "generic".
   * @return A map from generated file name (of the form "<*>SoyInfo.java") to generated file
   *     content.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public ImmutableMap<String, String> generateParseInfo(
      String javaPackage, String javaClassNameSource) throws SoySyntaxException {

    SoyFileSetNode soyTree = (new SoyFileSetParser(soyFileSuppliers)).parse();

    return (new GenerateParseInfoVisitor(javaPackage, javaClassNameSource)).exec(soyTree);
  }

  /**
   * Extracts all messages from this Soy file set into a SoyMsgBundle (which can then be turned into
   * an extracted messages file with the help of a SoyMsgBundleHandler).
   *
   * @return A SoyMsgBundle containing all the extracted messages (locale "en").
   * @throws SoySyntaxException If a syntax error is found.
   */
  public SoyMsgBundle extractMsgs() throws SoySyntaxException {

    SoyFileSetNode soyTree =
        (new SoyFileSetParser(soyFileSuppliers))
            .setDoEnforceSyntaxVersionV2(false)
            .setDoCheckOverrides(false)
            .parse();

    return (new ExtractMsgsVisitor()).exec(soyTree);
  }

  /**
   * Compiles this Soy file set into a Java object (type {@code SoyTofu}) capable of rendering the
   * compiled templates. The resulting {@code SoyTofu} does not cache intermediate results after
   * substitutions from the SoyMsgBundle and the SoyCssRenamingMap.
   *
   * @see #compileToTofu(com.google.template.soy.tofu.SoyTofuOptions)
   * @return The resulting {@code SoyTofu} object.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public SoyTofu compileToTofu() throws SoySyntaxException {
    return compileToTofu(new SoyTofuOptions());
  }

  /**
   * Compiles this Soy file set into a Java object (type {@code SoyTofu}) capable of rendering the
   * compiled templates.
   *
   * @param tofuOptions The compilation options for the Tofu backend.
   * @return The resulting {@code SoyTofu} object.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public SoyTofu compileToTofu(SoyTofuOptions tofuOptions) throws SoySyntaxException {

    // Defensive copy of options. (Doesn't matter now, but might forget later when it matters.)
    tofuOptions = tofuOptions.clone();

    // TODO: Allow binding a SoyTofu instance to volatile inputs.
    SoyFileSetNode soyTree = (new SoyFileSetParser(soyFileSuppliers)).parse();
    runMiddleendPasses(soyTree, true);

    // If allowExternalCalls is not explicitly set, then disallow by default for Tofu backend.
    if (generalOptions.allowExternalCalls() == null) {
      // TODO: Enable this check when all Google internal projects are compliant.
      // (new AssertNoExternalCallsVisitor()).exec(soyTree);
    }

    // Note: Globals should have been substituted already. The pass below is just a check.
    (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), true)).exec(soyTree);

    // Clear the SoyDoc strings because they use unnecessary memory.
    (new ClearSoyDocStringsVisitor()).exec(soyTree);

    return baseTofuFactory.create(soyTree, tofuOptions.useCaching());
  }

  /**
   * Compiles this Soy file set into a Java object (type {@code SoyTofu}) capable of rendering the
   * compiled templates. The resulting {@code SoyTofu} does not cache intermediate results after
   * substitutions from the SoyMsgBundle and the SoyCssRenamingMap.
   *
   * @see #compileToTofu()
   * @return The result of compiling this Soy file set into a Java object.
   * @throws SoySyntaxException If a syntax error is found.
   * @deprecated Use {@link #compileToTofu()}.
   */
  @Deprecated
  public SoyTofu compileToJavaObj() throws SoySyntaxException {
    return compileToTofu(new SoyTofuOptions());
  }

  /**
   * Compiles this Soy file set into a Java object (type {@code SoyTofu}) capable of rendering the
   * compiled templates.
   *
   * @param useCaching Whether the resulting SoyTofu instance should cache intermediate results
   *     after substitutions from the SoyMsgBundle and the SoyCssRenamingMap. It is recommended to
   *     set this param to true if you're planning to reuse the SoyTofu instance to render multiple
   *     times.
   *     <p>Specifically, if this param is set to true, then (a) The first time the SoyTofu is used
   *     with a new combination of SoyMsgBundle and SoyCssRenamingMap, the render will be slower.
   *     (Note that this first-render slowness can be eliminated by calling the method {@link
   *     SoyTofu#addToCache} to prime the cache.) (b) The subsequent times the SoyTofu is used with
   *     an already-seen combination of SoyMsgBundle and SoyCssRenamingMap, the render will be
   *     faster.
   *     <p>The cache will use memory proportional to the number of distinct combinations of
   *     SoyMsgBundle and SoyCssRenamingMap your app uses (note most apps have at most one
   *     SoyCssRenamingMap). If you find memory usage to be a problem, you can manually control the
   *     contents of the cache. See {@link SoyTofu.Renderer#setDontAddToCache} for details.
   * @see #compileToTofu(com.google.template.soy.tofu.SoyTofuOptions)
   * @return The result of compiling this Soy file set into a Java object.
   * @throws SoySyntaxException If a syntax error is found.
   * @deprecated Use {@link #compileToTofu(com.google.template.soy.tofu.SoyTofuOptions)}.
   */
  @Deprecated
  public SoyTofu compileToJavaObj(boolean useCaching) throws SoySyntaxException {
    SoyTofuOptions options = new SoyTofuOptions();
    options.setUseCaching(useCaching);
    return compileToTofu(options);
  }

  /**
   * Warning: The Java Src backend is experimental (incomplete, repetitive, untested, undocumented).
   *
   * <p>Returns a bundle of templates compiled using the experimental java compiler that will be
   * automatically recompiled if the underlying Soy sources are modified.
   *
   * @return The compiled result.
   */
  public SoyTemplateRuntimes compileToRuntimes(
      final String bundleName, SoyJavaSrcOptions options, final SoyMsgBundle msgBundle) {

    // Defensively copy options so that changes to them can't affect lazily compiled modules.
    final SoyJavaSrcOptions copyOfOptions = options.clone();
    copyOfOptions.setCodeStyle(SoyJavaSrcOptions.CodeStyle.STRINGBUILDER);

    return new SoyTemplateRuntimes() {

      /** The versions corresponding to compiledTemplates used to produce the compiled form. */
      private List<SoyFileSupplier.Version> compiledVersions = null;
      /** The compiled form or null if not yet compiled. */
      private ImmutableMap<String, SoyTemplateRuntime> compiledTemplates;
      /** True if at least one file supplier might change from the last compiled version. */
      private final boolean isDynamic;

      {
        synchronized (this) { // Synchronize so isDynamic is in step with compiledVersions.
          compile();

          // If none of the inputs are volatile we never need to check versions in newRenderer().
          boolean isDynamic = false;
          for (SoyFileSupplier.Version version : this.compiledVersions) {
            if (version != SoyFileSupplier.Version.STABLE_VERSION) {
              isDynamic = true;
              break;
            }
          }
          this.isDynamic = isDynamic;
        }
      }

      /** @throws SoySyntaxException If an input is out of date and malformed. */
      @Override
      public SoyTemplateRuntime newRenderer(String templateName) throws SoySyntaxException {

        // Recompile if necessary.
        if (isOutOfDate()) {
          compile();
        }

        return compiledTemplates.get(templateName);
      }

      /**
       * Invokes the {@link SoyToJavaDynamicCompiler} to produce an up-to-date version of the
       * template name to SoyRuntime map.
       */
      private void compile() throws SoySyntaxException {

        Pair<SoyFileSetNode, List<SoyFileSupplier.Version>> soyTreeAndVersions =
            (new SoyFileSetParser(soyFileSuppliers)).parseWithVersions();
        SoyFileSetNode soyTree = soyTreeAndVersions.first;
        runMiddleendPasses(soyTree, true);

        ImmutableMap<String, SoyTemplateRuntime> result =
            SoyToJavaDynamicCompiler.compile(
                bundleName, compileFileSetToJavaSrc(soyTree, copyOfOptions, msgBundle));

        // Atomically updated compiledTemplates, the version, and isDynamic since they are
        // all related.
        synchronized (this) {
          compiledTemplates = result;
          compiledVersions = soyTreeAndVersions.second;
        }
      }

      /** True iff there is a volatile input that is out of date. */
      private boolean isOutOfDate() {
        if (isDynamic) {
          // Check if we need to recompile based on changes to volatile inputs.
          int numFiles = soyFileSuppliers.size();
          for (int i = 0; i < numFiles; ++i) {
            if (soyFileSuppliers.get(i).hasChangedSince(compiledVersions.get(i))) {
              return true;
            }
          }
        }
        return false;
      }
    };
  }

  /**
   * Warning: The Java Src backend is experimental (incomplete, repetitive, untested, undocumented).
   *
   * <p>To use Soy from Java, you should call {@link #compileToTofu()} to obtain a {@code SoyTofu}
   * object that will be able to render any public template in this Soy file set.
   *
   * @param javaSrcOptions The compilation options for the Java Src output target.
   * @param msgBundle The bundle of translated messages, or null to use the messages from the Soy
   *     source.
   * @return Java source code in one big ugly blob. Can be put inside any class without needing
   *     additional imports because all class names in the generated code are fully qualified.
   */
  public String compileToJavaSrc(SoyJavaSrcOptions javaSrcOptions, SoyMsgBundle msgBundle) {

    SoyFileSetNode soyTree = (new SoyFileSetParser(soyFileSuppliers)).parse();
    runMiddleendPasses(soyTree, true);

    return compileFileSetToJavaSrc(soyTree, javaSrcOptions, msgBundle);
  }

  /**
   * Invokes the Java Src backend after running the prerequisite visitors on the given Soy tree.
   *
   * @param soyTree Modified in place by the prerequisite visitors.
   * @param javaSrcOptions The compilation options for the Java Src output target.
   * @param msgBundle The bundle of translated messages, or null to use the messages from the Soy
   *     source.
   * @return Java source code in one big ugly blob. Can be put inside any class without needing
   *     additional imports because all class names in the generated code are fully qualified.
   */
  private String compileFileSetToJavaSrc(
      SoyFileSetNode soyTree, SoyJavaSrcOptions javaSrcOptions, SoyMsgBundle msgBundle) {

    // Note: Globals should have been substituted already. The pass below is just a check.
    (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), true)).exec(soyTree);

    return javaSrcMainProvider.get().genJavaSrc(soyTree, javaSrcOptions, msgBundle);
  }

  /**
   * Warning: The Go Src backend is experimental (repetitive, untested, undocumented).
   *
   * <p>To use Soy from Go, you should call {@link #compileToJavaObj()} to obtain a {@code SoyTofu}
   * object that will be able to render any public template in this Soy file set.
   *
   * @param goSrcOptions The compilation options for the Go Src output target.
   * @param msgBundle The bundle of translated messages, or null to use the messages from the Soy
   *     source.
   * @return Go source code in one big ugly blob. Can be put inside any class without needing
   *     additional imports because all class names in the generated code are fully qualified.
   */
  public List<Pair<String, String>> compileToGoSrc(
      SoyGoSrcOptions goSrcOptions, SoyMsgBundle msgBundle) {

    SoyFileSetNode soyTree = (new SoyFileSetParser(soyFileSuppliers)).parse();
    runMiddleendPasses(soyTree, true);

    return compileFileSetToGoSrc(soyTree, goSrcOptions, msgBundle);
  }

  private List<Pair<String, String>> compileFileSetToGoSrc(
      SoyFileSetNode soyTree, SoyGoSrcOptions goSrcOptions, SoyMsgBundle msgBundle) {

    // Note: Globals should have been substituted already. The pass below is just a check.
    (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), true)).exec(soyTree);

    return goSrcMainProvider.get().genGoSrc(soyTree, goSrcOptions, msgBundle);
  }

  /**
   * Compiles this Soy file set into JS source code files and returns these JS files as a list of
   * strings, one per file.
   *
   * @param jsSrcOptions The compilation options for the JS Src output target.
   * @param msgBundle The bundle of translated messages, or null to use the messages from the Soy
   *     source.
   * @return A list of strings where each string represents the JS source code that belongs in one
   *     JS file. The generated JS files correspond one-to-one to the original Soy source files.
   * @throws SoySyntaxException If a syntax error is found.
   */
  public List<String> compileToJsSrc(SoyJsSrcOptions jsSrcOptions, @Nullable SoyMsgBundle msgBundle)
      throws SoySyntaxException {

    boolean doEnforceSyntaxVersionV2 = !jsSrcOptions.shouldAllowDeprecatedSyntax();
    SoyFileSetNode soyTree =
        (new SoyFileSetParser(soyFileSuppliers))
            .setDoEnforceSyntaxVersionV2(doEnforceSyntaxVersionV2)
            .parse();
    runMiddleendPasses(soyTree, doEnforceSyntaxVersionV2);

    return jsSrcMainProvider.get().genJsSrc(soyTree, jsSrcOptions, msgBundle);
  }

  /**
   * Compiles this Soy file set into JS source code files and writes these JS files to disk.
   *
   * @param outputPathFormat The format string defining how to build the output file path
   *     corresponding to an input file path.
   * @param inputFilePathPrefix The prefix prepended to all input file paths (can be empty string).
   * @param jsSrcOptions The compilation options for the JS Src output target.
   * @param locales The list of locales. Can be an empty list if not applicable.
   * @param messageFilePathFormat The message file path format, or null if not applicable.
   * @throws SoySyntaxException If a syntax error is found.
   * @throws IOException If there is an error in opening/reading a message file or opening/writing
   *     an output JS file.
   */
  void compileToJsSrcFiles(
      String outputPathFormat,
      String inputFilePathPrefix,
      SoyJsSrcOptions jsSrcOptions,
      List<String> locales,
      @Nullable String messageFilePathFormat)
      throws SoySyntaxException, IOException {

    boolean doEnforceSyntaxVersionV2 = !jsSrcOptions.shouldAllowDeprecatedSyntax();
    SoyFileSetNode soyTree =
        (new SoyFileSetParser(soyFileSuppliers))
            .setDoEnforceSyntaxVersionV2(doEnforceSyntaxVersionV2)
            .parse();
    runMiddleendPasses(soyTree, doEnforceSyntaxVersionV2);

    if (locales.size() == 0) {
      // Not generating localized JS.
      jsSrcMainProvider
          .get()
          .genJsFiles(soyTree, jsSrcOptions, null, null, outputPathFormat, inputFilePathPrefix);

    } else {
      // Generating localized JS.
      for (String locale : locales) {

        SoyFileSetNode soyTreeClone = soyTree.clone();

        String msgFilePath =
            JsSrcUtils.buildFilePath(messageFilePathFormat, locale, null, inputFilePathPrefix);

        SoyMsgBundle msgBundle =
            msgBundleHandlerProvider.get().createFromFile(new File(msgFilePath));
        if (msgBundle.getLocaleString() == null) {
          // TODO: Remove this check (but make sure no projects depend on this behavior).
          // There was an error reading the message file. We continue processing only if the locale
          // begins with "en", because falling back to the Soy source will proably be fine.
          if (!locale.startsWith("en")) {
            throw new IOException("Error opening or reading message file " + msgFilePath);
          }
        }

        jsSrcMainProvider
            .get()
            .genJsFiles(
                soyTreeClone,
                jsSrcOptions,
                locale,
                msgBundle,
                outputPathFormat,
                inputFilePathPrefix);
      }
    }
  }

  /**
   * Runs middleend passes on the given Soy tree.
   *
   * @param soyTree The Soy tree to run middleend passes on.
   * @param doEnforceSyntaxVersionV2 Whether to enforce SyntaxVersion.V2.
   * @throws SoySyntaxException If a syntax error is found.
   * @throws SoyAutoescapeException If there is a problem determining the context for an {@code
   *     autoescape="contextual"} template or one of its callers.
   */
  private void runMiddleendPasses(SoyFileSetNode soyTree, boolean doEnforceSyntaxVersionV2)
      throws SoySyntaxException {

    // If diallowing external calls, perform the check.
    if (generalOptions.allowExternalCalls() == Boolean.FALSE) {
      (new AssertNoExternalCallsVisitor()).exec(soyTree);
    }

    // Handle CSS commands (if not backend-specific) and substitute compile-time globals.
    (new HandleCssCommandVisitor(generalOptions.getCssHandlingScheme())).exec(soyTree);
    if (generalOptions.getCompileTimeGlobals() != null) {
      (new SubstituteGlobalsVisitor(generalOptions.getCompileTimeGlobals(), false)).exec(soyTree);
    }

    // Soy version 1 allowed calling functions that are not backed by any SoyFunction definition.
    checkFunctionCallsVisitor.setAllowExternallyDefinedFunctions(!doEnforceSyntaxVersionV2);
    checkFunctionCallsVisitor.exec(soyTree);

    // Run contextual escaping after CSS has been done, but before the autoescape visitor adds
    // |escapeHtml directives.  The contextual directive filterHtmlIdent serves the same purpose
    // in some places, but with runtime guarantees.
    doContextualEscaping(soyTree);
    performAutoescapeVisitor.exec(soyTree);

    // Attempt to simplify the tree.
    (new ChangeCallsToPassAllDataVisitor()).exec(soyTree);
    simplifyVisitor.exec(soyTree);
  }

  private void doContextualEscaping(SoyFileSetNode soyTree) throws SoySyntaxException {
    List<TemplateNode> extraTemplates = contextualAutoescaper.rewrite(soyTree);
    // TODO: Run the redundant template remover here and rename after CL 16642341 is in.
    if (!extraTemplates.isEmpty()) {
      // TODO: pull out somewhere else.  Ideally do the merge as part of the redundant template
      // removal.
      Map<String, SoyFileNode> containingFile = Maps.newHashMap();
      for (SoyFileNode fileNode : soyTree.getChildren()) {
        for (TemplateNode templateNode : fileNode.getChildren()) {
          String name =
              templateNode instanceof TemplateDelegateNode
                  ? ((TemplateDelegateNode) templateNode).getDelTemplateName()
                  : templateNode.getTemplateName();
          containingFile.put(DerivedTemplateUtils.getBaseName(name), fileNode);
        }
      }
      for (TemplateNode extraTemplate : extraTemplates) {
        String name =
            extraTemplate instanceof TemplateDelegateNode
                ? ((TemplateDelegateNode) extraTemplate).getDelTemplateName()
                : extraTemplate.getTemplateName();
        containingFile.get(DerivedTemplateUtils.getBaseName(name)).addChild(extraTemplate);
      }
    }
  }
}
Example #19
0
 /**
  * Set the element to provide.
  *
  * @param item the item to use. Must not be null.
  * @param pluginName the name of the plugin providing the item.
  * @return handle to remove the item at a later point in time.
  */
 public RegistrationHandle set(T item, String pluginName) {
   return set(Providers.of(item), pluginName);
 }
  public ConfigInfoImpl(
      boolean serverEnableSignedPush,
      ProjectControl control,
      TransferConfig config,
      DynamicMap<ProjectConfigEntry> pluginConfigEntries,
      PluginConfigFactory cfgFactory,
      AllProjectsName allProjects,
      DynamicMap<RestView<ProjectResource>> views) {
    ProjectState projectState = control.getProjectState();
    Project p = control.getProject();
    this.description = Strings.emptyToNull(p.getDescription());

    InheritedBooleanInfo useContributorAgreements = new InheritedBooleanInfo();
    InheritedBooleanInfo useSignedOffBy = new InheritedBooleanInfo();
    InheritedBooleanInfo useContentMerge = new InheritedBooleanInfo();
    InheritedBooleanInfo requireChangeId = new InheritedBooleanInfo();
    InheritedBooleanInfo createNewChangeForAllNotInTarget = new InheritedBooleanInfo();
    InheritedBooleanInfo enableSignedPush = new InheritedBooleanInfo();
    InheritedBooleanInfo requireSignedPush = new InheritedBooleanInfo();
    InheritedBooleanInfo rejectImplicitMerges = new InheritedBooleanInfo();

    useContributorAgreements.value = projectState.isUseContributorAgreements();
    useSignedOffBy.value = projectState.isUseSignedOffBy();
    useContentMerge.value = projectState.isUseContentMerge();
    requireChangeId.value = projectState.isRequireChangeID();
    createNewChangeForAllNotInTarget.value = projectState.isCreateNewChangeForAllNotInTarget();

    useContributorAgreements.configuredValue = p.getUseContributorAgreements();
    useSignedOffBy.configuredValue = p.getUseSignedOffBy();
    useContentMerge.configuredValue = p.getUseContentMerge();
    requireChangeId.configuredValue = p.getRequireChangeID();
    createNewChangeForAllNotInTarget.configuredValue = p.getCreateNewChangeForAllNotInTarget();
    enableSignedPush.configuredValue = p.getEnableSignedPush();
    requireSignedPush.configuredValue = p.getRequireSignedPush();
    rejectImplicitMerges.configuredValue = p.getRejectImplicitMerges();

    ProjectState parentState = Iterables.getFirst(projectState.parents(), null);
    if (parentState != null) {
      useContributorAgreements.inheritedValue = parentState.isUseContributorAgreements();
      useSignedOffBy.inheritedValue = parentState.isUseSignedOffBy();
      useContentMerge.inheritedValue = parentState.isUseContentMerge();
      requireChangeId.inheritedValue = parentState.isRequireChangeID();
      createNewChangeForAllNotInTarget.inheritedValue =
          parentState.isCreateNewChangeForAllNotInTarget();
      enableSignedPush.inheritedValue = projectState.isEnableSignedPush();
      requireSignedPush.inheritedValue = projectState.isRequireSignedPush();
      rejectImplicitMerges.inheritedValue = projectState.isRejectImplicitMerges();
    }

    this.useContributorAgreements = useContributorAgreements;
    this.useSignedOffBy = useSignedOffBy;
    this.useContentMerge = useContentMerge;
    this.requireChangeId = requireChangeId;
    this.rejectImplicitMerges = rejectImplicitMerges;
    this.createNewChangeForAllNotInTarget = createNewChangeForAllNotInTarget;
    if (serverEnableSignedPush) {
      this.enableSignedPush = enableSignedPush;
      this.requireSignedPush = requireSignedPush;
    }

    MaxObjectSizeLimitInfo maxObjectSizeLimit = new MaxObjectSizeLimitInfo();
    maxObjectSizeLimit.value =
        config.getEffectiveMaxObjectSizeLimit(projectState) == config.getMaxObjectSizeLimit()
            ? config.getFormattedMaxObjectSizeLimit()
            : p.getMaxObjectSizeLimit();
    maxObjectSizeLimit.configuredValue = p.getMaxObjectSizeLimit();
    maxObjectSizeLimit.inheritedValue = config.getFormattedMaxObjectSizeLimit();
    this.maxObjectSizeLimit = maxObjectSizeLimit;

    this.submitType = p.getSubmitType();
    this.state =
        p.getState() != com.google.gerrit.extensions.client.ProjectState.ACTIVE
            ? p.getState()
            : null;

    this.commentlinks = new LinkedHashMap<>();
    for (CommentLinkInfo cl : projectState.getCommentLinks()) {
      this.commentlinks.put(cl.name, cl);
    }

    pluginConfig =
        getPluginConfig(control.getProjectState(), pluginConfigEntries, cfgFactory, allProjects);

    actions = new TreeMap<>();
    for (UiAction.Description d :
        UiActions.from(views, new ProjectResource(control), Providers.of(control.getUser()))) {
      actions.put(d.getId(), new ActionInfo(d));
    }
    this.theme = projectState.getTheme();
  }