All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.swm.gwt.linker.PermutationMapLinker Maven / Gradle / Ivy

The newest version!
package de.swm.gwt.linker;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeMap;

import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.AbstractLinker;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.ConfigurationProperty;
import com.google.gwt.core.ext.linker.EmittedArtifact;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.Shardable;
import com.google.gwt.core.ext.linker.SyntheticArtifact;
import com.google.gwt.core.ext.linker.impl.SelectionInformation;

import de.swm.gwt.linker.server.BindingProperty;

/**
 * @author Daniel Kurka (see http://code.google.com/p/mgwt/)
 *
 *
 * Modified by Guido Wimmel (SWM Services GmbH):
 * consistently use "/" as path separators in generated file
 */

@LinkerOrder(LinkerOrder.Order.POST)
@Shardable
public class PermutationMapLinker extends AbstractLinker {

	public static final String EXTERNAL_FILES_CONFIGURATION_PROPERTY_NAME = "html5manifestlinker_files";
	public static final String PERMUTATION_MANIFEST_FILE_ENDING = ".manifest";
	public static final String PERMUTATION_FILE_ENDING = ".perm.xml";
	public static final String MANIFEST_MAP_FILE_NAME = "manifest.map";

	private XMLPermutationProvider xmlPermutationProvider;

	public PermutationMapLinker() {
		xmlPermutationProvider = new XMLPermutationProvider();
		manifestWriter = new ManifestWriter();
	}

	private ManifestWriter manifestWriter;

	@Override
	public String getDescription() {
		return "PermutationMapLinker";
	}

	@Override
	public ArtifactSet link(TreeLogger logger, LinkerContext context, ArtifactSet artifacts, boolean onePermutation)
			throws UnableToCompleteException {
		
		if (onePermutation) {
			Map> permutationMap = buildPermutationMap(logger, context, artifacts);
			Set>> entrySet = permutationMap.entrySet();

			// since we are in onePermutation there should be just one
			// strongName
			// better make sure..
			if (permutationMap.size() != 1) {
				logger.log(Type.ERROR, "There should be only one permutation right now, but there were: '"
						+ permutationMap.size() + "'");
				throw new UnableToCompleteException();
			}

			Entry> next = entrySet.iterator().next();
			String strongName = next.getKey();
			Set bindingProperties = next.getValue();

			logger.log(Type.INFO, "Linker call for specific permutation with strong name " + strongName
					+ " and binding properties " + bindingProperties);

			// all artifacts for this compilation
			Set artifactsForCompilation = getArtifactsForCompilation(logger, context, artifacts);

			ArtifactSet toReturn = new ArtifactSet(artifacts);
			PermutationArtifact permutationArtifact = new PermutationArtifact(PermutationMapLinker.class, strongName,
					artifactsForCompilation, bindingProperties);
			toReturn.add(permutationArtifact);
			return toReturn;
		}

		ArtifactSet toReturn = new ArtifactSet(artifacts);
		Map> map = buildPermutationMap(logger, context, artifacts);

		if (map.size() == 0) {
			// hosted mode
			return toReturn;
		}

		logger.log(Type.INFO, "Final linker call with binding properties map " + map);

		Map permutationArtifactAsMap = getPermutationArtifactAsMap(artifacts);

		Set externalFiles = getExternalFiles(logger, context);

		Set allPermutationFiles = getAllPermutationFiles(permutationArtifactAsMap);

		// get all artifacts
		Set allArtifacts = getArtifactsForCompilation(logger, context, artifacts);

		for (Entry entry : permutationArtifactAsMap.entrySet()) {
			PermutationArtifact permutationArtifact = entry.getValue();
			// make a copy of all artifacts
			HashSet filesForCurrentPermutation = new HashSet(allArtifacts);
			// remove all permutations
			filesForCurrentPermutation.removeAll(allPermutationFiles);
			// add files of the one permutation we are interested in
			// leaving the common stuff for all permutations in...
			filesForCurrentPermutation.addAll(entry.getValue().getPermutationFiles());

			String permXml = buildPermXml(logger, permutationArtifact, filesForCurrentPermutation, externalFiles);

			// emit permutation information file
			SyntheticArtifact emitString = emitString(logger, permXml, permutationArtifact.getPermutationName()
					+ PERMUTATION_FILE_ENDING);
			toReturn.add(emitString);

			// build manifest
			String maniFest = buildManiFest(entry.getKey(), filesForCurrentPermutation, externalFiles);
			toReturn.add(emitString(logger, maniFest, entry.getKey() + PERMUTATION_MANIFEST_FILE_ENDING));

		}

		toReturn.add(createPermutationMap(logger, map));
		return toReturn;

	}

	protected String buildPermXml(TreeLogger logger, PermutationArtifact permutationArtifact,
			Set gwtCompiledFiles, Set otherResources) throws UnableToCompleteException {
		HashSet namesForPermXml = new HashSet(gwtCompiledFiles);
		namesForPermXml.addAll(otherResources);

		try {
			return xmlPermutationProvider.writePermutationInformation(permutationArtifact.getPermutationName(),
					permutationArtifact.getBindingProperties(), namesForPermXml);
		} catch (XMLPermutationProviderException e) {
			logger.log(Type.ERROR, "can not build xml for permutation file", e);
			throw new UnableToCompleteException();
		}

	}

	/**
	 * @param permutationArtifactAsMap
	 * @return
	 */
	protected Set getAllPermutationFiles(Map permutationArtifactAsMap) {
		Set allPermutationFiles = new HashSet();

		for (Entry entry : permutationArtifactAsMap.entrySet()) {
			allPermutationFiles.addAll(entry.getValue().getPermutationFiles());
		}
		return allPermutationFiles;
	}

	protected Map getPermutationArtifactAsMap(ArtifactSet artifacts) {
		Map hashMap = new HashMap();
		for (PermutationArtifact permutationArtifact : artifacts.find(PermutationArtifact.class)) {
			hashMap.put(permutationArtifact.getPermutationName(), permutationArtifact);
		}
		return hashMap;
	}

	protected boolean shouldArtifactBeInManifest(String pathName) {
		if (pathName.endsWith("symbolMap") || pathName.endsWith(".xml.gz") || pathName.endsWith("rpc.log")
				|| pathName.endsWith("gwt.rpc") || pathName.endsWith("manifest.txt")
				|| pathName.startsWith("rpcPolicyManifest") || pathName.startsWith("soycReport")
				|| pathName.endsWith(".cssmap") || pathName.endsWith("hosted.html")) {
			return false;
		}

		// TODO reg exp

		return true;
	}

	protected Set getArtifactsForCompilation(TreeLogger logger, LinkerContext context, ArtifactSet artifacts) {
		Set artifactNames = new HashSet();
		for (EmittedArtifact artifact : artifacts.find(EmittedArtifact.class)) {
			String pathName = artifact.getPartialPath();

			if (shouldArtifactBeInManifest(pathName)) {
				artifactNames.add(context.getModuleName() + "/" + pathName.replace('\\', '/'));
			}
		}

		return artifactNames;

	}

	protected String buildManiFest(String moduleName, Set cacheResources, Set externalFiles) {
		return manifestWriter.writeManifest(externalFiles, cacheResources);
	}

	protected Set getExternalFiles(TreeLogger logger, LinkerContext context) {
		HashSet set = new HashSet();
		SortedSet properties = context.getConfigurationProperties();
		for (ConfigurationProperty configurationProperty : properties) {
			String name = configurationProperty.getName();
			if (EXTERNAL_FILES_CONFIGURATION_PROPERTY_NAME.equals(name)) {
				for (String value : configurationProperty.getValues()) {
					set.add(value);
				}
			}
		}

		return set;
	}

	protected EmittedArtifact createPermutationMap(TreeLogger logger, Map> map)
			throws UnableToCompleteException {

		try {
			String string = xmlPermutationProvider.serializeMap(map);
			return emitString(logger, string, MANIFEST_MAP_FILE_NAME);
		} catch (XMLPermutationProviderException e) {
			logger.log(Type.ERROR, "can not build manifest map", e);
			throw new UnableToCompleteException();
		}

	}

	protected Map> buildPermutationMap(TreeLogger logger, LinkerContext context,
			ArtifactSet artifacts) throws UnableToCompleteException {

		HashMap> map = new HashMap>();

		for (SelectionInformation result : artifacts.find(SelectionInformation.class)) {
			Set list = new HashSet();
			map.put(result.getStrongName(), list);

			TreeMap propMap = result.getPropMap();
			Set> set = propMap.entrySet();

			for (Entry entry : set) {
				BindingProperty bindingProperty = new BindingProperty(entry.getKey(), entry.getValue());
				list.add(bindingProperty);
			}

		}

		return map;

	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy