Package com.google.gwt.chrome.crx.linker

Source Code of com.google.gwt.chrome.crx.linker.ExtensionGenerator

/*
* Copyright 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.gwt.chrome.crx.linker;

import com.google.gwt.chrome.crx.client.Extension;
import com.google.gwt.chrome.crx.client.Extension.ManifestInfo;
import com.google.gwt.chrome.crx.linker.ExtensionArtifact.IconInfo;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dev.util.Util;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;

import javax.imageio.ImageIO;

/**
* Generator responsible for extracting the Specification annotations from
* Extension subclasses.
*/
public class ExtensionGenerator extends Generator {

  private static IconInfo[] createIconResources(TreeLogger logger,
      GeneratorContext context, JClassType userType, String[] icons)
      throws UnableToCompleteException {
    final IconInfo[] result = new IconInfo[icons.length];
    for (int i = 0, n = icons.length; i < n; ++i) {
      final String icon = icons[i];

      // Open a stream for the icon resource.
      InputStream iconStream = ExtensionGenerator.class.getClassLoader().getResourceAsStream(
          getResourcePath(userType, icon));
      if (iconStream == null) {
        logger.log(TreeLogger.ERROR, "Resource not found on classpath: " + icon);
        throw new UnableToCompleteException();
      }

      try {
        // Read the icon's byte data and decode it to determine the size.
        final byte[] iconData = getBytesFromStream(iconStream);
        assert iconData != null;
        final String strongname = Util.computeStrongName(iconData)
            + getIconExtension(icon);
        result[i] = new IconInfo(strongname, getImageSize(iconData));

        // Write the icon's bytes into GWT resource.
        try {
          final OutputStream resStream = context.tryCreateResource(logger,
              strongname);
          if (resStream != null) {
            resStream.write(iconData);
            context.commitResource(logger, resStream);
          }
        } catch (IOException e) {
          logger.log(TreeLogger.ERROR, "Unable to write resource: " + icon, e);
          throw new UnableToCompleteException();
        }

      } catch (IOException e) {
        logger.log(TreeLogger.ERROR, "Unable to read image: " + icon, e);
        throw new UnableToCompleteException();
      }
    }

    return result;
  }

  private static String generateExtensionType(TreeLogger logger,
      GeneratorContext context, JClassType userType, ExtensionArtifact spec) {
    final String subclassName = userType.getSimpleSourceName().replace('.', '_')
        + "_generated";
    final String packageName = userType.getPackage().getName();
    final ClassSourceFileComposerFactory f = new ClassSourceFileComposerFactory(
        packageName, subclassName);
    f.setSuperclass(userType.getQualifiedSourceName());
    final PrintWriter pw = context.tryCreate(logger, packageName, subclassName);
    if (pw != null) {
      final SourceWriter sw = f.createSourceWriter(context, pw);

      final String version = (spec.getVersion() != null) ? spec.getVersion()
          : "";
      sw.println("@Override public String getVersion() {");
      sw.println("  return \"" + GeneratorUtils.toJavaLiteral(version) + "\";");
      sw.println("}");

      sw.commit(logger);
    }
    return f.getCreatedClassName();
  }

  private static byte[] getBytesFromStream(InputStream stream)
      throws IOException {
    final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
    int n;
    final byte[] buffer = new byte[2048];
    while ((n = stream.read(buffer)) >= 0) {
      byteStream.write(buffer, 0, n);
    }
    return byteStream.toByteArray();
  }

  private static String getIconExtension(String icon) {
    final int index = icon.lastIndexOf('.');
    return (index < 0) ? "" : icon.substring(index);
  }

  private static int getImageSize(byte[] data) throws IOException {
    final InputStream stream = new ByteArrayInputStream(data);
    final BufferedImage image = ImageIO.read(stream);
    return Math.max(image.getWidth(), image.getHeight());
  }

  private static String getResourcePath(JClassType userType, String name) {
    final String base = userType.getPackage().getName().replace('.', '/');
    return base + "/" + name;
  }

  private static ExtensionArtifact getSpecification(TreeLogger logger,
      GeneratorContext context, JClassType userType)
      throws UnableToCompleteException {
    final ManifestInfo spec = userType.getAnnotation(Extension.ManifestInfo.class);
    if (spec != null) {
      return new ExtensionArtifact(spec.name(), spec.description(),
          spec.version(), spec.permissions(), spec.updateUrl(),
          createIconResources(logger, context, userType, spec.icons()),
          spec.publicKey());
    }

    logger.log(TreeLogger.ERROR,
        "You need a @Extension.Specification annotation on "
            + userType.getQualifiedSourceName()
            + " or else I'll have to make up a silly name for it.");
    throw new UnableToCompleteException();
  }

  @Override
  public String generate(TreeLogger logger, GeneratorContext context,
      String typeName) throws UnableToCompleteException {
    try {
      final JClassType userType = context.getTypeOracle().getType(typeName);
      final ExtensionArtifact spec = getSpecification(logger, context, userType);
      context.commitArtifact(logger, spec);
      return generateExtensionType(logger, context, userType, spec);
    } catch (NotFoundException e) {
      // TODO(knorton): Better error message.
      logger.log(TreeLogger.ERROR, "Unknown Type: " + typeName);
      throw new UnableToCompleteException();
    }
  }
}
TOP

Related Classes of com.google.gwt.chrome.crx.linker.ExtensionGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.