Java tutorial
/* * Copyright 2010 JBoss, a divison Red Hat, 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 org.jboss.errai.workspaces.rebind; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.ResourceBundle; import java.util.Set; import org.jboss.errai.bus.rebind.ScannerSingleton; import org.jboss.errai.bus.server.annotations.security.RequireRoles; import org.jboss.errai.bus.server.service.metadata.MetaDataScanner; import org.jboss.errai.ioc.rebind.ioc.codegen.Context; import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClass; import org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClassFactory; import org.jboss.errai.ioc.rebind.ioc.codegen.util.Stmt; import org.jboss.errai.workspaces.client.api.ProvisioningCallback; import org.jboss.errai.workspaces.client.api.WidgetProvider; import org.jboss.errai.workspaces.client.api.annotations.GroupOrder; import org.jboss.errai.workspaces.client.api.annotations.LoadTool; import org.jboss.errai.workspaces.client.api.annotations.LoadToolSet; import org.jboss.errai.workspaces.client.api.annotations.LoginComponent; 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.core.ext.typeinfo.TypeOracle; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; public class WorkspaceLoaderBootstrapGenerator extends Generator { /** * Simple name of class to be generated */ private String className = null; /** * Package name of class to be generated */ private String packageName = null; private final static String TOOLSET_PROFILE = "toolset-profile.properties"; private TypeOracle typeOracle; private volatile int counter = 0; // inherited generator method public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { typeOracle = context.getTypeOracle(); try { // get classType and save instance variables JClassType classType = typeOracle.getType(typeName); packageName = classType.getPackage().getName(); className = classType.getSimpleSourceName() + "Impl"; // Generate class source code generateClass(logger, context); } catch (Exception e) { // record sendNowWith logger that Map generation threw an exception logger.log(TreeLogger.ERROR, "Error generating bootstrap loader", e); } // return the fully qualifed name of the class generated return packageName + "." + className; } /** * Generate source code for new class. Class extends <code>HashMap</code>. * * @param logger * Logger object * @param context * Generator context */ private void generateClass(TreeLogger logger, GeneratorContext context) { // get print writer that receives the source code PrintWriter printWriter = context.tryCreate(logger, packageName, className); // print writer if null, source code has ALREADY been generated, if (printWriter == null) return; // init composer, set class properties, create source writer ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, className); composer.addImplementedInterface("org.jboss.errai.workspaces.client.framework.WorkspaceConfig"); SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter); // generator constructor source code generateBootstrapClass(context, logger, sourceWriter); // close generated class sourceWriter.outdent(); sourceWriter.println("}"); // commit generated class context.commit(logger, printWriter); } private void generateBootstrapClass(final GeneratorContext context, final TreeLogger logger, final SourceWriter sourceWriter) { ResourceBundle bundle; try { bundle = ResourceBundle.getBundle("org.jboss.errai.workspaces.rebind.WorkspaceModules"); } catch (Exception e) { logger.log(TreeLogger.Type.ERROR, "can't find WorkspaceModules.properties in classpath"); logger.log(TreeLogger.Type.ERROR, e.getMessage()); throw new RuntimeException(); } // start constructor source generation sourceWriter.println("public " + className + "() { "); sourceWriter.indent(); sourceWriter.println("super();"); sourceWriter.outdent(); sourceWriter.println("}"); sourceWriter.println( "public void configure(org.jboss.errai.workspaces.client.framework.ToolContainer workspace) { "); sourceWriter.outdent(); // toolset profile (acts as whitelist). Used with BPM console atm final List<String> enabledTools = new ArrayList<String>(); InputStream in = getClass().getClassLoader().getResourceAsStream(TOOLSET_PROFILE); if (in != null) { try { BufferedReader input = new BufferedReader(new InputStreamReader(in)); try { String line = null; while ((line = input.readLine()) != null) { // ignore comments and empty lines if (line.equals("") || line.startsWith("#")) continue; enabledTools.add(line); } } finally { input.close(); } } catch (IOException ex) { throw new RuntimeException("Error reading '" + TOOLSET_PROFILE + "'"); } } for (Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) { String key = keys.nextElement(); sourceWriter.println("new " + bundle.getString(key) + "().initModule(errai);"); } final boolean applyFilter = in != null; MetaDataScanner scanner = ScannerSingleton.getOrCreateInstance(); /** * LoadToolSet */ Set<Class<?>> toolsets = scanner.getTypesAnnotatedWith(LoadToolSet.class); for (Class<?> toolSetClass : toolsets) { JClassType clazz = typeOracle.findType(toolSetClass.getName()); MetaClass metaClass = MetaClassFactory.get(clazz); if ((!applyFilter || enabledTools.contains(clazz.getQualifiedSourceName()))) { sourceWriter.println( "workspace.addToolSet(" + Stmt.newObject(metaClass).generate(Context.create()) + ");"); logger.log(TreeLogger.Type.INFO, "Adding Errai Toolset: " + clazz.getQualifiedSourceName()); } } /** * LoadTool */ Set<Class<?>> tools = scanner.getTypesAnnotatedWith(LoadTool.class); for (Class<?> toolClass : tools) { JClassType clazz = typeOracle.findType(toolClass.getName()); MetaClass metaClass = MetaClassFactory.get(clazz); if ((!applyFilter || enabledTools.contains(clazz.getQualifiedSourceName()))) { LoadTool loadTool = clazz.getAnnotation(LoadTool.class); logger.log(TreeLogger.Type.INFO, "Adding Errai Tool: " + clazz.getQualifiedSourceName()); if (clazz.isAnnotationPresent(RequireRoles.class)) { RequireRoles requireRoles = clazz.getAnnotation(RequireRoles.class); StringBuilder rolesBuilder = new StringBuilder("new String[] {"); String[] roles = requireRoles.value(); for (int i = 0; i < roles.length; i++) { rolesBuilder.append("\"").append(roles[i].trim()).append("\""); if ((i + 1) < roles.length) rolesBuilder.append(", "); } rolesBuilder.append("}"); generateWidgetProvisioning(context, clazz.getQualifiedSourceName(), loadTool, rolesBuilder, logger, sourceWriter); } else { generateWidgetProvisioning(context, clazz.getQualifiedSourceName(), loadTool, null, logger, sourceWriter); } } else if (clazz.isAnnotationPresent(LoginComponent.class)) { sourceWriter.println("workspace.setLoginComponent(new " + clazz.getQualifiedSourceName() + "());"); } } /** * Group order */ Set<Class<?>> groupOrderClasses = scanner.getTypesAnnotatedWith(GroupOrder.class); for (Class<?> clazz : groupOrderClasses) { GroupOrder groupOrder = clazz.getAnnotation(GroupOrder.class); if ("".equals(groupOrder.value().trim())) return; String[] order = groupOrder.value().split(","); sourceWriter.print("workspace.setPreferredGroupOrdering(new String[] {"); for (int i = 0; i < order.length; i++) { sourceWriter.print("\""); sourceWriter.print(order[i].trim()); sourceWriter.print("\""); if (i + 1 < order.length) { sourceWriter.print(","); } } sourceWriter.println("});"); } // wrap up sourceWriter.outdent(); sourceWriter.println("}"); } public void generateWidgetProvisioning(final GeneratorContext context, String className, final LoadTool loadTool, final StringBuilder rolesBuilder, final TreeLogger logger, final SourceWriter writer) { MetaClass type; MetaClass widgetType; try { type = MetaClassFactory.get(typeOracle.getType(className)); widgetType = MetaClassFactory.get(typeOracle.getType(Widget.class.getName())); } catch (NotFoundException e) { throw new RuntimeException("error bootstrapping: " + className, e); } if (widgetType.isAssignableFrom(type)) { writer.println(WidgetProvider.class.getName() + " widgetProvider" + (++counter) + " = new " + WidgetProvider.class.getName() + "() {"); writer.outdent(); writer.println("public void provideWidget(" + ProvisioningCallback.class.getName() + " callback) {"); writer.outdent(); writer.println("callback.onSuccess(" + Stmt.newObject(type).generate(Context.create()) + ");"); writer.outdent(); writer.println("}"); writer.outdent(); writer.println("};"); } writer.print("workspace.addTool(\"" + loadTool.group() + "\"," + " \"" + loadTool.name() + "\", \"" + loadTool.icon() + "\", " + loadTool.multipleAllowed() + ", " + loadTool.priority() + ", " + Stmt.newObject(type).generate(Context.create())); if (rolesBuilder == null) { writer.println(");"); } else { writer.println(", " + rolesBuilder.toString() + ");"); } } }