Skip to content

Commit

Permalink
[FIXED JENKINS-12803] support installing plugin without restarting
Browse files Browse the repository at this point in the history
  • Loading branch information
ssogabe committed May 12, 2013
1 parent 2e14968 commit 1932163
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 44 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plugin</artifactId>
<version>1.398</version>
<version>1.447</version>
</parent>

<artifactId>persona</artifactId>
Expand Down
@@ -1,7 +1,7 @@
/*
* The MIT License
*
* Copyright (c) 2010-2012, InfraDNA, Inc., Seiji Sogabe
* Copyright (c) 2010-2013, InfraDNA, Inc., Seiji Sogabe
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -33,6 +33,8 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import jenkins.ExtensionComponentSet;
import jenkins.ExtensionRefreshException;

/**
* @author whren
Expand All @@ -57,4 +59,15 @@ public <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson)
private void parsePersonaInto(Collection<ExtensionComponent<RandomPersona>> result) {
result.add(new ExtensionComponent<RandomPersona>(RandomPersona.create()));
}

@Override
public ExtensionComponentSet refresh() throws ExtensionRefreshException {
return new ExtensionComponentSet() {

@Override
public <T> Collection<ExtensionComponent<T>> find(Class<T> type) {
return Collections.EMPTY_LIST;
}
};
}
}
128 changes: 86 additions & 42 deletions src/main/java/hudson/plugins/persona/xml/XmlPersonaFinder.java
@@ -1,7 +1,7 @@
/*
* The MIT License
*
* Copyright (c) 2010-2012, InfraDNA, Inc., Seiji Sogabe
* Copyright (c) 2010-2013, InfraDNA, Inc., Seiji Sogabe
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -41,6 +41,9 @@
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.ExtensionComponentSet;
import jenkins.ExtensionRefreshException;
import jenkins.model.Jenkins;

/**
* Instantiates {@link XmlBasedPersona}s }by looking at a known location in
Expand All @@ -51,15 +54,43 @@
@Extension
public class XmlPersonaFinder extends ExtensionFinder {

private List<PluginWrapper> parsedWrappers;

@Override
public <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson) {
if ((type != Persona.class) && (type != XmlBasedPersona.class)) {
return Collections.emptyList();
return Collections.EMPTY_LIST;
}

Collection<ExtensionComponent<T>> r = new ArrayList<ExtensionComponent<T>>();

// locate persona from $JENKINS_HOME
loadFromJenkinsHomeTo(hudson, r);

if (parsedWrappers == null) {
// locate personas from plugins
parsedWrappers = hudson.getPluginManager().getPlugins();
r.addAll(new ExtensionComponentSetImpl(parsedWrappers).find(type));
}

List<ExtensionComponent<XmlBasedPersona>> r = new ArrayList<ExtensionComponent<XmlBasedPersona>>();
if (r.isEmpty()) {
LOGGER.warning("[Persona] No Persona found.");
}

return (List) r;
}

@Override
public ExtensionComponentSet refresh() throws ExtensionRefreshException {
List<PluginWrapper> newWrappers = Jenkins.getInstance().getPluginManager().getPlugins();
List<PluginWrapper> delta = new ArrayList<PluginWrapper>(newWrappers);
delta.removeAll(parsedWrappers);
parsedWrappers = newWrappers;
return new ExtensionComponentSetImpl(delta);
}

private <T> void loadFromJenkinsHomeTo(Hudson hudson, Collection<ExtensionComponent<T>> r) {

// locate personas from $HUDSON_HOME or $JENKINS_HOME
try {
FilePath baseDir = new FilePath(hudson.getRootDir());
for (FilePath xml : baseDir.list("persona/**/*.xml")) {
Expand All @@ -76,53 +107,66 @@ public <T> Collection<ExtensionComponent<T>> find(Class<T> type, Hudson hudson)
// all local processing. can't happen
throw new Error(e);
}

// locate personas from plugins
for (PluginWrapper pw : hudson.getPluginManager().getPlugins()) {
try {
FilePath baseDir = new FilePath(new File(pw.baseResourceURL.getFile()));
// support persona-1.0,1,1 style
FilePath personaXML = baseDir.child("persona.xml");
if (personaXML.exists()) {
LOGGER.log(Level.INFO, "loading old style persona from {0}.hpi", pw.getShortName());
URL url = personaXML.toURI().toURL();
parsePersonaInto(url, pw.baseResourceURL, "plugin/" + pw.getShortName(), r);
continue;
}
// support persona-1.2 or newer style
for (FilePath xml : baseDir.list("**/persona.xml")) {
LOGGER.log(Level.INFO, "loading 1.2 or newer style persona from {0}.hpi", pw.getShortName());
URL url = xml.toURI().toURL();
parsePersonaInto(url,
xml.getParent().toURI().toURL(),
"plugin/" + pw.getShortName() + "/" + xml.getParent().getRemote().substring(baseDir.getRemote().length() + 1), r);
}
} catch (RuntimeException e) {
continue; // FilePath#list throws BuildException
} catch (IOException e) {
continue; // no such file
} catch (InterruptedException e) {
// all local processing. can't happen
throw new Error(e);
}
}

if (r.isEmpty()) {
LOGGER.warning("[Persona] No Persona found.");
}

return (List) r;
}

private void parsePersonaInto(URL xml, URL imageBase, String imageBasePath, Collection<ExtensionComponent<XmlBasedPersona>> result) {
private static <T> void parsePersonaInto(URL xml, URL imageBase, String imageBasePath,
Collection<ExtensionComponent<T>> result) {
try {
result.add(new ExtensionComponent<XmlBasedPersona>(XmlBasedPersona.create(xml, imageBase, imageBasePath)));
result.add(new ExtensionComponent(XmlBasedPersona.create(xml, imageBase, imageBasePath)));
} catch (DocumentException e) {
LOGGER.log(Level.SEVERE, "Failed to load a persona from " + xml, e);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to load a persona from " + xml, e);
}
}

private static class ExtensionComponentSetImpl extends ExtensionComponentSet {

private List<PluginWrapper> wrappers;

public ExtensionComponentSetImpl(List<PluginWrapper> wrappers) {
this.wrappers = wrappers;
}

@Override
public <T> Collection<ExtensionComponent<T>> find(Class<T> type) {
Collection<ExtensionComponent<T>> r = new ArrayList<ExtensionComponent<T>>();
if (type != Persona.class && type != XmlBasedPersona.class) {
return r;
}

for (PluginWrapper pw : wrappers) {
try {
FilePath baseDir = new FilePath(new File(pw.baseResourceURL.getFile()));
// support persona-1.0,1,1 style
FilePath personaXML = baseDir.child("persona.xml");
if (personaXML.exists()) {
LOGGER.log(Level.INFO, "loading old style persona from {0}.hpi", pw.getShortName());
URL url = personaXML.toURI().toURL();
parsePersonaInto(url, pw.baseResourceURL, "plugin/" + pw.getShortName(), r);
continue;
}
// support persona-1.2 or newer style
for (FilePath xml : baseDir.list("**/persona.xml")) {
LOGGER.log(Level.INFO, "loading 1.2 or newer style persona from {0}.hpi", pw.getShortName());
URL url = xml.toURI().toURL();
parsePersonaInto(url,
xml.getParent().toURI().toURL(),
"plugin/" + pw.getShortName() + "/" + xml.getParent().getRemote().substring(baseDir.getRemote().length() + 1), r);
}
} catch (RuntimeException e) {
continue; // FilePath#list throws BuildException
} catch (IOException e) {
continue; // no such file
} catch (InterruptedException e) {
// all local processing. can't happen
throw new Error(e);
}
}

return r;
}
}

private static final Logger LOGGER = Logger.getLogger(XmlPersonaFinder.class.getName());
}

0 comments on commit 1932163

Please sign in to comment.