| /******************************************************************************* |
| * Copyright (c) 2004, 2007 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.wtp.releng.tools.component.api; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.eclipse.wtp.releng.tools.component.CommandOptionParser; |
| import org.eclipse.wtp.releng.tools.component.IClazz; |
| import org.eclipse.wtp.releng.tools.component.IClazzVisitor; |
| import org.eclipse.wtp.releng.tools.component.ILocation; |
| import org.eclipse.wtp.releng.tools.component.IPluginXML; |
| import org.eclipse.wtp.releng.tools.component.api.ComponentUse; |
| import org.eclipse.wtp.releng.tools.component.internal.AbstractEmitter; |
| import org.eclipse.wtp.releng.tools.component.internal.ComponentXML; |
| import org.eclipse.wtp.releng.tools.component.internal.FieldRef; |
| import org.eclipse.wtp.releng.tools.component.internal.FileLocation; |
| import org.eclipse.wtp.releng.tools.component.internal.MethodRef; |
| import org.eclipse.wtp.releng.tools.component.internal.Plugin; |
| |
| public class ComponentUseEmitter extends AbstractEmitter implements IClazzVisitor |
| { |
| public static final String OPTION_ECLIPSE_DIR = "eclipseDir"; |
| public static final String OPTION_COMPONENT_XML_DIR = "compXMLDir"; |
| public static final String OPTION_COMPONENT_USE_DIR = "compUseDir"; |
| public static final String OPTION_INCLUDE = "include"; |
| public static final String OPTION_EXCLUDE = "exclude"; |
| public static final String OPTION_CLASS_REF_ONLY = "classRefOnly"; |
| public static final String OPTION_DEBUG = "debug"; |
| private String compUseDir; |
| private Map pluginId2Plugin; |
| private Map fragmentId2Fragment; |
| private Map compLoc2CompXML; |
| private List classUseIncludes; |
| private List classUseIncludesMatch; |
| private List classUseExcludes; |
| private List classUseExcludesMatch; |
| private boolean classRefOnly; |
| private boolean debug; |
| private ComponentUse compUse; |
| |
| public ComponentUseEmitter(String compUseDir) |
| { |
| this.compUseDir = addTrailingSeperator(compUseDir); |
| classRefOnly = false; |
| debug = false; |
| } |
| |
| public void init(List eclipseDirs, List compXMLDirs) |
| { |
| compLoc2CompXML = new HashMap(); |
| pluginId2Plugin = new HashMap(); |
| fragmentId2Fragment = new HashMap(); |
| for (Iterator it = eclipseDirs.iterator(); it.hasNext();) |
| { |
| File eclipseFile = new File(addTrailingSeperator((String)it.next())); |
| if (eclipseFile.exists()) |
| harvestPlugins(eclipseFile, pluginId2Plugin, fragmentId2Fragment); |
| } |
| linkPluginsAndFragments(pluginId2Plugin, fragmentId2Fragment); |
| for (Iterator it = compXMLDirs.iterator(); it.hasNext();) |
| { |
| File compXMLFile = new File(addTrailingSeperator((String)it.next())); |
| if (compXMLFile.exists()) |
| harvestComponents(compXMLFile, compLoc2CompXML); |
| } |
| } |
| |
| public void init(Map compLoc2CompXML, Map pluginId2Plugin, Map fragmentId2Fragment) |
| { |
| this.compLoc2CompXML = compLoc2CompXML; |
| this.pluginId2Plugin = pluginId2Plugin; |
| this.fragmentId2Fragment = fragmentId2Fragment; |
| } |
| |
| /** |
| * @return Returns the classRefOnly. |
| */ |
| public boolean isClassRefOnly() |
| { |
| return classRefOnly; |
| } |
| |
| /** |
| * @param classRefOnly |
| * The classRefOnly to set. |
| */ |
| public void setClassRefOnly(boolean classRefOnly) |
| { |
| this.classRefOnly = classRefOnly; |
| } |
| |
| /** |
| * @return Returns the debug. |
| */ |
| public boolean isDebug() |
| { |
| return debug; |
| } |
| |
| /** |
| * @param debug |
| * The debug to set. |
| */ |
| public void setDebug(boolean debug) |
| { |
| this.debug = debug; |
| } |
| |
| public List getClassUseIncludes() |
| { |
| return classUseIncludes; |
| } |
| |
| public void setClassUseIncludes(List includes) |
| { |
| this.classUseIncludes = includes; |
| } |
| |
| public List getClassUseIncludesMatch() |
| { |
| return classUseIncludesMatch; |
| } |
| |
| public void setClassUseIncludesMatch(List includesMatch) |
| { |
| this.classUseIncludesMatch = includesMatch; |
| } |
| |
| public List getClassUseExcludes() |
| { |
| return classUseExcludes; |
| } |
| |
| public void setClassUseExcludes(List excludes) |
| { |
| this.classUseExcludes = excludes; |
| } |
| |
| public List getClassUseExcludesMatch() |
| { |
| return classUseExcludesMatch; |
| } |
| |
| public void setClassUseExcludesMatch(List excludesMatch) |
| { |
| this.classUseExcludesMatch = excludesMatch; |
| } |
| |
| public void genComponentUseXML() throws IOException |
| { |
| for (Iterator it = compLoc2CompXML.keySet().iterator(); it.hasNext();) |
| genComponentUseXML((String)it.next()); |
| } |
| |
| public ComponentUse genComponentUseXML(String compLoc) throws IOException |
| { |
| ComponentXML compXML = (ComponentXML)compLoc2CompXML.get(compLoc); |
| if (compXML != null) |
| { |
| compXML.load(); |
| String compName = compXML.getName(); |
| compUse = newComponentUse(compXML); |
| for (Iterator pluginsIt = compXML.getPlugins().iterator(); pluginsIt.hasNext();) |
| { |
| IPluginXML pluginXML = (IPluginXML)pluginId2Plugin.get(((Plugin)pluginsIt.next()).getId()); |
| if (pluginXML != null) |
| pluginXML.accept(this); |
| } |
| compXML = null; |
| if (compUseDir != null) |
| System.out.println("Writing component-use.xml for " + compName); |
| compUse.save(); |
| return compUse; |
| } |
| return null; |
| } |
| |
| public ComponentUse genAll() throws IOException |
| { |
| compUse = new ComponentUse(); |
| for (Iterator it = pluginId2Plugin.values().iterator(); it.hasNext();) |
| ((IPluginXML)it.next()).accept(this); |
| return compUse; |
| } |
| |
| public Source genUse(IClazz clazz) |
| { |
| return newSource(clazz); |
| } |
| |
| public boolean visit(IClazz clazz) |
| { |
| if (compUse == null) |
| return false; |
| Source source = newSource(clazz); |
| addSource(compUse, source); |
| return true; |
| } |
| |
| private Source newSource(IClazz clazz) |
| { |
| String className = clazz.getName(); |
| Source source = newSource(clazz.getName()); |
| if (!classRefOnly) |
| { |
| // method references |
| List methodRefs = clazz.getMethodRefs(combineFilters(classUseIncludes, classUseIncludesMatch), combineFilters(classUseExcludes, classUseExcludesMatch), debug); |
| for (Iterator it = methodRefs.iterator(); it.hasNext();) |
| { |
| MethodRef methodRef = (MethodRef)it.next(); |
| String refClassName = methodRef.getClassName(); |
| String methodName = methodRef.getMethodName(); |
| ClassUse classUse; |
| if (isConstructor(methodName)) |
| { |
| // use: instantiate |
| classUse = addUniqueClassUse(source, refClassName, null, null, null, Boolean.TRUE, methodRef.getLines()); |
| } |
| else |
| { |
| classUse = addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null); |
| } |
| MethodUse methodUse = newMethodUse(methodName, methodRef.getMethodDescriptor(), methodRef.getLines()); |
| classUse.getMethodUses().add(methodUse); |
| } |
| clazz.resetMethodRefs(); |
| methodRefs = null; |
| // field references |
| List fieldRefs = clazz.getFieldRefs(combineFilters(classUseIncludes, classUseIncludesMatch), combineFilters(classUseExcludes, classUseExcludesMatch), debug); |
| for (Iterator it = fieldRefs.iterator(); it.hasNext();) |
| { |
| FieldRef fieldRef = (FieldRef)it.next(); |
| String refClassName = fieldRef.getClassName(); |
| ClassUse classUse = addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null); |
| FieldAPI fieldUse = newFieldUse(fieldRef.getFieldName(), fieldRef.getFieldDescriptor(), fieldRef.getLines()); |
| classUse.getFieldAPIs().add(fieldUse); |
| } |
| clazz.resetFieldRefs(); |
| fieldRefs = null; |
| // use: subclass |
| if (!clazz.isInterface()) |
| { |
| String superClass = clazz.getSuperClass(); |
| if (superClass != null && isReportClassUse(className, superClass)) |
| addUniqueClassUse(source, superClass, null, Boolean.TRUE, null, null, null); |
| } |
| // use: implement |
| String[] interfaces = clazz.getInterfaces(); |
| for (int i = 0; i < interfaces.length; i++) |
| if (isReportClassUse(className, interfaces[i])) |
| addUniqueClassUse(source, interfaces[i], null, null, Boolean.TRUE, null, null); |
| } |
| // use: reference |
| Set refClasses = clazz.getReferencedTypes(); |
| for (Iterator refClassesIt = refClasses.iterator(); refClassesIt.hasNext();) |
| { |
| String refClassName = (String)refClassesIt.next(); |
| if (isReportClassUse(className, refClassName)) |
| addUniqueClassUse(source, refClassName, Boolean.TRUE, null, null, null, null); |
| } |
| return source; |
| } |
| |
| private List combineFilters(List filtersStart, List filtersMatch) |
| { |
| List filters = new ArrayList(); |
| if (filtersStart != null) |
| filters.addAll(filtersStart); |
| if (filtersMatch != null) |
| for (Iterator it = filtersMatch.iterator(); it.hasNext();) |
| filters.add(new StringBuffer("*").append((String)it.next()).append("*").toString()); |
| if (filters.size() > 0) |
| return filters; |
| else |
| return null; |
| } |
| |
| private boolean isReportClassUse(String sourceClassName, String classUseName) |
| { |
| if (sourceClassName != null && sourceClassName.equals(classUseName)) |
| return false; |
| if (classUseExcludes != null) |
| for (Iterator it = classUseExcludes.iterator(); it.hasNext();) |
| if (classUseName.startsWith((String)it.next())) |
| return false; |
| if (classUseExcludesMatch != null) |
| for (Iterator it = classUseExcludesMatch.iterator(); it.hasNext();) |
| if (classUseName.indexOf((String)it.next()) != -1) |
| return false; |
| if ((classUseIncludes != null && classUseIncludes.size() > 0) || (classUseIncludesMatch != null && classUseIncludesMatch.size() > 0)) |
| { |
| if (classUseIncludes != null) |
| for (Iterator it = classUseIncludes.iterator(); it.hasNext();) |
| if (classUseName.startsWith((String)it.next())) |
| return true; |
| if (classUseIncludesMatch != null) |
| for (Iterator it = classUseIncludesMatch.iterator(); it.hasNext();) |
| if (classUseName.indexOf((String)it.next()) != -1) |
| return true; |
| return false; |
| } |
| return true; |
| } |
| |
| private boolean isConstructor(String methodName) |
| { |
| return methodName.equals("<init>"); |
| } |
| |
| private void addSource(ComponentUse compUse, Source source) |
| { |
| if (source.getClassUses().size() > 0) |
| compUse.getSources().add(source); |
| } |
| |
| private ClassUse addUniqueClassUse(Source source, String className, Boolean ref, Boolean subclass, Boolean implement, Boolean instantiate, List lines) |
| { |
| for (Iterator it = source.getClassUses().iterator(); it.hasNext();) |
| { |
| ClassUse classUse = (ClassUse)it.next(); |
| if (!classUse.getName().equals(className)) |
| continue; |
| if (ref != null && (classUse.getReference() == null || (ref.booleanValue() != classUse.isReference()))) |
| continue; |
| if (subclass != null && (classUse.getSubclass() == null || (subclass.booleanValue() != classUse.isSubclass()))) |
| continue; |
| if (implement != null && (classUse.getImplement() == null || (implement.booleanValue() != classUse.isImplement()))) |
| continue; |
| if (instantiate != null && (classUse.getInstantiate() == null || (instantiate.booleanValue() != classUse.isInstantiate()))) |
| continue; |
| if (lines != null) |
| classUse.getLines().addAll(lines); |
| return classUse; |
| } |
| ClassUse classUse = newClassUse(className, ref, subclass, implement, instantiate, lines); |
| source.addClassUse(classUse); |
| return classUse; |
| } |
| |
| private ClassUse newClassUse(String className, Boolean ref, Boolean subclass, Boolean implement, Boolean instantiate, List lines) |
| { |
| ClassUse classUse = new ClassUse(); |
| classUse.setName(className); |
| classUse.setReference(ref); |
| classUse.setSubclass(subclass); |
| classUse.setImplement(implement); |
| classUse.setInstantiate(instantiate); |
| if (lines != null) |
| classUse.getLines().addAll(lines); |
| return classUse; |
| } |
| |
| private MethodUse newMethodUse(String methodName, String descriptor, List lines) |
| { |
| MethodUse methodUse = new MethodUse(); |
| methodUse.setName(methodName); |
| methodUse.setDescriptor(descriptor); |
| if (lines != null) |
| methodUse.getLines().addAll(lines); |
| return methodUse; |
| } |
| |
| private FieldUse newFieldUse(String fieldName, String descriptor, List lines) |
| { |
| FieldUse fieldUse = new FieldUse(); |
| fieldUse.setName(fieldName); |
| fieldUse.setDescriptor(descriptor); |
| if (lines != null) |
| fieldUse.getLines().addAll(lines); |
| return fieldUse; |
| } |
| |
| private ComponentUse newComponentUse(ComponentXML compXML) |
| { |
| String compName = compXML.getName(); |
| ILocation location = null; |
| if (compUseDir != null) |
| { |
| StringBuffer sb = new StringBuffer(compUseDir); |
| sb.append(compName); |
| sb.append('/'); |
| sb.append(ComponentUse.CONST_COMPONENT_USE_XML); |
| location = new FileLocation(new File(sb.toString())); |
| } |
| return newComponentUse(compName, location); |
| } |
| |
| private ComponentUse newComponentUse(String name, ILocation location) |
| { |
| ComponentUse compUse = new ComponentUse(); |
| compUse.setName(name); |
| compUse.setLocation(location); |
| return compUse; |
| } |
| |
| private Source newSource(String className) |
| { |
| Source source = new Source(); |
| source.setName(className); |
| return source; |
| } |
| |
| public static void main(String[] args) |
| { |
| CommandOptionParser optionParser = new CommandOptionParser(args); |
| Map options = optionParser.getOptions(); |
| List eclipseDir = (List)options.get(ComponentUseEmitter.OPTION_ECLIPSE_DIR); |
| List compXMLDir = (List)options.get(ComponentUseEmitter.OPTION_COMPONENT_XML_DIR); |
| List compUseDir = (List)options.get(ComponentUseEmitter.OPTION_COMPONENT_USE_DIR); |
| List includes = (List)options.get(ComponentUseEmitter.OPTION_INCLUDE); |
| List excludes = (List)options.get(ComponentUseEmitter.OPTION_EXCLUDE); |
| List classRefOnly = (List)options.get(ComponentUseEmitter.OPTION_CLASS_REF_ONLY); |
| List debug = (List)options.get(ComponentUseEmitter.OPTION_DEBUG); |
| if (eclipseDir == null || compXMLDir == null || compUseDir == null || eclipseDir.size() < 1 || compXMLDir.size() < 1 || compUseDir.size() < 1) |
| { |
| printUsage(); |
| System.exit(-1); |
| } |
| List includesStart = null; |
| List includesMatch = null; |
| if (includes != null) |
| { |
| for (Iterator it = includes.iterator(); it.hasNext();) |
| { |
| String s = (String)it.next(); |
| if (s.charAt(0) == '*' && s.charAt(s.length() - 1) == '*') |
| { |
| if (includesMatch == null) |
| includesMatch = new ArrayList(1); |
| includesMatch.add(s.substring(1, s.length() - 1)); |
| } |
| else |
| { |
| if (includesStart == null) |
| includesStart = new ArrayList(1); |
| includesStart.add(s); |
| } |
| } |
| } |
| List excludesStart = null; |
| List excludesMatch = null; |
| if (excludes != null) |
| { |
| for (Iterator it = excludes.iterator(); it.hasNext();) |
| { |
| String s = (String)it.next(); |
| if (s.charAt(0) == '*' && s.charAt(s.length() - 1) == '*') |
| { |
| if (excludesMatch == null) |
| excludesMatch = new ArrayList(1); |
| excludesMatch.add(s.substring(1, s.length() - 1)); |
| } |
| else |
| { |
| if (excludesStart == null) |
| excludesStart = new ArrayList(1); |
| excludesStart.add(s); |
| } |
| } |
| } |
| ComponentUseEmitter compUseEmitter = new ComponentUseEmitter((String)compUseDir.get(0)); |
| compUseEmitter.setClassUseIncludes(includesStart); |
| compUseEmitter.setClassUseIncludesMatch(includesMatch); |
| compUseEmitter.setClassUseExcludes(excludesStart); |
| compUseEmitter.setClassUseExcludesMatch(excludesMatch); |
| compUseEmitter.setClassRefOnly(classRefOnly != null); |
| compUseEmitter.setDebug(debug != null); |
| compUseEmitter.init(eclipseDir, compXMLDir); |
| try |
| { |
| compUseEmitter.genComponentUseXML(); |
| } |
| catch (IOException ioe) |
| { |
| ioe.printStackTrace(); |
| } |
| } |
| |
| private static void printUsage() |
| { |
| System.out.println("Usage: java org.eclipse.wtp.releng.tools.component.use.ComponentUseEmitter -eclipseDir <eclipseDir> -compXMLDir <compDir> [-options]"); |
| System.out.println(""); |
| System.out.println("\t-eclipseDir\t<eclipseDir>\tspace seperated list of directories containing Eclipse plugins"); |
| System.out.println("\t-compXMLDir\t<compXMLDir>\tdirectory containing component.xml"); |
| System.out.println("\t-compUseDir\t<compUseDir>\toutput directory of component-use.xml"); |
| System.out.println(""); |
| System.out.println("where options include:"); |
| System.out.println(""); |
| System.out.println("\t-include\t<include>\tspace seperated packages to include"); |
| System.out.println("\t-exclude\t<exclude>\tspace seperated packages to exclude"); |
| System.out.println("\t-classRefOnly\t\t\ttreat all violations as class reference"); |
| System.out.println("\t-debug\t\t\t\tgenerate debug information (ex. line numbers)"); |
| } |
| } |