blob: d8f580aa74ac9cb5dc0348f2a5516c73512ca444 [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// 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.gerrit.rebind.css;
import com.google.gerrit.client.css.CssReference;
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.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.util.Util;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
public class CssGenerator extends Generator {
private static final String LDR_SUFFIX = "_Loader";
@Override
public String generate(TreeLogger logger, final GeneratorContext ctx,
final String requestedClass) throws UnableToCompleteException {
logger =
logger.branch(TreeLogger.DEBUG,
"Generating client proxy for css loading interface '"
+ requestedClass + "'", null);
final TypeOracle typeOracle = ctx.getTypeOracle();
final JClassType ldrInf = typeOracle.findType(requestedClass);
if (ldrInf == null) {
logger.log(TreeLogger.ERROR, "Unable to find metadata for type '"
+ requestedClass + "'", null);
throw new UnableToCompleteException();
}
if (ldrInf.isInterface() == null) {
logger.log(TreeLogger.ERROR, ldrInf.getQualifiedSourceName()
+ " is not an interface", null);
throw new UnableToCompleteException();
}
final SourceWriter w = getSourceWriter(logger, ctx, ldrInf);
if (w != null) {
try {
writeClass(logger, ctx, w, ldrInf);
} catch (Exception e) {
logger.log(TreeLogger.ERROR, "Cannot create '"
+ ldrInf.getQualifiedSourceName() + "'", e);
throw new UnableToCompleteException();
}
}
return getProxyQualifiedName(ldrInf);
}
private void writeClass(TreeLogger logger, final GeneratorContext ctx,
final SourceWriter w, final JClassType ldrInf) throws IOException,
UnableToCompleteException {
final String srcname =
ldrInf.getQualifiedSourceName().replace('.', '/') + ".css";
final InputStream in =
getClass().getClassLoader().getResourceAsStream(srcname);
if (in == null) {
throw new FileNotFoundException(srcname);
}
final ByteArrayOutputStream tmp = new ByteArrayOutputStream();
try {
final byte[] buf = new byte[2048];
int n;
while ((n = in.read(buf)) >= 0) {
tmp.write(buf, 0, n);
}
tmp.close();
} finally {
in.close();
}
final byte[] rawcss = tmp.toByteArray();
final String outname = Util.computeStrongName(rawcss) + ".cache.css";
final OutputStream out = ctx.tryCreateResource(logger, outname);
if (out != null) {
out.write(rawcss);
ctx.commitResource(logger, out);
}
w.println("public CssReference load() {");
w.indent();
w.println("return new CssReference(\"" + escape(outname) + "\");");
w.outdent();
w.println("}");
w.commit(logger);
}
private static SourceWriter getSourceWriter(final TreeLogger logger,
final GeneratorContext ctx, final JClassType ldrInf) {
final JPackage servicePkg = ldrInf.getPackage();
final String pkgn = servicePkg == null ? "" : servicePkg.getName();
final PrintWriter pw;
final ClassSourceFileComposerFactory cf;
pw = ctx.tryCreate(logger, pkgn, getProxySimpleName(ldrInf));
if (pw == null) {
return null;
}
cf = new ClassSourceFileComposerFactory(pkgn, getProxySimpleName(ldrInf));
cf.addImport(CssReference.class.getName());
cf.addImplementedInterface(ldrInf.getErasedType().getQualifiedSourceName());
return cf.createSourceWriter(ctx, pw);
}
private static String getProxyQualifiedName(final JClassType ldrInf) {
final String[] name = synthesizeTopLevelClassName(ldrInf, LDR_SUFFIX);
return name[0].length() == 0 ? name[1] : name[0] + "." + name[1];
}
private static String getProxySimpleName(final JClassType ldrInf) {
return synthesizeTopLevelClassName(ldrInf, LDR_SUFFIX)[1];
}
private static String[] synthesizeTopLevelClassName(JClassType type,
String suffix) {
// Gets the basic name of the type. If it's a nested type, the type name
// will contains dots.
//
String className;
String packageName;
JType leafType = type.getLeafType();
if (leafType.isPrimitive() != null) {
className = leafType.getSimpleSourceName();
packageName = "";
} else {
JClassType classOrInterface = leafType.isClassOrInterface();
assert (classOrInterface != null);
className = classOrInterface.getName();
packageName = classOrInterface.getPackage().getName();
}
JArrayType isArray = type.isArray();
if (isArray != null) {
className += "_Array_Rank_" + isArray.getRank();
}
// Add the meaningful suffix.
//
className += suffix;
// Make it a top-level name.
//
className = className.replace('.', '_');
return new String[] {packageName, className};
}
}