/* * Copyright (C) 2011 Red Hat, Inc. and/or its affiliates. * * 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.marshalling.rebind; import java.io.File; import org.jboss.errai.codegen.meta.MetaClass; import org.jboss.errai.codegen.util.ClassChangeUtil; import org.jboss.errai.common.metadata.RebindUtils; import org.jboss.errai.config.rebind.AbstractAsyncGenerator; import org.jboss.errai.config.rebind.EnvUtil; import org.jboss.errai.config.rebind.GenerateAsync; import org.jboss.errai.marshalling.client.api.MarshallerFactory; import org.jboss.errai.marshalling.rebind.util.MarshallingGenUtil; import org.jboss.errai.marshalling.rebind.util.OutputDirectoryUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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; /** * @author Mike Brock <cbrock@redhat.com> */ @GenerateAsync(MarshallerFactory.class) public class MarshallersGenerator extends AbstractAsyncGenerator { static final Logger logger = LoggerFactory.getLogger(Generator.class); public static final String SERVER_MARSHALLER_PACKAGE_NAME = "org.jboss.errai"; public static final String SERVER_MARSHALLER_CLASS_NAME = "ServerMarshallingFactoryImpl"; private static final String SERVER_MARSHALLER_OUTPUT_DIR_PROP = "errai.marshalling.server.classOutput"; private static final String SERVER_MARSHALLER_OUTPUT_ENABLED_PROP = "errai.marshalling.server.classOutput.enabled"; private static final String SERVER_MARSHALLER_OUTPUT_DIR = System.getProperty(SERVER_MARSHALLER_OUTPUT_DIR_PROP) != null ? System.getProperty(SERVER_MARSHALLER_OUTPUT_DIR_PROP) : null; private static final boolean SERVER_MARSHALLER_OUTPUT_ENABLED = Boolean.valueOf(System.getProperty(SERVER_MARSHALLER_OUTPUT_ENABLED_PROP, "true")); private static final Logger log = LoggerFactory.getLogger(MarshallersGenerator.class); /** * Simple name of class to be generated */ private final String className = MarshallerFactory.class.getSimpleName() + "Impl"; /** * Package name of class to be generated */ private final String packageName = MarshallerFactory.class.getPackage().getName(); @Override public String generate(final TreeLogger logger, final GeneratorContext context, final String typeName) throws UnableToCompleteException { logger.log(TreeLogger.INFO, "Generating Marshallers Bootstrapper..."); return startAsyncGeneratorsAndWaitFor(MarshallerFactory.class, context, logger, packageName, className); } private static final String sourceOutputTemp = RebindUtils.getTempDirectory() + "/errai.marshalling/gen/"; private static volatile String _serverMarshallerCache; private static volatile String _clientMarshallerCache; private static final Object generatorLock = new Object(); @Override protected String generate(final TreeLogger treeLogger, final GeneratorContext context) { synchronized (generatorLock) { final boolean junitOrDevMode = !EnvUtil.isProdMode(); if (SERVER_MARSHALLER_OUTPUT_ENABLED && MarshallingGenUtil.isUseStaticMarshallers()) { final String serverSource; if (!junitOrDevMode && _serverMarshallerCache != null) { serverSource = _serverMarshallerCache; } else { serverSource = MarshallerGeneratorFactory.getFor(context, MarshallerOutputTarget.Java) .generate(SERVER_MARSHALLER_PACKAGE_NAME, SERVER_MARSHALLER_CLASS_NAME); _serverMarshallerCache = serverSource; } if (junitOrDevMode) { if (MarshallingGenUtil.isUseStaticMarshallers()) { final String tmpLocation = new File(sourceOutputTemp).getAbsolutePath(); log.info("*** using temporary path: " + tmpLocation + " ***"); try { OutputDirectoryUtil.generateClassFileInTmpDir(SERVER_MARSHALLER_PACKAGE_NAME, SERVER_MARSHALLER_CLASS_NAME, serverSource, tmpLocation); } catch (final Throwable t) { throw new RuntimeException("failed to load server marshallers", t); } } } else if (SERVER_MARSHALLER_OUTPUT_DIR != null || OutputDirectoryUtil.OUTPUT_DIR.isPresent()) { final String outputDir = (SERVER_MARSHALLER_OUTPUT_DIR != null ? SERVER_MARSHALLER_OUTPUT_DIR : OutputDirectoryUtil.OUTPUT_DIR.get()); ClassChangeUtil.generateClassFile(SERVER_MARSHALLER_PACKAGE_NAME, SERVER_MARSHALLER_CLASS_NAME, sourceOutputTemp, serverSource, outputDir); logger.info("** deposited marshaller class in : " + new File(outputDir).getAbsolutePath()); } else { writeServerSideMarshallerToDiscoveredOutputDirs(context, serverSource); } } else { logger.info("not emitting server marshaller class"); } if (!junitOrDevMode && _clientMarshallerCache != null) { return _clientMarshallerCache; } return _clientMarshallerCache = MarshallerGeneratorFactory.getFor(context, MarshallerOutputTarget.GWT) .generate(packageName, className, new MarshallerGenerationCallback() { @Override public void callback(final MetaClass marshalledType) { addCacheRelevantClass(marshalledType); } }); } } private static void writeServerSideMarshallerToDiscoveredOutputDirs(final GeneratorContext context, final String source) { OutputDirectoryUtil.generateClassFileInDiscoveredDirs(context, SERVER_MARSHALLER_PACKAGE_NAME, SERVER_MARSHALLER_CLASS_NAME, sourceOutputTemp, source); } @Override protected boolean isRelevantClass(final MetaClass clazz) { return EnvUtil.isPortableType(clazz); } }