Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More robust AsciDoc serializaion, add logging #19

Merged
merged 3 commits into from
Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/main/java/hudson/MockExtensionLists.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,38 @@
import jenkins.model.Jenkins;

public class MockExtensionLists {
private static Map<String, ExtensionList> extensionLists = new HashMap<String, ExtensionList>();
private static Map<String, ExtensionList<?>> extensionLists = new HashMap<String, ExtensionList<?>>();

public ExtensionList getMockExtensionList(HyperLocalPluginManger hlpm, Jenkins hudson, Class type) {
public ExtensionList<?> getMockExtensionList(HyperLocalPluginManger hlpm, Jenkins hudson, Class<?> type) {
if(extensionLists.get(type.getName()) != null) {
return extensionLists.get(type.getName());
} else {
MockExtensionList mockList = new MockExtensionList(hlpm, hudson, type);
MockExtensionList<?> mockList = new MockExtensionList<>(hlpm, hudson, type);
extensionLists.put(type.getName(), mockList.getMockExtensionList());
return mockList.getMockExtensionList();
}
}

private class MockExtensionList {
ExtensionList mockExtensionList;
private class MockExtensionList<T> {
ExtensionList<T> mockExtensionList;

public MockExtensionList(HyperLocalPluginManger hlpm, Jenkins hudson, Class type) {
ExtensionList realList = ExtensionList.create(hudson, type);
public MockExtensionList(HyperLocalPluginManger hlpm, Jenkins hudson, Class<T> type) {
ExtensionList<T> realList = ExtensionList.create(hudson, type);
mockExtensionList = spy(realList);

doReturn("Locking resources").when(mockExtensionList).getLoadLock();
doAnswer(mockLoad(hlpm)).when(mockExtensionList).load();
}

private <T> Answer<List<ExtensionComponent<T>>> mockLoad(HyperLocalPluginManger hlpm) {
private Answer<List<ExtensionComponent<T>>> mockLoad(HyperLocalPluginManger hlpm) {
return new Answer<List<ExtensionComponent<T>>>() {
public List<ExtensionComponent<T>> answer(InvocationOnMock invocation) throws Throwable {
return hlpm.getPluginStrategy().findComponents(mockExtensionList.extensionType, (Hudson)null);
}
};
}

public ExtensionList getMockExtensionList(){
public ExtensionList<T> getMockExtensionList(){
return mockExtensionList;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Acts as a PluginManager that operates outside the normal startup process of Jenkins. Essentially, this captures the
Expand All @@ -44,6 +45,7 @@
* use calls to Jenkins.
*/
public class HyperLocalPluginManger extends LocalPluginManager{
private static final Logger LOG = Logger.getLogger(HyperLocalPluginManger.class.getName());
private final ModClassicPluginStrategy strategy;
public final UberPlusClassLoader uberPlusClassLoader = new UberPlusClassLoader();
private final boolean checkCycles;
Expand Down Expand Up @@ -126,7 +128,7 @@ public void run(Reactor session1) throws Exception {
private boolean isDuplicate(PluginWrapper p) {
String shortName = p.getShortName();
if (inspectedShortNames.containsKey(shortName)) {
System.out.println("Ignoring "+arc+" because "+inspectedShortNames.get(shortName)+" is already loaded");
LOG.info("Ignoring "+arc+" because "+inspectedShortNames.get(shortName)+" is already loaded");
return true;
}

Expand Down Expand Up @@ -164,7 +166,7 @@ private void addTo(List<PluginWrapper.Dependency> dependencies, List<PluginWrapp
protected void reactOnCycle(PluginWrapper q, List<PluginWrapper> cycle)
throws hudson.util.CyclicGraphDetector.CycleDetectedException {

System.out.println("FATAL: found cycle in plugin dependencies: (root="+q+", deactivating all involved) "+Util.join(cycle," -> "));
LOG.severe("FATAL: found cycle in plugin dependencies: (root="+q+", deactivating all involved) "+Util.join(cycle," -> "));
for (PluginWrapper pluginWrapper : cycle) {
pluginWrapper.setHasCycleDependency(true);
failedPlugins.add(new FailedPlugin(pluginWrapper.getShortName(), new CycleDetectedException(cycle)));
Expand Down Expand Up @@ -205,7 +207,7 @@ public final class UberPlusClassLoader extends ClassLoader {
* Make generated types visible.
* Keyed by the generated class name.
*/
private ConcurrentMap<String, WeakReference<Class>> generatedClasses = new ConcurrentHashMap<String, WeakReference<Class>>();
private ConcurrentMap<String, WeakReference<Class<?>>> generatedClasses = new ConcurrentHashMap<String, WeakReference<Class<?>>>();
/** Cache of loaded, or known to be unloadable, classes. */
private final Map<String,Class<?>> loaded = new HashMap<String,Class<?>>();
private final Map<String, String> byPlugin = new HashMap<String, String>();
Expand All @@ -214,16 +216,16 @@ public UberPlusClassLoader() {
super(PluginManager.class.getClassLoader());
}

public void addNamedClass(String className, Class c) {
generatedClasses.put(className,new WeakReference<Class>(c));
public void addNamedClass(String className, Class<?> c) {
generatedClasses.put(className,new WeakReference<Class<?>>(c));
}

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//likely want to avoid this, but we'll deal with it right now.
WeakReference<Class> wc = generatedClasses.get(name);
WeakReference<Class<?>> wc = generatedClasses.get(name);
if (wc!=null) {
Class c = wc.get();
Class<?> c = wc.get();
if (c!=null) return c;
else generatedClasses.remove(name,wc);
}
Expand Down Expand Up @@ -270,7 +272,7 @@ protected Class<?> findClass(String name) throws ClassNotFoundException {
} else {
for (PluginWrapper p : activePlugins) {
try {
Class c = p.classLoader.loadClass(name);
Class<?> c = p.classLoader.loadClass(name);
synchronized (byPlugin){
byPlugin.put(c.getName(), p.getShortName());
}
Expand Down Expand Up @@ -447,7 +449,7 @@ private <T> Collection<ExtensionComponent<T>> _find(Class<T> type, List<IndexIte
AnnotatedElement e = item.element();
Class<?> extType;
if (e instanceof Class) {
extType = (Class) e;
extType = (Class<?>) e;
} else
if (e instanceof Field) {
extType = ((Field)e).getType();
Expand All @@ -465,20 +467,20 @@ private <T> Collection<ExtensionComponent<T>> _find(Class<T> type, List<IndexIte
} catch (LinkageError|Exception e) {
// sometimes the instantiation fails in an indirect classloading failure,
// which results in a LinkageError
System.out.println("Failed to load "+item.className() + "\n" + e);
LOG.fine("Failed to load "+item.className() + "\n" + e);
}
}

return result;
}

public void scout(Class extensionType, ClassLoader cl) {
public void scout(Class<?> extensionType, ClassLoader cl) {
for (IndexItem<Extension,Object> item : getIndices(cl)) {
try {
AnnotatedElement e = item.element();
Class<?> extType;
if (e instanceof Class) {
extType = (Class) e;
extType = (Class<?>) e;
} else
if (e instanceof Field) {
extType = ((Field)e).getType();
Expand All @@ -490,14 +492,10 @@ public void scout(Class extensionType, ClassLoader cl) {
// according to JDK-4993813 this is the only way to force class initialization
Class.forName(extType.getName(),true,extType.getClassLoader());
} catch (Exception | LinkageError e) {
System.out.println("Failed to scout " + item.className() + "\n" + e);
LOG.fine("Failed to scout " + item.className() + "\n" + e);
}
}
}

private Level logLevel(IndexItem<Extension, Object> item) {
return item.annotation().optional() ? Level.FINE : Level.WARNING;
}
}

/**
Expand All @@ -510,11 +508,11 @@ protected String getPluginNameForDescriptor(Descriptor<?> d) {
try {
uberPlusClassLoader.findClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
LOG.log(Level.WARNING, "Class not found", e);
}
String pluginName = uberPlusClassLoader.getByPlugin().get(className);
if (pluginName == null) {
System.out.println("No plugin found, assuming core: " + className);
LOG.info("No plugin found, assuming core: " + className);
return "core";
}
return pluginName.trim();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
Expand All @@ -46,6 +47,8 @@
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Stream;

import static org.mockito.Mockito.*;
Expand All @@ -54,6 +57,10 @@
* Process and find all the Pipeline steps definied in Jenkins plugins.
*/
public class PipelineStepExtractor {
private static final Logger LOG = Logger.getLogger(PipelineStepExtractor.class.getName());
static {
System.setProperty("java.util.logging.SimpleFormatter.format","[%4$-7s] %5$s %6$s%n");
}
@Option(name="-homeDir",usage="Root directory of the plugin folder. This serves as the root directory of the PluginManager.")
public String homeDir = null;

Expand All @@ -69,18 +76,16 @@ public static void main(String[] args){
CmdLineParser p = new CmdLineParser(pse);
p.parseArgument(args);
} catch(Exception ex){
ex.printStackTrace();
System.out.println("There was an error with parsing the commands, defaulting to the home directory.");
LOG.log(Level.SEVERE, "There was an error with parsing the commands, defaulting to the home directory.", ex);
}
try{
Map<String, Map<String, List<QuasiDescriptor>>> steps = pse.findSteps();
pse.generateAscii(steps, pse.pluginManager);
pse.generateDeclarativeAscii();
} catch(Exception ex){
ex.printStackTrace();
System.out.println("Error in finding all the steps");
LOG.log(Level.SEVERE, "Error in finding all the steps", ex);
}
System.out.println("CONVERSION COMPLETE!");
LOG.info("CONVERSION COMPLETE!");
System.exit(0); //otherwise environment hangs around
}

Expand Down Expand Up @@ -128,8 +133,7 @@ public Map<String, Map<String, List<QuasiDescriptor>>> findSteps(){
completeListing.put(opt, exists);
}
} catch (Exception ex){
ex.printStackTrace();
//log exception, job essentially fails
LOG.log(Level.SEVERE, "Step generation failed", ex);
}

return completeListing;
Expand Down Expand Up @@ -206,7 +210,7 @@ protected void runTask(Task task) throws Exception {
new InitReactorRunner() {
@Override
protected void onInitMilestoneAttained(InitMilestone milestone) {
System.out.println("init milestone attained " + milestone);
LOG.info("init milestone attained " + milestone);
}
}.run(reactor);
}
Expand Down Expand Up @@ -239,7 +243,7 @@ public void generateAscii(Map<String, Map<String, List<QuasiDescriptor>>> allSte
allAscii.mkdirs();
String allAsciiPath = allAscii.getAbsolutePath();
for(String plugin : allSteps.keySet()){
System.out.println("processing " + plugin);
LOG.info("processing " + plugin);
Map<String, List<QuasiDescriptor>> byPlugin = allSteps.get(plugin);
PluginWrapper thePlugin = pluginManager.getPlugin(plugin);
String displayName = thePlugin == null ? "Jenkins Core" : thePlugin.getDisplayName();
Expand All @@ -248,8 +252,7 @@ public void generateAscii(Map<String, Map<String, List<QuasiDescriptor>>> allSte
try {
FileUtils.writeStringToFile(new File(allAsciiPath, plugin + ".adoc"), whole9yards, StandardCharsets.UTF_8);
} catch (Exception ex){
ex.printStackTrace();
System.out.println("Error generating plugin file for " + plugin + ". Skip.");
LOG.log(Level.SEVERE, "Error generating plugin file for " + plugin + ". Skip.", ex);
//continue to next plugin
}
}
Expand All @@ -268,22 +271,21 @@ public void generateDeclarativeAscii() {
Map<Class<? extends Descriptor>, Predicate<Descriptor>> filters = getDeclarativeFilters();

for (Map.Entry<String,List<Class<? extends Descriptor>>> entry : getDeclarativeDirectives().entrySet()) {
System.out.println("Generating docs for directive " + entry.getKey());
LOG.info("Generating docs for directive " + entry.getKey());
Map<String, List<Descriptor>> pluginDescMap = new HashMap<>();

for (Class<? extends Descriptor> d : entry.getValue()) {
Predicate<Descriptor> filter = filters.get(d);
System.out.println(" - Loading descriptors of type " + d.getSimpleName() + " with filter: " + (filter != null));
LOG.info(" - Loading descriptors of type " + d.getSimpleName() + " with filter: " + (filter != null));
pluginDescMap = processDescriptors(d, pluginDescMap, filter);
}

String whole9yards = ToAsciiDoc.generateDirectiveHelp(entry.getKey(), pluginDescMap, true);

try{
FileUtils.writeStringToFile(new File(declPath, entry.getKey() + ".adoc"), whole9yards, StandardCharsets.UTF_8);
} catch (Exception ex){
ex.printStackTrace();
System.out.println("Error generating directive file for " + entry.getKey() + ". Skip.");
} catch (Exception ex) {
LOG.log(Level.SEVERE, "Error generating directive file for " + entry.getKey() + ". Skip.", ex);
//continue to next directive
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,15 @@
import java.util.Optional;
import java.util.Set;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

//fake out unit tests
import hudson.Main;

public class ToAsciiDoc {
private static final Logger LOG = Logger.getLogger(ToAsciiDoc.class.getName());
/**
* Keeps track of nested {@link DescribableModel#getType()} to avoid recursion.
*/
Expand Down Expand Up @@ -81,6 +84,7 @@ private static String describeType(ParameterType type) throws Exception {
}
} else if (type instanceof ErrorType) { //Shouldn't hit this; open a ticket
Exception x = ((ErrorType) type).getError();
LOG.log(Level.FINE, "Encountered ErrorType object with exception:" + x);
if(x instanceof NoStaplerConstructorException || x instanceof UnsupportedOperationException) {
String msg = x.toString();
typeInfo.append("<code>").append(msg.substring(msg.lastIndexOf(" ")).trim()).append("</code>\n");
Expand All @@ -99,8 +103,13 @@ private static String generateAttrHelp(DescribableParameter param) throws Except
if (help != null && !help.equals("")) {
attrHelp.append(helpify(help)).append("\n");
}
ParameterType type = param.getType();
attrHelp.append("<ul>").append(describeType(type)).append("</ul>");
try {
String typeDesc = describeType(param.getType());
attrHelp.append("<ul>").append(typeDesc).append("</ul>");
} catch (RuntimeException | Error ex) {
LOG.log(Level.WARNING, "Restricted description of attribute "
+ param.getName(), ex);
}
return attrHelp.toString();
}

Expand Down Expand Up @@ -164,7 +173,7 @@ public static String generateStepHelp(QuasiDescriptor d){
}
} catch (Exception | Error ex) {
mkDesc.append("<code>").append(ex).append("</code>");
System.out.println("Description of " + d.real.clazz + " skipped, encountered " + ex);
LOG.log(Level.SEVERE, "Description of " + d.real.clazz + " skipped, encountered ", ex);
}
return mkDesc.append("\n\n\n++++\n").toString();
}
Expand All @@ -174,7 +183,7 @@ private static void appendSimpleStepDescription(StringBuilder mkDesc, Class<?> c
mkDesc.append(generateHelp(new DescribableModel<>(clazz), true));
} catch (Exception ex) {
mkDesc.append(getHelp("help.html", clazz));
System.out.println("Description of " + clazz + " restricted, encountered " + ex);
LOG.log(Level.WARNING, "Description of " + clazz + " restricted, encountered ", ex);
}
}

Expand Down Expand Up @@ -207,14 +216,10 @@ private static String generateDescribableHelp(Descriptor<?> d) {
StringBuilder mkDesc = new StringBuilder(header(3)).append(" `").append(symbols.iterator().next()).append("`: ").append(d.getDisplayName()).append("\n");
try {
mkDesc.append(generateHelp(new DescribableModel<>(d.clazz), true)).append("\n\n");
} catch (Exception ex) {
ex.printStackTrace();
} catch (Exception | Error ex) {
LOG.log(Level.SEVERE, "Problem generating help for descriptor", ex);
// backtick-plus for safety - monospace literal string
mkDesc.append("`+").append(ex).append("+`\n\n");
} catch (Error err) {
err.printStackTrace();
// backtick-plus for safety - monospace literal string
mkDesc.append("`+").append(err).append("+`\n\n");
}
return mkDesc.toString();
} else {
Expand Down